aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-05-15 01:54:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-21 21:48:01 -0400
commitccc038abe4cb00cf56aeae5b1df47fcc4ed4136c (patch)
tree0c35fec8a1c9e7179f9b756d30c3f8af02d9bfa5
parenta98410139a2ef6553ae5d73bf12bb9a68d0b38b9 (diff)
iwlwifi: clean up and bug fix for security
This patch cleans up code in security. 1) uses the new pointer to ieee80211_key_conf passed with the tx_control. 2) resolves bug reported by Mirco Tischler (sends ADD_STA in ASYNC mode) 3) resolves bug reported by Volker Braun regarding dynamic WEP 4) drops a WEP packet which has been garbaged by firmware. This can happen upon rekeying. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c41
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c3
6 files changed, 29 insertions, 46 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 8f0852d058e5..52c7eae08d44 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -2389,6 +2389,7 @@ static int iwl4965_set_decrypted_flag(struct iwl_priv *priv,
2389 RX_RES_STATUS_BAD_KEY_TTAK) 2389 RX_RES_STATUS_BAD_KEY_TTAK)
2390 break; 2390 break;
2391 2391
2392 case RX_RES_STATUS_SEC_TYPE_WEP:
2392 if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == 2393 if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
2393 RX_RES_STATUS_BAD_ICV_MIC) { 2394 RX_RES_STATUS_BAD_ICV_MIC) {
2394 /* bad ICV, the packet is destroyed since the 2395 /* bad ICV, the packet is destroyed since the
@@ -2396,7 +2397,6 @@ static int iwl4965_set_decrypted_flag(struct iwl_priv *priv,
2396 IWL_DEBUG_RX("Packet destroyed\n"); 2397 IWL_DEBUG_RX("Packet destroyed\n");
2397 return -1; 2398 return -1;
2398 } 2399 }
2399 case RX_RES_STATUS_SEC_TYPE_WEP:
2400 case RX_RES_STATUS_SEC_TYPE_CCMP: 2400 case RX_RES_STATUS_SEC_TYPE_CCMP:
2401 if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == 2401 if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
2402 RX_RES_STATUS_DECRYPT_OK) { 2402 RX_RES_STATUS_DECRYPT_OK) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 7a54682a3d86..305491ff9beb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -442,7 +442,6 @@ struct iwl_hw_key {
442 enum ieee80211_key_alg alg; 442 enum ieee80211_key_alg alg;
443 int keylen; 443 int keylen;
444 u8 keyidx; 444 u8 keyidx;
445 struct ieee80211_key_conf *conf;
446 u8 key[32]; 445 u8 key[32];
447}; 446};
448 447
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index c8e468fb3caa..99ee1e14e29e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -324,7 +324,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
324 unsigned long flags; 324 unsigned long flags;
325 325
326 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; 326 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
327 keyconf->hw_key_idx = keyconf->keyidx; 327 keyconf->hw_key_idx = HW_KEY_DEFAULT;
328 priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; 328 priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP;
329 329
330 spin_lock_irqsave(&priv->sta_lock, flags); 330 spin_lock_irqsave(&priv->sta_lock, flags);
@@ -354,7 +354,6 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
354 int ret; 354 int ret;
355 355
356 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; 356 keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
357 keyconf->hw_key_idx = keyconf->keyidx;
358 357
359 key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK); 358 key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
360 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); 359 key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
@@ -411,7 +410,6 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
411 key_flags |= STA_KEY_MULTICAST_MSK; 410 key_flags |= STA_KEY_MULTICAST_MSK;
412 411
413 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 412 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
414 keyconf->hw_key_idx = keyconf->keyidx;
415 413
416 spin_lock_irqsave(&priv->sta_lock, flags); 414 spin_lock_irqsave(&priv->sta_lock, flags);
417 priv->stations[sta_id].keyinfo.alg = keyconf->alg; 415 priv->stations[sta_id].keyinfo.alg = keyconf->alg;
@@ -449,12 +447,10 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
449 447
450 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 448 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
451 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; 449 keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
452 keyconf->hw_key_idx = keyconf->keyidx;
453 450
454 spin_lock_irqsave(&priv->sta_lock, flags); 451 spin_lock_irqsave(&priv->sta_lock, flags);
455 452
456 priv->stations[sta_id].keyinfo.alg = keyconf->alg; 453 priv->stations[sta_id].keyinfo.alg = keyconf->alg;
457 priv->stations[sta_id].keyinfo.conf = keyconf;
458 priv->stations[sta_id].keyinfo.keylen = 16; 454 priv->stations[sta_id].keyinfo.keylen = 16;
459 455
460 if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) 456 if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
@@ -483,7 +479,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
483 u16 key_flags; 479 u16 key_flags;
484 u8 keyidx; 480 u8 keyidx;
485 481
486 priv->key_mapping_key = 0; 482 priv->key_mapping_key--;
487 483
488 spin_lock_irqsave(&priv->sta_lock, flags); 484 spin_lock_irqsave(&priv->sta_lock, flags);
489 key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); 485 key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
@@ -514,31 +510,32 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
514 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; 510 priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
515 511
516 IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); 512 IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
517 ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0); 513 ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
518 spin_unlock_irqrestore(&priv->sta_lock, flags); 514 spin_unlock_irqrestore(&priv->sta_lock, flags);
519 return ret; 515 return ret;
520} 516}
521EXPORT_SYMBOL(iwl_remove_dynamic_key); 517EXPORT_SYMBOL(iwl_remove_dynamic_key);
522 518
523int iwl_set_dynamic_key(struct iwl_priv *priv, 519int iwl_set_dynamic_key(struct iwl_priv *priv,
524 struct ieee80211_key_conf *key, u8 sta_id) 520 struct ieee80211_key_conf *keyconf, u8 sta_id)
525{ 521{
526 int ret; 522 int ret;
527 523
528 priv->key_mapping_key = 1; 524 priv->key_mapping_key++;
525 keyconf->hw_key_idx = HW_KEY_DYNAMIC;
529 526
530 switch (key->alg) { 527 switch (keyconf->alg) {
531 case ALG_CCMP: 528 case ALG_CCMP:
532 ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id); 529 ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
533 break; 530 break;
534 case ALG_TKIP: 531 case ALG_TKIP:
535 ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id); 532 ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
536 break; 533 break;
537 case ALG_WEP: 534 case ALG_WEP:
538 ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id); 535 ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id);
539 break; 536 break;
540 default: 537 default:
541 IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); 538 IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, keyconf->alg);
542 ret = -EINVAL; 539 ret = -EINVAL;
543 } 540 }
544 541
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index ee2564307084..b643546961f9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -29,6 +29,9 @@
29#ifndef __iwl_sta_h__ 29#ifndef __iwl_sta_h__
30#define __iwl_sta_h__ 30#define __iwl_sta_h__
31 31
32#define HW_KEY_DYNAMIC 0
33#define HW_KEY_DEFAULT 1
34
32int iwl_get_free_ucode_key_index(struct iwl_priv *priv); 35int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
33int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); 36int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty);
34int iwl_remove_default_wep_key(struct iwl_priv *priv, 37int iwl_remove_default_wep_key(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index a37ced58c661..f32cddabdf64 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -639,16 +639,12 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
639 struct sk_buff *skb_frag, 639 struct sk_buff *skb_frag,
640 int sta_id) 640 int sta_id)
641{ 641{
642 struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; 642 struct ieee80211_key_conf *keyconf = ctl->hw_key;
643 struct iwl_wep_key *wepkey;
644 int keyidx = 0;
645 643
646 BUG_ON(ctl->hw_key->hw_key_idx > 3); 644 switch (keyconf->alg) {
647
648 switch (keyinfo->alg) {
649 case ALG_CCMP: 645 case ALG_CCMP:
650 tx_cmd->sec_ctl = TX_CMD_SEC_CCM; 646 tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
651 memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen); 647 memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
652 if (ctl->flags & IEEE80211_TXCTL_AMPDU) 648 if (ctl->flags & IEEE80211_TXCTL_AMPDU)
653 tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; 649 tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
654 IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n"); 650 IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
@@ -656,39 +652,26 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
656 652
657 case ALG_TKIP: 653 case ALG_TKIP:
658 tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; 654 tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
659 ieee80211_get_tkip_key(keyinfo->conf, skb_frag, 655 ieee80211_get_tkip_key(keyconf, skb_frag,
660 IEEE80211_TKIP_P2_KEY, tx_cmd->key); 656 IEEE80211_TKIP_P2_KEY, tx_cmd->key);
661 IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n"); 657 IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n");
662 break; 658 break;
663 659
664 case ALG_WEP: 660 case ALG_WEP:
665 wepkey = &priv->wep_keys[ctl->hw_key->hw_key_idx];
666 tx_cmd->sec_ctl = 0;
667 if (priv->default_wep_key) {
668 /* the WEP key was sent as static */
669 keyidx = ctl->hw_key->hw_key_idx;
670 memcpy(&tx_cmd->key[3], wepkey->key,
671 wepkey->key_size);
672 if (wepkey->key_size == WEP_KEY_LEN_128)
673 tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
674 } else {
675 /* the WEP key was sent as dynamic */
676 keyidx = keyinfo->keyidx;
677 memcpy(&tx_cmd->key[3], keyinfo->key,
678 keyinfo->keylen);
679 if (keyinfo->keylen == WEP_KEY_LEN_128)
680 tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
681 }
682
683 tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | 661 tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP |
684 (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); 662 (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
663
664 if (keyconf->keylen == WEP_KEY_LEN_128)
665 tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
666
667 memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
685 668
686 IWL_DEBUG_TX("Configuring packet for WEP encryption " 669 IWL_DEBUG_TX("Configuring packet for WEP encryption "
687 "with key %d\n", keyidx); 670 "with key %d\n", keyconf->keyidx);
688 break; 671 break;
689 672
690 default: 673 default:
691 printk(KERN_ERR "Unknown encode alg %d\n", keyinfo->alg); 674 printk(KERN_ERR "Unknown encode alg %d\n", keyconf->alg);
692 break; 675 break;
693 } 676 }
694} 677}
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index a532a9e576dc..40616dbd26f0 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -4951,7 +4951,8 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
4951 if (cmd == SET_KEY) 4951 if (cmd == SET_KEY)
4952 is_default_wep_key = !priv->key_mapping_key; 4952 is_default_wep_key = !priv->key_mapping_key;
4953 else 4953 else
4954 is_default_wep_key = priv->default_wep_key; 4954 is_default_wep_key =
4955 (key->hw_key_idx == HW_KEY_DEFAULT);
4955 } 4956 }
4956 4957
4957 switch (cmd) { 4958 switch (cmd) {