diff options
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 19 | ||||
-rw-r--r-- | include/net/ieee80211.h | 4 | ||||
-rw-r--r-- | net/ieee80211/ieee80211_rx.c | 56 |
4 files changed, 55 insertions, 25 deletions
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 12043f8be1bf..a659442b9c15 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c | |||
@@ -690,6 +690,7 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, | |||
690 | bcm->ieee->host_encrypt = !!on; | 690 | bcm->ieee->host_encrypt = !!on; |
691 | bcm->ieee->host_decrypt = !!on; | 691 | bcm->ieee->host_decrypt = !!on; |
692 | bcm->ieee->host_build_iv = !on; | 692 | bcm->ieee->host_build_iv = !on; |
693 | bcm->ieee->host_strip_iv_icv = !on; | ||
693 | spin_unlock_irqrestore(&bcm->irq_lock, flags); | 694 | spin_unlock_irqrestore(&bcm->irq_lock, flags); |
694 | mutex_unlock(&bcm->mutex); | 695 | mutex_unlock(&bcm->mutex); |
695 | 696 | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index 0159e4e93201..a957bc861382 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | |||
@@ -543,25 +543,6 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, | |||
543 | break; | 543 | break; |
544 | } | 544 | } |
545 | 545 | ||
546 | frame_ctl = le16_to_cpu(wlhdr->frame_ctl); | ||
547 | if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { | ||
548 | frame_ctl &= ~IEEE80211_FCTL_PROTECTED; | ||
549 | wlhdr->frame_ctl = cpu_to_le16(frame_ctl); | ||
550 | /* trim IV and ICV */ | ||
551 | /* FIXME: this must be done only for WEP encrypted packets */ | ||
552 | if (skb->len < 32) { | ||
553 | dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " | ||
554 | "set and length < 32)\n"); | ||
555 | return -EINVAL; | ||
556 | } else { | ||
557 | memmove(skb->data + 4, skb->data, 24); | ||
558 | skb_pull(skb, 4); | ||
559 | skb_trim(skb, skb->len - 4); | ||
560 | stats.len -= 8; | ||
561 | } | ||
562 | wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); | ||
563 | } | ||
564 | |||
565 | switch (WLAN_FC_GET_TYPE(frame_ctl)) { | 546 | switch (WLAN_FC_GET_TYPE(frame_ctl)) { |
566 | case IEEE80211_FTYPE_MGMT: | 547 | case IEEE80211_FTYPE_MGMT: |
567 | ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); | 548 | ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); |
diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index b174ebb277a9..cb255432e4e4 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h | |||
@@ -1037,6 +1037,10 @@ struct ieee80211_device { | |||
1037 | /* host performs multicast decryption */ | 1037 | /* host performs multicast decryption */ |
1038 | int host_mc_decrypt; | 1038 | int host_mc_decrypt; |
1039 | 1039 | ||
1040 | /* host should strip IV and ICV from protected frames */ | ||
1041 | /* meaningful only when hardware decryption is being used */ | ||
1042 | int host_strip_iv_icv; | ||
1043 | |||
1040 | int host_open_frag; | 1044 | int host_open_frag; |
1041 | int host_build_iv; | 1045 | int host_build_iv; |
1042 | int ieee802_1x; /* is IEEE 802.1X used */ | 1046 | int ieee802_1x; /* is IEEE 802.1X used */ |
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; |