Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F166379246
D8533.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
D8533.id.diff
View Options
Index: head/sys/net80211/ieee80211_adhoc.c
===================================================================
--- head/sys/net80211/ieee80211_adhoc.c
+++ head/sys/net80211/ieee80211_adhoc.c
@@ -316,6 +316,16 @@
int hdrspace, need_tap = 1; /* mbuf need to be tapped. */
uint8_t dir, type, subtype, qos;
uint8_t *bssid;
+ int is_hw_decrypted = 0;
+ int has_decrypted = 0;
+
+ /*
+ * Some devices do hardware decryption all the way through
+ * to pretending the frame wasn't encrypted in the first place.
+ * So, tag it appropriately so it isn't discarded inappropriately.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED))
+ is_hw_decrypted = 1;
if (m->m_flags & M_AMPDU_MPDU) {
/*
@@ -479,7 +489,7 @@
* crypto cipher modules used to do delayed update
* of replay sequence numbers.
*/
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
/*
* Discard encrypted frames when privacy is off.
@@ -490,14 +500,14 @@
IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out;
}
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail);
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
} else {
/* XXX M_WEP and IEEE80211_F_PRIVACY */
key = NULL;
@@ -528,7 +538,7 @@
/*
* Next strip any MSDU crypto bits.
*/
- if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) {
+ if (!ieee80211_crypto_demic(vap, key, m, 0)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
ni->ni_macaddr, "data", "%s", "demic error");
vap->iv_stats.is_rx_demicfail++;
@@ -582,7 +592,8 @@
* any non-PAE frames received without encryption.
*/
if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
- (key == NULL && (m->m_flags & M_WEP) == 0) &&
+ ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
+ (is_hw_decrypted == 0) &&
eh->ether_type != htons(ETHERTYPE_PAE)) {
/*
* Drop unencrypted frames.
Index: head/sys/net80211/ieee80211_crypto.h
===================================================================
--- head/sys/net80211/ieee80211_crypto.h
+++ head/sys/net80211/ieee80211_crypto.h
@@ -114,7 +114,8 @@
#define IEEE80211_KEY_DEVICE /* flags owned by device driver */\
(IEEE80211_KEY_DEVKEY|IEEE80211_KEY_CIPHER0|IEEE80211_KEY_CIPHER1| \
- IEEE80211_KEY_SWCRYPT|IEEE80211_KEY_SWMIC)
+ IEEE80211_KEY_SWCRYPT|IEEE80211_KEY_SWMIC|IEEE80211_KEY_NOIV | \
+ IEEE80211_KEY_NOIVMGT|IEEE80211_KEY_NOMIC|IEEE80211_KEY_NOMICMGT)
#define IEEE80211_KEY_BITS \
"\20\1XMIT\2RECV\3GROUP\4SWENCRYPT\5SWDECRYPT\6SWENMIC\7SWDEMIC" \
@@ -207,8 +208,8 @@
struct mbuf *);
struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
struct mbuf *);
-struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *,
- struct mbuf *, int);
+int ieee80211_crypto_decap(struct ieee80211_node *,
+ struct mbuf *, int, struct ieee80211_key **);
int ieee80211_crypto_demic(struct ieee80211vap *vap, struct ieee80211_key *k,
struct mbuf *, int);
/*
Index: head/sys/net80211/ieee80211_crypto.c
===================================================================
--- head/sys/net80211/ieee80211_crypto.c
+++ head/sys/net80211/ieee80211_crypto.c
@@ -580,8 +580,9 @@
* Validate and strip privacy headers (and trailer) for a
* received frame that has the WEP/Privacy bit set.
*/
-struct ieee80211_key *
-ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen)
+int
+ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen,
+ struct ieee80211_key **key)
{
#define IEEE80211_WEP_HDRLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
#define IEEE80211_WEP_MINLEN \
@@ -590,16 +591,38 @@
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211_key *k;
struct ieee80211_frame *wh;
+ const struct ieee80211_rx_stats *rxs;
const struct ieee80211_cipher *cip;
uint8_t keyid;
+ /*
+ * Check for hardware decryption and IV stripping.
+ * If the IV is stripped then we definitely can't find a key.
+ * Set the key to NULL but return true; upper layers
+ * will need to handle a NULL key for a successful
+ * decrypt.
+ */
+ rxs = ieee80211_get_rx_params_ptr(m);
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED)) {
+ if (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP) {
+ /*
+ * Hardware decrypted, IV stripped.
+ * We can't find a key with a stripped IV.
+ * Return successful.
+ */
+ *key = NULL;
+ return (1);
+ }
+ }
+
/* NB: this minimum size data frame could be bigger */
if (m->m_pkthdr.len < IEEE80211_WEP_MINLEN) {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY,
"%s: WEP data frame too short, len %u\n",
__func__, m->m_pkthdr.len);
vap->iv_stats.is_rx_tooshort++; /* XXX need unique stat? */
- return NULL;
+ *key = NULL;
+ return (0);
}
/*
@@ -625,15 +648,29 @@
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
"unable to pullup %s header", cip->ic_name);
vap->iv_stats.is_rx_wepfail++; /* XXX */
- return NULL;
+ *key = NULL;
+ return (0);
}
- return (cip->ic_decap(k, m, hdrlen) ? k : NULL);
+ /*
+ * Attempt decryption.
+ *
+ * If we fail then don't return the key - return NULL
+ * and an error.
+ */
+ if (cip->ic_decap(k, m, hdrlen)) {
+ /* success */
+ *key = k;
+ return (1);
+ }
+
+ /* Failure */
+ *key = NULL;
+ return (0);
#undef IEEE80211_WEP_MINLEN
#undef IEEE80211_WEP_HDRLEN
}
-
/*
* Check and remove any MIC.
*/
Index: head/sys/net80211/ieee80211_crypto_ccmp.c
===================================================================
--- head/sys/net80211/ieee80211_crypto_ccmp.c
+++ head/sys/net80211/ieee80211_crypto_ccmp.c
@@ -162,12 +162,27 @@
static int
ccmp_encap(struct ieee80211_key *k, struct mbuf *m)
{
+ const struct ieee80211_frame *wh;
struct ccmp_ctx *ctx = k->wk_private;
struct ieee80211com *ic = ctx->cc_ic;
uint8_t *ivp;
int hdrlen;
+ int is_mgmt;
hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
+ wh = mtod(m, const struct ieee80211_frame *);
+ is_mgmt = IEEE80211_IS_MGMT(wh);
+
+ /*
+ * Check to see if we need to insert IV/MIC.
+ *
+ * Some offload devices don't require the IV to be inserted
+ * as part of the hardware encryption.
+ */
+ if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOIVMGT))
+ return 1;
+ if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOIV))
+ return 1;
/*
* Copy down 802.11 header and add the IV, KeyID, and ExtIV.
@@ -217,12 +232,18 @@
static int
ccmp_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
{
+ const struct ieee80211_rx_stats *rxs;
struct ccmp_ctx *ctx = k->wk_private;
struct ieee80211vap *vap = ctx->cc_vap;
struct ieee80211_frame *wh;
uint8_t *ivp, tid;
uint64_t pn;
+ rxs = ieee80211_get_rx_params_ptr(m);
+
+ if ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))
+ goto finish;
+
/*
* Header should have extended IV and sequence number;
* verify the former and validate the latter.
@@ -261,17 +282,28 @@
!ccmp_decrypt(k, pn, m, hdrlen))
return 0;
+finish:
/*
* Copy up 802.11 header and strip crypto bits.
*/
- ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + ccmp.ic_header, hdrlen);
- m_adj(m, ccmp.ic_header);
- m_adj(m, -ccmp.ic_trailer);
+ if (! ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
+ ovbcopy(mtod(m, void *), mtod(m, uint8_t *) + ccmp.ic_header,
+ hdrlen);
+ m_adj(m, ccmp.ic_header);
+ }
+
+ /*
+ * 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);
/*
* Ok to update rsc now.
*/
- k->wk_keyrsc[tid] = pn;
+ if (! ((rxs != NULL) & (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
+ k->wk_keyrsc[tid] = pn;
+ }
return 1;
}
Index: head/sys/net80211/ieee80211_crypto_tkip.c
===================================================================
--- head/sys/net80211/ieee80211_crypto_tkip.c
+++ head/sys/net80211/ieee80211_crypto_tkip.c
@@ -177,8 +177,13 @@
struct tkip_ctx *ctx = k->wk_private;
struct ieee80211vap *vap = ctx->tc_vap;
struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_frame *wh;
uint8_t *ivp;
int hdrlen;
+ int is_mgmt;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ is_mgmt = IEEE80211_IS_MGMT(wh);
/*
* Handle TKIP counter measures requirement.
@@ -193,6 +198,16 @@
vap->iv_stats.is_crypto_tkipcm++;
return 0;
}
+
+ /*
+ * Check to see whether IV needs to be included.
+ */
+ if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOIVMGT))
+ return 1;
+ if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOIV))
+ return 1;
+
+
hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
/*
@@ -224,6 +239,19 @@
tkip_enmic(struct ieee80211_key *k, struct mbuf *m, int force)
{
struct tkip_ctx *ctx = k->wk_private;
+ struct ieee80211_frame *wh;
+ int is_mgmt;
+
+ wh = mtod(m, struct ieee80211_frame *);
+ is_mgmt = IEEE80211_IS_MGMT(wh);
+
+ /*
+ * Check to see whether MIC needs to be included.
+ */
+ if (is_mgmt && (k->wk_flags & IEEE80211_KEY_NOMICMGT))
+ return 1;
+ if ((! is_mgmt) && (k->wk_flags & IEEE80211_KEY_NOMIC))
+ return 1;
if (force || (k->wk_flags & IEEE80211_KEY_SWENMIC)) {
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
@@ -259,11 +287,20 @@
static int
tkip_decap(struct ieee80211_key *k, struct mbuf *m, int hdrlen)
{
+ const struct ieee80211_rx_stats *rxs;
struct tkip_ctx *ctx = k->wk_private;
struct ieee80211vap *vap = ctx->tc_vap;
struct ieee80211_frame *wh;
uint8_t *ivp, tid;
+ rxs = ieee80211_get_rx_params_ptr(m);
+
+ /*
+ * If IV has been stripped, we skip most of the below.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))
+ goto finish;
+
/*
* Header should have extended IV and sequence number;
* verify the former and validate the latter.
@@ -318,11 +355,22 @@
!tkip_decrypt(ctx, k, m, hdrlen))
return 0;
+finish:
+
+ /*
+ * Copy up 802.11 header and strip crypto bits - but only if we
+ * are required to.
+ */
+ if (! ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_IV_STRIP))) {
+ memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *),
+ hdrlen);
+ m_adj(m, tkip.ic_header);
+ }
+
/*
- * Copy up 802.11 header and strip crypto bits.
+ * XXX TODO: do we need an option to potentially not strip the
+ * WEP trailer? Does "MMIC_STRIP" also mean this? Or?
*/
- memmove(mtod(m, uint8_t *) + tkip.ic_header, mtod(m, void *), hdrlen);
- m_adj(m, tkip.ic_header);
m_adj(m, -tkip.ic_trailer);
return 1;
@@ -334,11 +382,33 @@
static int
tkip_demic(struct ieee80211_key *k, struct mbuf *m, int force)
{
+ const struct ieee80211_rx_stats *rxs;
struct tkip_ctx *ctx = k->wk_private;
struct ieee80211_frame *wh;
uint8_t tid;
wh = mtod(m, struct ieee80211_frame *);
+ rxs = ieee80211_get_rx_params_ptr(m);
+
+ /*
+ * If we are told about a MIC failure from the driver,
+ * directly notify as a michael failure to the upper
+ * layers.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_FAIL_MIC)) {
+ struct ieee80211vap *vap = ctx->tc_vap;
+ ieee80211_notify_michael_failure(vap, wh,
+ k->wk_rxkeyix != IEEE80211_KEYIX_NONE ?
+ k->wk_rxkeyix : k->wk_keyix);
+ return 0;
+ }
+
+ /*
+ * If IV has been stripped, we skip most of the below.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_MMIC_STRIP))
+ goto finish;
+
if ((k->wk_flags & IEEE80211_KEY_SWDEMIC) || force) {
struct ieee80211vap *vap = ctx->tc_vap;
int hdrlen = ieee80211_hdrspace(vap->iv_ic, wh);
@@ -371,6 +441,7 @@
tid = ieee80211_gettid(wh);
k->wk_keyrsc[tid] = ctx->rx_rsc;
+finish:
return 1;
}
Index: head/sys/net80211/ieee80211_hostap.c
===================================================================
--- head/sys/net80211/ieee80211_hostap.c
+++ head/sys/net80211/ieee80211_hostap.c
@@ -479,6 +479,16 @@
int hdrspace, need_tap = 1; /* mbuf need to be tapped. */
uint8_t dir, type, subtype, qos;
uint8_t *bssid;
+ int is_hw_decrypted = 0;
+ int has_decrypted = 0;
+
+ /*
+ * Some devices do hardware decryption all the way through
+ * to pretending the frame wasn't encrypted in the first place.
+ * So, tag it appropriately so it isn't discarded inappropriately.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED))
+ is_hw_decrypted = 1;
if (m->m_flags & M_AMPDU_MPDU) {
/*
@@ -668,7 +678,7 @@
* crypto cipher modules used to do delayed update
* of replay sequence numbers.
*/
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
/*
* Discard encrypted frames when privacy is off.
@@ -679,14 +689,14 @@
IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out;
}
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail);
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
} else {
/* XXX M_WEP and IEEE80211_F_PRIVACY */
key = NULL;
@@ -769,7 +779,8 @@
* any non-PAE frames received without encryption.
*/
if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
- (key == NULL && (m->m_flags & M_WEP) == 0) &&
+ ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
+ (is_hw_decrypted == 0) &&
eh->ether_type != htons(ETHERTYPE_PAE)) {
/*
* Drop unencrypted frames.
@@ -851,13 +862,13 @@
goto out;
}
hdrspace = ieee80211_hdrspace(ic, wh);
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
}
/*
* Pass the packet to radiotap before calling iv_recv_mgmt().
Index: head/sys/net80211/ieee80211_sta.c
===================================================================
--- head/sys/net80211/ieee80211_sta.c
+++ head/sys/net80211/ieee80211_sta.c
@@ -546,6 +546,16 @@
int hdrspace, need_tap = 1; /* mbuf need to be tapped. */
uint8_t dir, type, subtype, qos;
uint8_t *bssid;
+ int is_hw_decrypted = 0;
+ int has_decrypted = 0;
+
+ /*
+ * Some devices do hardware decryption all the way through
+ * to pretending the frame wasn't encrypted in the first place.
+ * So, tag it appropriately so it isn't discarded inappropriately.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED))
+ is_hw_decrypted = 1;
if (m->m_flags & M_AMPDU_MPDU) {
/*
@@ -724,6 +734,21 @@
}
/*
+ * Handle privacy requirements for hardware decryption
+ * devices.
+ *
+ * For those devices, a handful of things happen.
+ *
+ * + If IV has been stripped, then we can't run
+ * ieee80211_crypto_decap() - none of the key
+ * + If MIC has been stripped, we can't validate
+ * MIC here.
+ * + If MIC fails, then we need to communicate a
+ * MIC failure up to the stack - but we don't know
+ * which key was used.
+ */
+
+ /*
* Handle privacy requirements. Note that we
* must not be preempted from here until after
* we (potentially) call ieee80211_crypto_demic;
@@ -731,7 +756,7 @@
* crypto cipher modules used to do delayed update
* of replay sequence numbers.
*/
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
/*
* Discard encrypted frames when privacy is off.
@@ -742,14 +767,14 @@
IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out;
}
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail);
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
} else {
/* XXX M_WEP and IEEE80211_F_PRIVACY */
key = NULL;
@@ -779,8 +804,13 @@
/*
* Next strip any MSDU crypto bits.
+ *
+ * Note: we can't do MIC stripping/verification if the
+ * upper layer has stripped it. We have to check MIC
+ * ourselves. So, key may be NULL, but we have to check
+ * the RX status.
*/
- if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) {
+ if (!ieee80211_crypto_demic(vap, key, m, 0)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
ni->ni_macaddr, "data", "%s", "demic error");
vap->iv_stats.is_rx_demicfail++;
@@ -834,7 +864,8 @@
* any non-PAE frames received without encryption.
*/
if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
- (key == NULL && (m->m_flags & M_WEP) == 0) &&
+ ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
+ (is_hw_decrypted == 0) &&
eh->ether_type != htons(ETHERTYPE_PAE)) {
/*
* Drop unencrypted frames.
@@ -883,6 +914,16 @@
ether_sprintf(wh->i_addr2), rssi);
}
#endif
+
+ /*
+ * Note: See above for hardware offload privacy requirements.
+ * It also applies here.
+ */
+
+ /*
+ * Again, having encrypted flag set check would be good, but
+ * then we have to also handle crypto_decap() like above.
+ */
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if (subtype != IEEE80211_FC0_SUBTYPE_AUTH) {
/*
@@ -905,11 +946,16 @@
goto out;
}
hdrspace = ieee80211_hdrspace(ic, wh);
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+
+ /*
+ * Again, if IV/MIC was stripped, then this whole
+ * setup will fail. That's going to need some poking.
+ */
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
goto out;
}
+ has_decrypted = 1;
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
}
Index: head/sys/net80211/ieee80211_wds.c
===================================================================
--- head/sys/net80211/ieee80211_wds.c
+++ head/sys/net80211/ieee80211_wds.c
@@ -417,6 +417,16 @@
struct ether_header *eh;
int hdrspace, need_tap = 1; /* mbuf need to be tapped. */
uint8_t dir, type, subtype, qos;
+ int is_hw_decrypted = 0;
+ int has_decrypted = 0;
+
+ /*
+ * Some devices do hardware decryption all the way through
+ * to pretending the frame wasn't encrypted in the first place.
+ * So, tag it appropriately so it isn't discarded inappropriately.
+ */
+ if ((rxs != NULL) && (rxs->c_pktflags & IEEE80211_RX_F_DECRYPTED))
+ is_hw_decrypted = 1;
if (m->m_flags & M_AMPDU_MPDU) {
/*
@@ -544,7 +554,7 @@
* crypto cipher modules used to do delayed update
* of replay sequence numbers.
*/
- if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
+ if (is_hw_decrypted || wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {
/*
* Discard encrypted frames when privacy is off.
@@ -555,14 +565,14 @@
IEEE80211_NODE_STAT(ni, rx_noprivacy);
goto out;
}
- key = ieee80211_crypto_decap(ni, m, hdrspace);
- if (key == NULL) {
+ if (ieee80211_crypto_decap(ni, m, hdrspace, &key) == 0) {
/* NB: stats+msgs handled in crypto_decap */
IEEE80211_NODE_STAT(ni, rx_wepfail);
goto out;
}
wh = mtod(m, struct ieee80211_frame *);
wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ has_decrypted = 1;
} else {
/* XXX M_WEP and IEEE80211_F_PRIVACY */
key = NULL;
@@ -593,7 +603,7 @@
/*
* Next strip any MSDU crypto bits.
*/
- if (key != NULL && !ieee80211_crypto_demic(vap, key, m, 0)) {
+ if (!ieee80211_crypto_demic(vap, key, m, 0)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_INPUT,
ni->ni_macaddr, "data", "%s", "demic error");
vap->iv_stats.is_rx_demicfail++;
@@ -647,7 +657,8 @@
* any non-PAE frames received without encryption.
*/
if ((vap->iv_flags & IEEE80211_F_DROPUNENC) &&
- (key == NULL && (m->m_flags & M_WEP) == 0) &&
+ ((has_decrypted == 0) && (m->m_flags & M_WEP) == 0) &&
+ (is_hw_decrypted == 0) &&
eh->ether_type != htons(ETHERTYPE_PAE)) {
/*
* Drop unencrypted frames.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 14, 6:28 AM (2 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36687433
Default Alt Text
D8533.id.diff (20 KB)
Attached To
Mode
D8533: [net80211] handle hardware encryption offload in the receive path
Attached
Detach File
Event Timeline
Log In to Comment