aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorgregor kowski <gregor.kowski@gmail.com>2009-08-19 16:35:45 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-20 11:36:08 -0400
commit035d0243ebbdbd5f8f07d6ce378c9a9b36415bc9 (patch)
treebe26939b0411ed337c583927e2f8866113e12f5d /drivers
parent11ba964d4f936609a04e8b9f2051f6027ef761ae (diff)
b43: add hardware tkip
This add hardware tkip for b43. Signed-off-by: Gregor Kowski <gregor.kowski@gmail.com> Acked-by: Michael Buesch <mb@bu3sch.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/b43/dma.c2
-rw-r--r--drivers/net/wireless/b43/main.c122
-rw-r--r--drivers/net/wireless/b43/pio.c4
-rw-r--r--drivers/net/wireless/b43/xmit.c28
-rw-r--r--drivers/net/wireless/b43/xmit.h3
5 files changed, 147 insertions, 12 deletions
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 41a0e9c2b339..289aaf6dfe79 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1188,7 +1188,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
1188 header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]); 1188 header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]);
1189 cookie = generate_cookie(ring, slot); 1189 cookie = generate_cookie(ring, slot);
1190 err = b43_generate_txhdr(ring->dev, header, 1190 err = b43_generate_txhdr(ring->dev, header,
1191 skb->data, skb->len, info, cookie); 1191 skb, info, cookie);
1192 if (unlikely(err)) { 1192 if (unlikely(err)) {
1193 ring->current_slot = old_top_slot; 1193 ring->current_slot = old_top_slot;
1194 ring->used_slots = old_used_slots; 1194 ring->used_slots = old_used_slots;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 78ddbc7f836b..f5bdf1cae1d1 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -80,6 +80,10 @@ static int modparam_nohwcrypt;
80module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); 80module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
81MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); 81MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
82 82
83static int modparam_hwtkip;
84module_param_named(hwtkip, modparam_hwtkip, int, 0444);
85MODULE_PARM_DESC(hwtkip, "Enable hardware tkip.");
86
83static int modparam_qos = 1; 87static int modparam_qos = 1;
84module_param_named(qos, modparam_qos, int, 0444); 88module_param_named(qos, modparam_qos, int, 0444);
85MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); 89MODULE_PARM_DESC(qos, "Enable QOS support (default on)");
@@ -834,6 +838,85 @@ static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr)
834 (index * 2) + 1, addrtmp[1]); 838 (index * 2) + 1, addrtmp[1]);
835} 839}
836 840
841/* The ucode will use phase1 key with TEK key to decrypt rx packets.
842 * When a packet is received, the iv32 is checked.
843 * - if it doesn't the packet is returned without modification (and software
844 * decryption can be done). That's what happen when iv16 wrap.
845 * - if it does, the rc4 key is computed, and decryption is tried.
846 * Either it will success and B43_RX_MAC_DEC is returned,
847 * either it fails and B43_RX_MAC_DEC|B43_RX_MAC_DECERR is returned
848 * and the packet is not usable (it got modified by the ucode).
849 * So in order to never have B43_RX_MAC_DECERR, we should provide
850 * a iv32 and phase1key that match. Because we drop packets in case of
851 * B43_RX_MAC_DECERR, if we have a correct iv32 but a wrong phase1key, all
852 * packets will be lost without higher layer knowing (ie no resync possible
853 * until next wrap).
854 *
855 * NOTE : this should support 50 key like RCMTA because
856 * (B43_SHM_SH_KEYIDXBLOCK - B43_SHM_SH_TKIPTSCTTAK)/14 = 50
857 */
858static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32,
859 u16 *phase1key)
860{
861 unsigned int i;
862 u32 offset;
863 u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
864
865 if (!modparam_hwtkip)
866 return;
867
868 if (b43_new_kidx_api(dev))
869 pairwise_keys_start = B43_NR_GROUP_KEYS;
870
871 B43_WARN_ON(index < pairwise_keys_start);
872 /* We have four default TX keys and possibly four default RX keys.
873 * Physical mac 0 is mapped to physical key 4 or 8, depending
874 * on the firmware version.
875 * So we must adjust the index here.
876 */
877 index -= pairwise_keys_start;
878 B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS);
879
880 if (b43_debug(dev, B43_DBG_KEYS)) {
881 b43dbg(dev->wl, "rx_tkip_phase1_write : idx 0x%x, iv32 0x%x\n",
882 index, iv32);
883 }
884 /* Write the key to the RX tkip shared mem */
885 offset = B43_SHM_SH_TKIPTSCTTAK + index * (10 + 4);
886 for (i = 0; i < 10; i += 2) {
887 b43_shm_write16(dev, B43_SHM_SHARED, offset + i,
888 phase1key ? phase1key[i / 2] : 0);
889 }
890 b43_shm_write16(dev, B43_SHM_SHARED, offset + i, iv32);
891 b43_shm_write16(dev, B43_SHM_SHARED, offset + i + 2, iv32 >> 16);
892}
893
894static void b43_op_update_tkip_key(struct ieee80211_hw *hw,
895 struct ieee80211_key_conf *keyconf, const u8 *addr,
896 u32 iv32, u16 *phase1key)
897{
898 struct b43_wl *wl = hw_to_b43_wl(hw);
899 struct b43_wldev *dev;
900 int index = keyconf->hw_key_idx;
901
902 if (B43_WARN_ON(!modparam_hwtkip))
903 return;
904
905 mutex_lock(&wl->mutex);
906
907 dev = wl->current_dev;
908 if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
909 goto out_unlock;
910
911 keymac_write(dev, index, NULL); /* First zero out mac to avoid race */
912
913 rx_tkip_phase1_write(dev, index, iv32, phase1key);
914 keymac_write(dev, index, addr);
915
916out_unlock:
917 mutex_unlock(&wl->mutex);
918}
919
837static void do_key_write(struct b43_wldev *dev, 920static void do_key_write(struct b43_wldev *dev,
838 u8 index, u8 algorithm, 921 u8 index, u8 algorithm,
839 const u8 *key, size_t key_len, const u8 *mac_addr) 922 const u8 *key, size_t key_len, const u8 *mac_addr)
@@ -849,6 +932,19 @@ static void do_key_write(struct b43_wldev *dev,
849 932
850 if (index >= pairwise_keys_start) 933 if (index >= pairwise_keys_start)
851 keymac_write(dev, index, NULL); /* First zero out mac. */ 934 keymac_write(dev, index, NULL); /* First zero out mac. */
935 if (algorithm == B43_SEC_ALGO_TKIP) {
936 /*
937 * We should provide an initial iv32, phase1key pair.
938 * We could start with iv32=0 and compute the corresponding
939 * phase1key, but this means calling ieee80211_get_tkip_key
940 * with a fake skb (or export other tkip function).
941 * Because we are lazy we hope iv32 won't start with
942 * 0xffffffff and let's b43_op_update_tkip_key provide a
943 * correct pair.
944 */
945 rx_tkip_phase1_write(dev, index, 0xffffffff, (u16*)buf);
946 } else if (index >= pairwise_keys_start) /* clear it */
947 rx_tkip_phase1_write(dev, index, 0, NULL);
852 if (key) 948 if (key)
853 memcpy(buf, key, key_len); 949 memcpy(buf, key, key_len);
854 key_write(dev, index, algorithm, buf); 950 key_write(dev, index, algorithm, buf);
@@ -867,6 +963,15 @@ static int b43_key_write(struct b43_wldev *dev,
867 int i; 963 int i;
868 int pairwise_keys_start; 964 int pairwise_keys_start;
869 965
966 /* For ALG_TKIP the key is encoded as a 256-bit (32 byte) data block:
967 * - Temporal Encryption Key (128 bits)
968 * - Temporal Authenticator Tx MIC Key (64 bits)
969 * - Temporal Authenticator Rx MIC Key (64 bits)
970 *
971 * Hardware only store TEK
972 */
973 if (algorithm == B43_SEC_ALGO_TKIP && key_len == 32)
974 key_len = 16;
870 if (key_len > B43_SEC_KEYSIZE) 975 if (key_len > B43_SEC_KEYSIZE)
871 return -EINVAL; 976 return -EINVAL;
872 for (i = 0; i < ARRAY_SIZE(dev->key); i++) { 977 for (i = 0; i < ARRAY_SIZE(dev->key); i++) {
@@ -973,6 +1078,14 @@ static void b43_dump_keymemory(struct b43_wldev *dev)
973 printk(" Algo: %04X/%02X", algo, key->algorithm); 1078 printk(" Algo: %04X/%02X", algo, key->algorithm);
974 1079
975 if (index >= pairwise_keys_start) { 1080 if (index >= pairwise_keys_start) {
1081 if (key->algorithm == B43_SEC_ALGO_TKIP) {
1082 printk(" TKIP: ");
1083 offset = B43_SHM_SH_TKIPTSCTTAK + (index - 4) * (10 + 4);
1084 for (i = 0; i < 14; i += 2) {
1085 u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i);
1086 printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF));
1087 }
1088 }
976 rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, 1089 rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA,
977 ((index - pairwise_keys_start) * 2) + 0); 1090 ((index - pairwise_keys_start) * 2) + 0);
978 rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, 1091 rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA,
@@ -3620,8 +3733,10 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3620 3733
3621 switch (cmd) { 3734 switch (cmd) {
3622 case SET_KEY: 3735 case SET_KEY:
3623 if (algorithm == B43_SEC_ALGO_TKIP) { 3736 if (algorithm == B43_SEC_ALGO_TKIP &&
3624 /* FIXME: No TKIP hardware encryption for now. */ 3737 (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ||
3738 !modparam_hwtkip)) {
3739 /* We support only pairwise key */
3625 err = -EOPNOTSUPP; 3740 err = -EOPNOTSUPP;
3626 goto out_unlock; 3741 goto out_unlock;
3627 } 3742 }
@@ -3651,6 +3766,8 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3651 b43_hf_read(dev) & ~B43_HF_USEDEFKEYS); 3766 b43_hf_read(dev) & ~B43_HF_USEDEFKEYS);
3652 } 3767 }
3653 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; 3768 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
3769 if (algorithm == B43_SEC_ALGO_TKIP)
3770 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
3654 break; 3771 break;
3655 case DISABLE_KEY: { 3772 case DISABLE_KEY: {
3656 err = b43_key_clear(dev, key->hw_key_idx); 3773 err = b43_key_clear(dev, key->hw_key_idx);
@@ -4378,6 +4495,7 @@ static const struct ieee80211_ops b43_hw_ops = {
4378 .bss_info_changed = b43_op_bss_info_changed, 4495 .bss_info_changed = b43_op_bss_info_changed,
4379 .configure_filter = b43_op_configure_filter, 4496 .configure_filter = b43_op_configure_filter,
4380 .set_key = b43_op_set_key, 4497 .set_key = b43_op_set_key,
4498 .update_tkip_key = b43_op_update_tkip_key,
4381 .get_stats = b43_op_get_stats, 4499 .get_stats = b43_op_get_stats,
4382 .get_tx_stats = b43_op_get_tx_stats, 4500 .get_tx_stats = b43_op_get_tx_stats,
4383 .get_tsf = b43_op_get_tsf, 4501 .get_tsf = b43_op_get_tsf,
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 73c047d8de40..3fd653c78b10 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -461,8 +461,8 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
461 461
462 cookie = generate_cookie(q, pack); 462 cookie = generate_cookie(q, pack);
463 hdrlen = b43_txhdr_size(q->dev); 463 hdrlen = b43_txhdr_size(q->dev);
464 err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data, 464 err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb,
465 skb->len, info, cookie); 465 info, cookie);
466 if (err) 466 if (err)
467 return err; 467 return err;
468 468
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index be1c53ecdb01..e7075d2c7757 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -180,11 +180,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate)
180/* Generate a TX data header. */ 180/* Generate a TX data header. */
181int b43_generate_txhdr(struct b43_wldev *dev, 181int b43_generate_txhdr(struct b43_wldev *dev,
182 u8 *_txhdr, 182 u8 *_txhdr,
183 const unsigned char *fragment_data, 183 struct sk_buff *skb_frag,
184 unsigned int fragment_len,
185 struct ieee80211_tx_info *info, 184 struct ieee80211_tx_info *info,
186 u16 cookie) 185 u16 cookie)
187{ 186{
187 const unsigned char *fragment_data = skb_frag->data;
188 unsigned int fragment_len = skb_frag->len;
188 struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; 189 struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
189 const struct b43_phy *phy = &dev->phy; 190 const struct b43_phy *phy = &dev->phy;
190 const struct ieee80211_hdr *wlhdr = 191 const struct ieee80211_hdr *wlhdr =
@@ -258,9 +259,26 @@ int b43_generate_txhdr(struct b43_wldev *dev,
258 mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & 259 mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
259 B43_TXH_MAC_KEYALG; 260 B43_TXH_MAC_KEYALG;
260 wlhdr_len = ieee80211_hdrlen(fctl); 261 wlhdr_len = ieee80211_hdrlen(fctl);
261 iv_len = min((size_t) info->control.hw_key->iv_len, 262 if (key->algorithm == B43_SEC_ALGO_TKIP) {
262 ARRAY_SIZE(txhdr->iv)); 263 u16 phase1key[5];
263 memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); 264 int i;
265 /* we give the phase1key and iv16 here, the key is stored in
266 * shm. With that the hardware can do phase 2 and encryption.
267 */
268 ieee80211_get_tkip_key(info->control.hw_key, skb_frag,
269 IEEE80211_TKIP_P1_KEY, (u8*)phase1key);
270 /* phase1key is in host endian */
271 for (i = 0; i < 5; i++)
272 phase1key[i] = cpu_to_le16(phase1key[i]);
273
274 memcpy(txhdr->iv, phase1key, 10);
275 /* iv16 */
276 memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3);
277 } else {
278 iv_len = min((size_t) info->control.hw_key->iv_len,
279 ARRAY_SIZE(txhdr->iv));
280 memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
281 }
264 } 282 }
265 if (b43_is_old_txhdr_format(dev)) { 283 if (b43_is_old_txhdr_format(dev)) {
266 b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), 284 b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index 4fb2a190f7a7..3530de871873 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -176,8 +176,7 @@ size_t b43_txhdr_size(struct b43_wldev *dev)
176 176
177int b43_generate_txhdr(struct b43_wldev *dev, 177int b43_generate_txhdr(struct b43_wldev *dev,
178 u8 * txhdr, 178 u8 * txhdr,
179 const unsigned char *fragment_data, 179 struct sk_buff *skb_frag,
180 unsigned int fragment_len,
181 struct ieee80211_tx_info *txctl, u16 cookie); 180 struct ieee80211_tx_info *txctl, u16 cookie);
182 181
183/* Transmit Status */ 182/* Transmit Status */