diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -1512,7 +1512,7 @@ return (ENOENT); if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) && - !k->wk_cipher->ic_encap(k, m0)) + !k->wk_cipher->ic_encap(k, ni, m0)) return (ENOBUFS); wh = mtod(m0, struct ieee80211_frame *); @@ -1658,7 +1658,7 @@ return (ENOENT); } if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) && - !k->wk_cipher->ic_encap(k, m0)) { + !k->wk_cipher->ic_encap(k, ni, m0)) { m_freem(m0); return (ENOBUFS); } diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h --- a/sys/net80211/ieee80211_crypto.h +++ b/sys/net80211/ieee80211_crypto.h @@ -216,8 +216,8 @@ void (*ic_detach)(struct ieee80211_key *); int (*ic_setkey)(struct ieee80211_key *); void (*ic_setiv)(struct ieee80211_key *, uint8_t *); - int (*ic_encap)(struct ieee80211_key *, struct mbuf *); - int (*ic_decap)(struct ieee80211_key *, struct mbuf *, int); + int (*ic_encap)(struct ieee80211_key *, struct ieee80211_node *, struct mbuf *); + int (*ic_decap)(struct ieee80211_key *, struct ieee80211_node *, struct mbuf *, int); int (*ic_enmic)(struct ieee80211_key *, struct mbuf *, int); int (*ic_demic)(struct ieee80211_key *, struct mbuf *, int); }; @@ -234,6 +234,8 @@ const struct ieee80211_key *k); int ieee80211_crypto_get_key_igtk_idx(const struct ieee80211vap *, const struct ieee80211_key *k); +int ieee80211_crypto_get_key_igtk_idx(const struct ieee80211vap *, + const struct ieee80211_key *k); uint8_t ieee80211_crypto_get_keyid(struct ieee80211vap *vap, struct ieee80211_key *k); struct ieee80211_key *ieee80211_crypto_get_txkey(struct ieee80211_node *, 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 @@ -706,7 +706,7 @@ if ((k = ieee80211_crypto_get_txkey(ni, m)) != NULL) { cip = k->wk_cipher; - return (cip->ic_encap(k, m) ? k : NULL); + return (cip->ic_encap(k, ni, m) ? k : NULL); } return NULL; @@ -795,7 +795,7 @@ * If we fail then don't return the key - return NULL * and an error. */ - if (cip->ic_decap(k, m, hdrlen)) { + if (cip->ic_decap(k, ni, m, hdrlen)) { /* success */ *key = k; return (1); 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 @@ -64,8 +64,10 @@ static void ccmp_detach(struct ieee80211_key *); static int ccmp_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_encap(struct ieee80211_key *, struct ieee80211_node *, + struct mbuf *); +static int ccmp_decap(struct ieee80211_key *, struct ieee80211_node *, + struct mbuf *, int); static int ccmp_enmic(struct ieee80211_key *, struct mbuf *, int); static int ccmp_demic(struct ieee80211_key *, struct mbuf *, int); @@ -87,9 +89,10 @@ .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); +static int ccmp_encrypt(struct ieee80211_key *, struct ieee80211_node *, + struct mbuf *, int hdrlen); +static int ccmp_decrypt(struct ieee80211_key *, struct ieee80211_node *, + u_int64_t pn, struct mbuf *, int hdrlen); /* number of references from net80211 layer */ static int nrefs = 0; @@ -161,7 +164,8 @@ * Add privacy headers appropriate for the specified key. */ static int -ccmp_encap(struct ieee80211_key *k, struct mbuf *m) +ccmp_encap(struct ieee80211_key *k, struct ieee80211_node *ni, + struct mbuf *m) { const struct ieee80211_frame *wh; struct ccmp_ctx *ctx = k->wk_private; @@ -201,7 +205,7 @@ * Finally, do software encrypt if needed. */ if ((k->wk_flags & IEEE80211_KEY_SWENCRYPT) && - !ccmp_encrypt(k, m, hdrlen)) + !ccmp_encrypt(k, ni, m, hdrlen)) return 0; return 1; @@ -231,7 +235,8 @@ * is also verified. */ static int -ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) +ccmp_decap(struct ieee80211_key *k, struct ieee80211_node *ni, struct mbuf *m, + int hdrlen) { const struct ieee80211_rx_stats *rxs; struct ccmp_ctx *ctx = k->wk_private; @@ -280,7 +285,7 @@ * decryption work. */ if ((k->wk_flags & IEEE80211_KEY_SWDECRYPT) && - !ccmp_decrypt(k, pn, m, hdrlen)) + !ccmp_decrypt(k, ni, pn, m, hdrlen)) return 0; finish: @@ -342,16 +347,16 @@ static void ccmp_init_blocks(rijndael_ctx *ctx, struct ieee80211_frame *wh, - u_int64_t pn, size_t dlen, + u_int64_t pn, size_t dlen, bool is_mfp, 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) - /* CCM Initial Block: * Flag (Include authentication header, M=3 (8-octet MIC), * L=1 (2-octet Dlen)) - * Nonce: 0x00 | A2 | PN + * Nonce: Nonce flags | A2 | PN + * Nonce Flags: 0..3: priority, 4: MFP mgmt, 5-7: zero * Dlen */ b0[0] = 0x59; /* NB: b0[1] set below */ @@ -398,7 +403,11 @@ (struct ieee80211_qosframe_addr4 *) wh; aad[30] = qwh4->i_qos[0] & 0x0f;/* just priority bits */ aad[31] = 0; - b0[1] = aad[30]; + /* Set priority */ + b0[1] = aad[30] & 0xf; + /* Set MFP bit if needed */ + if (is_mfp) + b0[1] |= 0x10; aad[1] = 22 + IEEE80211_ADDR_LEN + 2; } else { *(uint16_t *)&aad[30] = 0; @@ -446,7 +455,8 @@ } while (0) static int -ccmp_encrypt(struct ieee80211_key *key, struct mbuf *m0, int hdrlen) +ccmp_encrypt(struct ieee80211_key *key, struct ieee80211_node *ni, + struct mbuf *m0, int hdrlen) { struct ccmp_ctx *ctx = key->wk_private; struct ieee80211_frame *wh; @@ -455,13 +465,15 @@ uint8_t aad[2 * AES_BLOCK_LEN], b0[AES_BLOCK_LEN], b[AES_BLOCK_LEN], e[AES_BLOCK_LEN], s0[AES_BLOCK_LEN]; uint8_t *pos; + bool is_mfp = false; 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, is_mfp, b0, aad, b, s0); i = 1; pos = mtod(m, uint8_t *) + hdrlen + ccmp.ic_header; @@ -591,7 +603,8 @@ } while (0) static int -ccmp_decrypt(struct ieee80211_key *key, u_int64_t pn, struct mbuf *m, int hdrlen) +ccmp_decrypt(struct ieee80211_key *key, struct ieee80211_node *ni, + u_int64_t pn, struct mbuf *m, int hdrlen) { struct ccmp_ctx *ctx = key->wk_private; struct ieee80211vap *vap = ctx->cc_vap; @@ -603,12 +616,14 @@ int i; uint8_t *pos; u_int space; + bool is_mfp = false; 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); + + ccmp_init_blocks(&ctx->cc_aes, wh, pn, data_len, is_mfp, 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); diff --git a/sys/net80211/ieee80211_crypto_none.c b/sys/net80211/ieee80211_crypto_none.c --- a/sys/net80211/ieee80211_crypto_none.c +++ b/sys/net80211/ieee80211_crypto_none.c @@ -50,8 +50,10 @@ static void none_detach(struct ieee80211_key *); static int none_setkey(struct ieee80211_key *); static void none_setiv(struct ieee80211_key *, uint8_t *); -static int none_encap(struct ieee80211_key *, struct mbuf *); -static int none_decap(struct ieee80211_key *, struct mbuf *, int); +static int none_encap(struct ieee80211_key *, struct ieee80211_node *, + struct mbuf *); +static int none_decap(struct ieee80211_key *, struct ieee80211_node *, + struct mbuf *, int); static int none_enmic(struct ieee80211_key *, struct mbuf *, int); static int none_demic(struct ieee80211_key *, struct mbuf *, int); @@ -96,7 +98,7 @@ } static int -none_encap(struct ieee80211_key *k, struct mbuf *m) +none_encap(struct ieee80211_key *k, struct ieee80211_node *ni, struct mbuf *m) { struct ieee80211vap *vap = k->wk_private; #ifdef IEEE80211_DEBUG @@ -117,7 +119,8 @@ } static int -none_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) +none_decap(struct ieee80211_key *k, struct ieee80211_node *ni, struct mbuf *m, + int hdrlen) { struct ieee80211vap *vap = k->wk_private; #ifdef IEEE80211_DEBUG diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c --- a/sys/net80211/ieee80211_crypto_tkip.c +++ b/sys/net80211/ieee80211_crypto_tkip.c @@ -55,9 +55,11 @@ static void tkip_detach(struct ieee80211_key *); static int tkip_setkey(struct ieee80211_key *); static void tkip_setiv(struct ieee80211_key *, uint8_t *); -static int tkip_encap(struct ieee80211_key *, struct mbuf *); +static int tkip_encap(struct ieee80211_key *, struct ieee80211_node *, + struct mbuf *); static int tkip_enmic(struct ieee80211_key *, struct mbuf *, int); -static int tkip_decap(struct ieee80211_key *, struct mbuf *, int); +static int tkip_decap(struct ieee80211_key *, struct ieee80211_node *, + struct mbuf *, int); static int tkip_demic(struct ieee80211_key *, struct mbuf *, int); static const struct ieee80211_cipher tkip = { @@ -173,7 +175,7 @@ * Add privacy headers and do any s/w encryption required. */ static int -tkip_encap(struct ieee80211_key *k, struct mbuf *m) +tkip_encap(struct ieee80211_key *k, struct ieee80211_node *ni, struct mbuf *m) { struct tkip_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->tc_vap; @@ -285,7 +287,8 @@ * the specified key. */ static int -tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) +tkip_decap(struct ieee80211_key *k, struct ieee80211_node *ni, struct mbuf *m, + int hdrlen) { const struct ieee80211_rx_stats *rxs; struct tkip_ctx *ctx = k->wk_private; diff --git a/sys/net80211/ieee80211_crypto_wep.c b/sys/net80211/ieee80211_crypto_wep.c --- a/sys/net80211/ieee80211_crypto_wep.c +++ b/sys/net80211/ieee80211_crypto_wep.c @@ -51,8 +51,10 @@ static void wep_detach(struct ieee80211_key *); static int wep_setkey(struct ieee80211_key *); static void wep_setiv(struct ieee80211_key *, uint8_t *); -static int wep_encap(struct ieee80211_key *, struct mbuf *); -static int wep_decap(struct ieee80211_key *, struct mbuf *, int); +static int wep_encap(struct ieee80211_key *, struct ieee80211_node *, + struct mbuf *); +static int wep_decap(struct ieee80211_key *, struct ieee80211_node *, + struct mbuf *, int); static int wep_enmic(struct ieee80211_key *, struct mbuf *, int); static int wep_demic(struct ieee80211_key *, struct mbuf *, int); @@ -177,7 +179,7 @@ * Add privacy headers appropriate for the specified key. */ static int -wep_encap(struct ieee80211_key *k, struct mbuf *m) +wep_encap(struct ieee80211_key *k, struct ieee80211_node *ni, struct mbuf *m) { struct wep_ctx *ctx = k->wk_private; struct ieee80211com *ic = ctx->wc_ic; @@ -236,7 +238,8 @@ * the specified key. */ static int -wep_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen) +wep_decap(struct ieee80211_key *k, struct ieee80211_node *ni, struct mbuf *m, + int hdrlen) { struct wep_ctx *ctx = k->wk_private; struct ieee80211vap *vap = ctx->wc_vap;