diff options
Diffstat (limited to 'net/ieee80211/ieee80211_rx.c')
-rw-r--r-- | net/ieee80211/ieee80211_rx.c | 56 |
1 files changed, 50 insertions, 6 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 2759312a4204..d9265195656d 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c | |||
@@ -415,17 +415,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | |||
415 | ieee->host_mc_decrypt : ieee->host_decrypt; | 415 | ieee->host_mc_decrypt : ieee->host_decrypt; |
416 | 416 | ||
417 | if (can_be_decrypted) { | 417 | if (can_be_decrypted) { |
418 | int idx = 0; | ||
419 | if (skb->len >= hdrlen + 3) { | 418 | if (skb->len >= hdrlen + 3) { |
420 | /* Top two-bits of byte 3 are the key index */ | 419 | /* Top two-bits of byte 3 are the key index */ |
421 | idx = skb->data[hdrlen + 3] >> 6; | 420 | keyidx = skb->data[hdrlen + 3] >> 6; |
422 | } | 421 | } |
423 | 422 | ||
424 | /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx | 423 | /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx |
425 | * is only allowed 2-bits of storage, no value of idx can | 424 | * is only allowed 2-bits of storage, no value of keyidx can |
426 | * be provided via above code that would result in idx | 425 | * be provided via above code that would result in keyidx |
427 | * being out of range */ | 426 | * being out of range */ |
428 | crypt = ieee->crypt[idx]; | 427 | crypt = ieee->crypt[keyidx]; |
429 | 428 | ||
430 | #ifdef NOT_YET | 429 | #ifdef NOT_YET |
431 | sta = NULL; | 430 | sta = NULL; |
@@ -655,6 +654,51 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, | |||
655 | goto rx_dropped; | 654 | goto rx_dropped; |
656 | } | 655 | } |
657 | 656 | ||
657 | /* If the frame was decrypted in hardware, we may need to strip off | ||
658 | * any security data (IV, ICV, etc) that was left behind */ | ||
659 | if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) && | ||
660 | ieee->host_strip_iv_icv) { | ||
661 | int trimlen = 0; | ||
662 | |||
663 | /* Top two-bits of byte 3 are the key index */ | ||
664 | if (skb->len >= hdrlen + 3) | ||
665 | keyidx = skb->data[hdrlen + 3] >> 6; | ||
666 | |||
667 | /* To strip off any security data which appears before the | ||
668 | * payload, we simply increase hdrlen (as the header gets | ||
669 | * chopped off immediately below). For the security data which | ||
670 | * appears after the payload, we use skb_trim. */ | ||
671 | |||
672 | switch (ieee->sec.encode_alg[keyidx]) { | ||
673 | case SEC_ALG_WEP: | ||
674 | /* 4 byte IV */ | ||
675 | hdrlen += 4; | ||
676 | /* 4 byte ICV */ | ||
677 | trimlen = 4; | ||
678 | break; | ||
679 | case SEC_ALG_TKIP: | ||
680 | /* 4 byte IV, 4 byte ExtIV */ | ||
681 | hdrlen += 8; | ||
682 | /* 8 byte MIC, 4 byte ICV */ | ||
683 | trimlen = 12; | ||
684 | break; | ||
685 | case SEC_ALG_CCMP: | ||
686 | /* 8 byte CCMP header */ | ||
687 | hdrlen += 8; | ||
688 | /* 8 byte MIC */ | ||
689 | trimlen = 8; | ||
690 | break; | ||
691 | } | ||
692 | |||
693 | if (skb->len < trimlen) | ||
694 | goto rx_dropped; | ||
695 | |||
696 | __skb_trim(skb, skb->len - trimlen); | ||
697 | |||
698 | if (skb->len < hdrlen) | ||
699 | goto rx_dropped; | ||
700 | } | ||
701 | |||
658 | /* skb: hdr + (possible reassembled) full plaintext payload */ | 702 | /* skb: hdr + (possible reassembled) full plaintext payload */ |
659 | 703 | ||
660 | payload = skb->data + hdrlen; | 704 | payload = skb->data + hdrlen; |