Page MenuHomeFreeBSD

D44921.id137618.diff
No OneTemporary

D44921.id137618.diff

diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -153,7 +153,8 @@
* hardware cipher list (ic_cryptocaps.)
*/
ic->ic_sw_cryptocaps = IEEE80211_CRYPTO_WEP |
- IEEE80211_CRYPTO_TKIP | IEEE80211_CRYPTO_AES_CCM;
+ IEEE80211_CRYPTO_TKIP | IEEE80211_CRYPTO_AES_CCM |
+ IEEE80211_CRYPTO_AES_CCM_256;
/*
* Default set of net80211 supported key management types.
diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c
--- a/sys/net80211/ieee80211_crypto_ccmp.c
+++ b/sys/net80211/ieee80211_crypto_ccmp.c
@@ -54,6 +54,9 @@
#define AES_BLOCK_LEN 16
+#define CCMP_128_MIC_LEN 8
+#define CCMP_256_MIC_LEN 16
+
struct ccmp_ctx {
struct ieee80211vap *cc_vap; /* for diagnostics+statistics */
struct ieee80211com *cc_ic;
@@ -63,18 +66,19 @@
static void *ccmp_attach(struct ieee80211vap *, struct ieee80211_key *);
static void ccmp_detach(struct ieee80211_key *);
static int ccmp_setkey(struct ieee80211_key *);
+static int ccmp_256_setkey(struct ieee80211_key *);
static void ccmp_setiv(struct ieee80211_key *, uint8_t *);
static int ccmp_encap(struct ieee80211_key *, struct mbuf *);
static int ccmp_decap(struct ieee80211_key *, struct mbuf *, int);
static int ccmp_enmic(struct ieee80211_key *, struct mbuf *, int);
static int ccmp_demic(struct ieee80211_key *, struct mbuf *, int);
-static const struct ieee80211_cipher ccmp = {
+static const struct ieee80211_cipher ccmp_128 = {
.ic_name = "AES-CCM",
.ic_cipher = IEEE80211_CIPHER_AES_CCM,
.ic_header = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
IEEE80211_WEP_EXTIVLEN,
- .ic_trailer = IEEE80211_WEP_MICLEN,
+ .ic_trailer = CCMP_128_MIC_LEN,
.ic_miclen = 0,
.ic_attach = ccmp_attach,
.ic_detach = ccmp_detach,
@@ -86,6 +90,23 @@
.ic_demic = ccmp_demic,
};
+static const struct ieee80211_cipher ccmp_256 = {
+ .ic_name = "AES-CCM-256",
+ .ic_cipher = IEEE80211_CIPHER_AES_CCM_256,
+ .ic_header = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
+ IEEE80211_WEP_EXTIVLEN,
+ .ic_trailer = CCMP_256_MIC_LEN,
+ .ic_miclen = 0,
+ .ic_attach = ccmp_attach,
+ .ic_detach = ccmp_detach,
+ .ic_setkey = ccmp_256_setkey,
+ .ic_setiv = ccmp_setiv,
+ .ic_encap = ccmp_encap,
+ .ic_decap = ccmp_decap,
+ .ic_enmic = ccmp_enmic,
+ .ic_demic = ccmp_demic,
+};
+
static int ccmp_encrypt(struct ieee80211_key *, struct mbuf *, int hdrlen);
static int ccmp_decrypt(struct ieee80211_key *, u_int64_t pn,
struct mbuf *, int hdrlen);
@@ -120,6 +141,28 @@
nrefs--; /* NB: we assume caller locking */
}
+static int
+ccmp_get_trailer_len(struct ieee80211_key *k)
+{
+ return k->wk_cipher->ic_trailer;
+}
+
+static int
+ccmp_get_header_len(struct ieee80211_key *k)
+{
+ return k->wk_cipher->ic_header;
+}
+
+static int
+ccmp_get_ccm_m(struct ieee80211_key *k)
+{
+ if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM)
+ return 8;
+ if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_AES_CCM_256)
+ return 16;
+ return 8; /* XXX default */
+}
+
static int
ccmp_setkey(struct ieee80211_key *k)
{
@@ -136,6 +179,22 @@
return 1;
}
+static int
+ccmp_256_setkey(struct ieee80211_key *k)
+{
+ struct ccmp_ctx *ctx = k->wk_private;
+
+ if (k->wk_keylen != (256/NBBY)) {
+ IEEE80211_DPRINTF(ctx->cc_vap, IEEE80211_MSG_CRYPTO,
+ "%s: Invalid key length %u, expecting %u\n",
+ __func__, k->wk_keylen, 256/NBBY);
+ return 0;
+ }
+ if (k->wk_flags & IEEE80211_KEY_SWENCRYPT)
+ rijndael_set_key(&ctx->cc_aes, k->wk_key, k->wk_keylen*NBBY);
+ return 1;
+}
+
static void
ccmp_setiv(struct ieee80211_key *k, uint8_t *ivp)
{
@@ -187,11 +246,11 @@
/*
* Copy down 802.11 header and add the IV, KeyID, and ExtIV.
*/
- M_PREPEND(m, ccmp.ic_header, IEEE80211_M_NOWAIT);
+ M_PREPEND(m, ccmp_get_header_len(k), IEEE80211_M_NOWAIT);
if (m == NULL)
return 0;
ivp = mtod(m, uint8_t *);
- ovbcopy(ivp + ccmp.ic_header, ivp, hdrlen);
+ ovbcopy(ivp + ccmp_get_header_len(k), ivp, hdrlen);
ivp += hdrlen;
ccmp_setiv(k, ivp);
@@ -287,16 +346,16 @@
* Copy up 802.11 header and strip crypto bits.
*/
if (! ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
- ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + ccmp.ic_header,
+ ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + ccmp_get_header_len(k),
hdrlen);
- m_adj(m, ccmp.ic_header);
+ m_adj(m, ccmp_get_header_len(k));
}
/*
* XXX TODO: see if MMIC_STRIP also covers CCMP MIC trailer.
*/
if (! ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP)))
- m_adj(m, -ccmp.ic_trailer);
+ m_adj(m, -ccmp_get_trailer_len(k));
/*
* Ok to update rsc now.
@@ -341,18 +400,27 @@
static void
ccmp_init_blocks(rijndael_ctx *ctx, struct ieee80211_frame *wh,
+ uint32_t m,
u_int64_t pn, size_t dlen,
uint8_t b0[AES_BLOCK_LEN], uint8_t aad[2 * AES_BLOCK_LEN],
uint8_t auth[AES_BLOCK_LEN], uint8_t s0[AES_BLOCK_LEN])
{
#define IS_QOS_DATA(wh) IEEE80211_QOS_HAS_SEQ(wh)
+ /*
+ * Map M parameter to encoding
+ * (RFC3610, Section 2 (CCM Mode Specification)
+ */
+ m = (m - 2) / 2;
+
/* CCM Initial Block:
- * Flag (Include authentication header, M=3 (8-octet MIC),
- * L=1 (2-octet Dlen))
+ * Flag (Include authentication header, M=8 (8-octet MIC),
+ * L=2 (2-octet Dlen))
* Nonce: 0x00 | A2 | PN
* Dlen */
- b0[0] = 0x59;
+ /* XXX 0x40 = Adata, 0x01 = L=2, 0x18 = M=8 */
+ /* M=3, L=2, ADATA = 0x59 */
+ b0[0] = 0x40 | 0x01 | (m << 3);
/* NB: b0[1] set below */
IEEE80211_ADDR_COPY(b0 + 2, wh->i_addr2);
b0[8] = pn >> 40;
@@ -458,14 +526,16 @@
ctx->cc_vap->iv_stats.is_crypto_ccmp++;
wh = mtod(m, struct ieee80211_frame *);
- data_len = m->m_pkthdr.len - (hdrlen + ccmp.ic_header);
- ccmp_init_blocks(&ctx->cc_aes, wh, key->wk_keytsc,
- data_len, b0, aad, b, s0);
+ data_len = m->m_pkthdr.len - (hdrlen + ccmp_get_header_len(key));
+ ccmp_init_blocks(&ctx->cc_aes, wh,
+ ccmp_get_ccm_m(key),
+ key->wk_keytsc,
+ data_len, b0, aad, b, s0);
i = 1;
- pos = mtod(m, uint8_t *) + hdrlen + ccmp.ic_header;
+ pos = mtod(m, uint8_t *) + hdrlen + ccmp_get_header_len(key);
/* NB: assumes header is entirely in first mbuf */
- space = m->m_len - (hdrlen + ccmp.ic_header);
+ space = m->m_len - (hdrlen + ccmp_get_header_len(key));
for (;;) {
if (space > data_len)
space = data_len;
@@ -573,8 +643,8 @@
}
done:
/* tack on MIC */
- xor_block(b, s0, ccmp.ic_trailer);
- return m_append(m0, ccmp.ic_trailer, b);
+ xor_block(b, s0, ccmp_get_trailer_len(key));
+ return m_append(m0, ccmp_get_trailer_len(key), b);
}
#undef CCMP_ENCRYPT
@@ -606,14 +676,18 @@
ctx->cc_vap->iv_stats.is_crypto_ccmp++;
wh = mtod(m, struct ieee80211_frame *);
- data_len = m->m_pkthdr.len - (hdrlen + ccmp.ic_header + ccmp.ic_trailer);
- ccmp_init_blocks(&ctx->cc_aes, wh, pn, data_len, b0, aad, a, b);
- m_copydata(m, m->m_pkthdr.len - ccmp.ic_trailer, ccmp.ic_trailer, mic);
- xor_block(mic, b, ccmp.ic_trailer);
+ data_len = m->m_pkthdr.len - (hdrlen + ccmp_get_header_len(key)
+ + ccmp_get_trailer_len(key));
+ ccmp_init_blocks(&ctx->cc_aes, wh,
+ ccmp_get_ccm_m(key),
+ pn, data_len, b0, aad, a, b);
+ m_copydata(m, m->m_pkthdr.len - ccmp_get_trailer_len(key),
+ ccmp_get_trailer_len(key), mic);
+ xor_block(mic, b, ccmp_get_trailer_len(key));
i = 1;
- pos = mtod(m, uint8_t *) + hdrlen + ccmp.ic_header;
- space = m->m_len - (hdrlen + ccmp.ic_header);
+ pos = mtod(m, uint8_t *) + hdrlen + ccmp_get_header_len(key);
+ space = m->m_len - (hdrlen + ccmp_get_header_len(key));
for (;;) {
if (space > data_len)
space = data_len;
@@ -665,7 +739,7 @@
space = m->m_len;
}
}
- if (memcmp(mic, a, ccmp.ic_trailer) != 0) {
+ if (memcmp(mic, a, ccmp_get_trailer_len(key)) != 0) {
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
"%s", "AES-CCM decrypt failed; MIC mismatch");
vap->iv_stats.is_rx_ccmpmic++;
@@ -678,4 +752,5 @@
/*
* Module glue.
*/
-IEEE80211_CRYPTO_MODULE(ccmp, 1);
+IEEE80211_CRYPTO_MODULE(ccmp_128, 1);
+IEEE80211_CRYPTO_MODULE_ADD(ccmp_256, 1);
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -1385,6 +1385,9 @@
case RSN_SEL(RSN_CSE_CCMP):
*cipher = IEEE80211_CIPHER_AES_CCM;
break;
+ case RSN_SEL(RSN_CSE_CCMP_256):
+ *cipher = IEEE80211_CIPHER_AES_CCM_256;
+ break;
case RSN_SEL(RSN_CSE_WRAP):
*cipher = IEEE80211_CIPHER_AES_OCB;
break;
@@ -1500,8 +1503,10 @@
frm += 4, len -= 4;
}
- if (w & (1 << IEEE80211_CIPHER_AES_CCM))
- rsn->rsn_ucastcipher = IEEE80211_CIPHER_AES_CCM;
+ if (w & (1 << IEEE80211_CIPHER_AES_CCM_256))
+ rsn->rsn_ucastcipher = IEEE80211_CIPHER_AES_CCM_256;
+ else if (w & (1 << IEEE80211_CIPHER_AES_CCM))
+ rsn->rsn_ucastcipher = IEEE80211_CIPHER_AES_CCM;
else if (w & (1 << IEEE80211_CIPHER_AES_OCB))
rsn->rsn_ucastcipher = IEEE80211_CIPHER_AES_OCB;
else if (w & (1 << IEEE80211_CIPHER_TKIP))

File Metadata

Mime Type
text/plain
Expires
Thu, May 1, 9:54 PM (8 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17891425
Default Alt Text
D44921.id137618.diff (8 KB)

Event Timeline