summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net80211/ieee80211_crypto.c55
-rw-r--r--sys/net80211/ieee80211_crypto.h46
2 files changed, 76 insertions, 25 deletions
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index 6e558475f39a0..28bbddaf87ca5 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -633,6 +633,61 @@ ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen)
#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)
{
diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h
index a996af14cfe08..3d1f8cc5e002c 100644
--- a/sys/net80211/ieee80211_crypto.h
+++ b/sys/net80211/ieee80211_crypto.h
@@ -73,19 +73,25 @@ typedef uint16_t ieee80211_keyix; /* h/w key index */
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 ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
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.
*/