aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_wx.c1
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.c19
-rw-r--r--include/net/ieee80211.h4
-rw-r--r--net/ieee80211/ieee80211_rx.c56
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;