|
@@ -415,17 +415,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
|
|
|
ieee->host_mc_decrypt : ieee->host_decrypt;
|
|
|
|
|
|
if (can_be_decrypted) {
|
|
|
- int idx = 0;
|
|
|
if (skb->len >= hdrlen + 3) {
|
|
|
/* Top two-bits of byte 3 are the key index */
|
|
|
- idx = skb->data[hdrlen + 3] >> 6;
|
|
|
+ keyidx = skb->data[hdrlen + 3] >> 6;
|
|
|
}
|
|
|
|
|
|
- /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx
|
|
|
- * is only allowed 2-bits of storage, no value of idx can
|
|
|
- * be provided via above code that would result in idx
|
|
|
+ /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx
|
|
|
+ * is only allowed 2-bits of storage, no value of keyidx can
|
|
|
+ * be provided via above code that would result in keyidx
|
|
|
* being out of range */
|
|
|
- crypt = ieee->crypt[idx];
|
|
|
+ crypt = ieee->crypt[keyidx];
|
|
|
|
|
|
#ifdef NOT_YET
|
|
|
sta = NULL;
|
|
@@ -655,6 +654,51 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
|
|
|
goto rx_dropped;
|
|
|
}
|
|
|
|
|
|
+ /* If the frame was decrypted in hardware, we may need to strip off
|
|
|
+ * any security data (IV, ICV, etc) that was left behind */
|
|
|
+ if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) &&
|
|
|
+ ieee->host_strip_iv_icv) {
|
|
|
+ int trimlen = 0;
|
|
|
+
|
|
|
+ /* Top two-bits of byte 3 are the key index */
|
|
|
+ if (skb->len >= hdrlen + 3)
|
|
|
+ keyidx = skb->data[hdrlen + 3] >> 6;
|
|
|
+
|
|
|
+ /* To strip off any security data which appears before the
|
|
|
+ * payload, we simply increase hdrlen (as the header gets
|
|
|
+ * chopped off immediately below). For the security data which
|
|
|
+ * appears after the payload, we use skb_trim. */
|
|
|
+
|
|
|
+ switch (ieee->sec.encode_alg[keyidx]) {
|
|
|
+ case SEC_ALG_WEP:
|
|
|
+ /* 4 byte IV */
|
|
|
+ hdrlen += 4;
|
|
|
+ /* 4 byte ICV */
|
|
|
+ trimlen = 4;
|
|
|
+ break;
|
|
|
+ case SEC_ALG_TKIP:
|
|
|
+ /* 4 byte IV, 4 byte ExtIV */
|
|
|
+ hdrlen += 8;
|
|
|
+ /* 8 byte MIC, 4 byte ICV */
|
|
|
+ trimlen = 12;
|
|
|
+ break;
|
|
|
+ case SEC_ALG_CCMP:
|
|
|
+ /* 8 byte CCMP header */
|
|
|
+ hdrlen += 8;
|
|
|
+ /* 8 byte MIC */
|
|
|
+ trimlen = 8;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (skb->len < trimlen)
|
|
|
+ goto rx_dropped;
|
|
|
+
|
|
|
+ __skb_trim(skb, skb->len - trimlen);
|
|
|
+
|
|
|
+ if (skb->len < hdrlen)
|
|
|
+ goto rx_dropped;
|
|
|
+ }
|
|
|
+
|
|
|
/* skb: hdr + (possible reassembled) full plaintext payload */
|
|
|
|
|
|
payload = skb->data + hdrlen;
|