aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00mac.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-08-04 10:37:44 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-08-22 16:29:58 -0400
commit2bb057d07a0bc17475a7bf897fc41667ab08b73f (patch)
tree55461e52caa34a45a67aaf9e3f1c608f96c77d59 /drivers/net/wireless/rt2x00/rt2x00mac.c
parent8e7cdbb6333ef7654e708bd60e50a123688dcd7b (diff)
rt2x00: Implement HW encryption
Various rt2x00 devices support hardware encryption. Most of them require the IV/EIV to be generated by mac80211, but require it to be provided seperately instead of within the frame itself. This means that rt2x00lib should extract the data from the frame and place it in the frame descriptor. During RX the IV/EIV is provided in the descriptor by the hardware which means that it should be inserted into the frame by rt2x00lib. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00mac.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c110
1 files changed, 102 insertions, 8 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 4b9fde903cd6..3af427339417 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -36,22 +36,22 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
36 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb); 36 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb);
37 struct ieee80211_tx_info *rts_info; 37 struct ieee80211_tx_info *rts_info;
38 struct sk_buff *skb; 38 struct sk_buff *skb;
39 int size; 39 unsigned int data_length;
40 int retval = 0; 40 int retval = 0;
41 41
42 if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) 42 if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
43 size = sizeof(struct ieee80211_cts); 43 data_length = sizeof(struct ieee80211_cts);
44 else 44 else
45 size = sizeof(struct ieee80211_rts); 45 data_length = sizeof(struct ieee80211_rts);
46 46
47 skb = dev_alloc_skb(size + rt2x00dev->hw->extra_tx_headroom); 47 skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom);
48 if (unlikely(!skb)) { 48 if (unlikely(!skb)) {
49 WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n"); 49 WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n");
50 return -ENOMEM; 50 return -ENOMEM;
51 } 51 }
52 52
53 skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); 53 skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom);
54 skb_put(skb, size); 54 skb_put(skb, data_length);
55 55
56 /* 56 /*
57 * Copy TX information over from original frame to 57 * Copy TX information over from original frame to
@@ -64,7 +64,6 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
64 */ 64 */
65 memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb)); 65 memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
66 rts_info = IEEE80211_SKB_CB(skb); 66 rts_info = IEEE80211_SKB_CB(skb);
67 rts_info->control.hw_key = NULL;
68 rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS; 67 rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS;
69 rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT; 68 rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT;
70 rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; 69 rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;
@@ -74,13 +73,24 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
74 else 73 else
75 rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK; 74 rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
76 75
76 skb->do_not_encrypt = 1;
77
78 /*
79 * RTS/CTS frame should use the length of the frame plus any
80 * encryption overhead that will be added by the hardware.
81 */
82#ifdef CONFIG_RT2X00_LIB_CRYPTO
83 if (!frag_skb->do_not_encrypt)
84 data_length += rt2x00crypto_tx_overhead(tx_info);
85#endif /* CONFIG_RT2X00_LIB_CRYPTO */
86
77 if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) 87 if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
78 ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif, 88 ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
79 frag_skb->data, size, tx_info, 89 frag_skb->data, data_length, tx_info,
80 (struct ieee80211_cts *)(skb->data)); 90 (struct ieee80211_cts *)(skb->data));
81 else 91 else
82 ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif, 92 ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif,
83 frag_skb->data, size, tx_info, 93 frag_skb->data, data_length, tx_info,
84 (struct ieee80211_rts *)(skb->data)); 94 (struct ieee80211_rts *)(skb->data));
85 95
86 retval = rt2x00queue_write_tx_frame(queue, skb); 96 retval = rt2x00queue_write_tx_frame(queue, skb);
@@ -464,6 +474,90 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
464} 474}
465EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); 475EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
466 476
477#ifdef CONFIG_RT2X00_LIB_CRYPTO
478int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
479 const u8 *local_address, const u8 *address,
480 struct ieee80211_key_conf *key)
481{
482 struct rt2x00_dev *rt2x00dev = hw->priv;
483 int (*set_key) (struct rt2x00_dev *rt2x00dev,
484 struct rt2x00lib_crypto *crypto,
485 struct ieee80211_key_conf *key);
486 struct rt2x00lib_crypto crypto;
487
488 if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
489 return -EOPNOTSUPP;
490 else if (key->keylen > 32)
491 return -ENOSPC;
492
493 memset(&crypto, 0, sizeof(crypto));
494
495 /*
496 * When in STA mode, bssidx is always 0 otherwise local_address[5]
497 * contains the bss number, see BSS_ID_MASK comments for details.
498 */
499 if (rt2x00dev->intf_sta_count)
500 crypto.bssidx = 0;
501 else
502 crypto.bssidx =
503 local_address[5] & (rt2x00dev->ops->max_ap_intf - 1);
504
505 crypto.cipher = rt2x00crypto_key_to_cipher(key);
506 if (crypto.cipher == CIPHER_NONE)
507 return -EOPNOTSUPP;
508
509 crypto.cmd = cmd;
510 crypto.address = address;
511
512 if (crypto.cipher == CIPHER_TKIP) {
513 if (key->keylen > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
514 memcpy(&crypto.key,
515 &key->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
516 sizeof(crypto.key));
517
518 if (key->keylen > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
519 memcpy(&crypto.tx_mic,
520 &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
521 sizeof(crypto.tx_mic));
522
523 if (key->keylen > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
524 memcpy(&crypto.rx_mic,
525 &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
526 sizeof(crypto.rx_mic));
527 } else
528 memcpy(&crypto.key, &key->key[0], key->keylen);
529
530 /*
531 * Each BSS has a maximum of 4 shared keys.
532 * Shared key index values:
533 * 0) BSS0 key0
534 * 1) BSS0 key1
535 * ...
536 * 4) BSS1 key0
537 * ...
538 * 8) BSS2 key0
539 * ...
540 * Both pairwise as shared key indeces are determined by
541 * driver. This is required because the hardware requires
542 * keys to be assigned in correct order (When key 1 is
543 * provided but key 0 is not, then the key is not found
544 * by the hardware during RX).
545 */
546 key->hw_key_idx = 0;
547
548 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
549 set_key = rt2x00dev->ops->lib->config_pairwise_key;
550 else
551 set_key = rt2x00dev->ops->lib->config_shared_key;
552
553 if (!set_key)
554 return -EOPNOTSUPP;
555
556 return set_key(rt2x00dev, &crypto, key);
557}
558EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
559#endif /* CONFIG_RT2X00_LIB_CRYPTO */
560
467int rt2x00mac_get_stats(struct ieee80211_hw *hw, 561int rt2x00mac_get_stats(struct ieee80211_hw *hw,
468 struct ieee80211_low_level_stats *stats) 562 struct ieee80211_low_level_stats *stats)
469{ 563{