Index: head/sys/net80211/ieee80211_crypto.h =================================================================== --- head/sys/net80211/ieee80211_crypto.h +++ head/sys/net80211/ieee80211_crypto.h @@ -73,19 +73,25 @@ struct ieee80211_key { uint8_t wk_keylen; /* key length in bytes */ - uint8_t wk_pad; - uint16_t wk_flags; -#define IEEE80211_KEY_XMIT 0x0001 /* key used for xmit */ -#define IEEE80211_KEY_RECV 0x0002 /* key used for recv */ -#define IEEE80211_KEY_GROUP 0x0004 /* key used for WPA group operation */ -#define IEEE80211_KEY_NOREPLAY 0x0008 /* ignore replay failures */ -#define IEEE80211_KEY_SWENCRYPT 0x0010 /* host-based encrypt */ -#define IEEE80211_KEY_SWDECRYPT 0x0020 /* host-based decrypt */ -#define IEEE80211_KEY_SWENMIC 0x0040 /* host-based enmic */ -#define IEEE80211_KEY_SWDEMIC 0x0080 /* host-based demic */ -#define IEEE80211_KEY_DEVKEY 0x0100 /* device key request completed */ -#define IEEE80211_KEY_CIPHER0 0x1000 /* cipher-specific action 0 */ -#define IEEE80211_KEY_CIPHER1 0x2000 /* cipher-specific action 1 */ + uint8_t wk_pad; /* .. some drivers use this. Fix that. */ + uint8_t wk_pad1[2]; + uint32_t wk_flags; +#define IEEE80211_KEY_XMIT 0x00000001 /* key used for xmit */ +#define IEEE80211_KEY_RECV 0x00000002 /* key used for recv */ +#define IEEE80211_KEY_GROUP 0x00000004 /* key used for WPA group operation */ +#define IEEE80211_KEY_NOREPLAY 0x00000008 /* ignore replay failures */ +#define IEEE80211_KEY_SWENCRYPT 0x00000010 /* host-based encrypt */ +#define IEEE80211_KEY_SWDECRYPT 0x00000020 /* host-based decrypt */ +#define IEEE80211_KEY_SWENMIC 0x00000040 /* host-based enmic */ +#define IEEE80211_KEY_SWDEMIC 0x00000080 /* host-based demic */ +#define IEEE80211_KEY_DEVKEY 0x00000100 /* device key request completed */ +#define IEEE80211_KEY_CIPHER0 0x00001000 /* cipher-specific action 0 */ +#define IEEE80211_KEY_CIPHER1 0x00002000 /* cipher-specific action 1 */ +#define IEEE80211_KEY_NOIV 0x00004000 /* don't insert IV/MIC for !mgmt */ +#define IEEE80211_KEY_NOIVMGT 0x00008000 /* don't insert IV/MIC for mgmt */ +#define IEEE80211_KEY_NOMIC 0x00010000 /* don't insert MIC for !mgmt */ +#define IEEE80211_KEY_NOMICMGT 0x00020000 /* don't insert MIC for mgmt */ + ieee80211_keyix wk_keyix; /* h/w key index */ ieee80211_keyix wk_rxkeyix; /* optional h/w rx key index */ uint8_t wk_key[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE]; @@ -203,18 +209,8 @@ struct mbuf *); struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *, struct mbuf *, int); - -/* - * Check and remove any MIC. - */ -static __inline int -ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k, - struct mbuf *m, int force) -{ - const struct ieee80211_cipher *cip = k->wk_cipher; - return (cip->ic_miclen > 0 ? cip->ic_demic(k, m, force) : 1); -} - +int ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k, + struct mbuf *, int); /* * Add any MIC. */ Index: head/sys/net80211/ieee80211_crypto.c =================================================================== --- head/sys/net80211/ieee80211_crypto.c +++ head/sys/net80211/ieee80211_crypto.c @@ -633,6 +633,61 @@ #undef IEEE80211_WEP_HDRLEN } + +/* + * Check and remove any MIC. + */ +int +ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k, + struct mbuf *m, int force) +{ + const struct ieee80211_cipher *cip; + const struct ieee80211_rx_stats *rxs; + struct ieee80211_frame *wh; + + rxs = ieee80211_get_rx_params_ptr(m); + wh = mtod(m, struct ieee80211_frame *); + + /* + * Handle demic / mic errors from hardware-decrypted offload devices. + */ + if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) { + if (rxs->c_pktflags & IEEE80211_RX_F_FAIL_MIC) { + /* + * Hardware has said MIC failed. We don't care about + * whether it was stripped or not. + * + * Eventually - teach the demic methods in crypto + * modules to handle a NULL key and not to dereference + * it. + */ + ieee80211_notify_michael_failure(vap, wh, -1); + return (0); + } + + if (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP) { + /* + * Hardware has decrypted and not indicated a + * MIC failure and has stripped the MIC. + * We may not have a key, so for now just + * return OK. + */ + return (1); + } + } + + /* + * If we don't have a key at this point then we don't + * have to demic anything. + */ + if (k == NULL) + return (1); + + cip = k->wk_cipher; + return (cip->ic_miclen > 0 ? cip->ic_demic(k, m, force) : 1); +} + + static void load_ucastkey(void *arg, struct ieee80211_node *ni) {