blob: 29a2961af5fc28f86441642c2165c613c4488fba [file] [log] [blame]
Bruno Randolf1bba5b72010-09-08 16:04:38 +09001/*
2 * Copyright (c) 2009 Atheros Communications Inc.
3 * Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <asm/unaligned.h>
19#include <net/mac80211.h>
20
21#include "ath.h"
22#include "reg.h"
Bruno Randolf1bba5b72010-09-08 16:04:38 +090023
24#define REG_READ (common->ops->read)
25#define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg)
26
27#define IEEE80211_WEP_NKID 4 /* number of key ids */
28
29/************************/
30/* Key Cache Management */
31/************************/
32
33bool ath_hw_keyreset(struct ath_common *common, u16 entry)
34{
35 u32 keyType;
36 void *ah = common->ah;
37
38 if (entry >= common->keymax) {
Joe Perches38002762010-12-02 19:12:36 -080039 ath_err(common, "keycache entry %u out of range\n", entry);
Bruno Randolf1bba5b72010-09-08 16:04:38 +090040 return false;
41 }
42
43 keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
44
45 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
46 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
47 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
48 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
49 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
50 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
51 REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
52 REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
53
54 if (keyType == AR_KEYTABLE_TYPE_TKIP) {
55 u16 micentry = entry + 64;
56
57 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
58 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
59 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
60 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
61
62 }
63
64 return true;
65}
66EXPORT_SYMBOL(ath_hw_keyreset);
67
Luis R. Rodrigueza3685d12010-10-20 06:59:36 -070068static bool ath_hw_keysetmac(struct ath_common *common,
69 u16 entry, const u8 *mac)
Bruno Randolf1bba5b72010-09-08 16:04:38 +090070{
71 u32 macHi, macLo;
72 u32 unicast_flag = AR_KEYTABLE_VALID;
73 void *ah = common->ah;
74
75 if (entry >= common->keymax) {
Joe Perches38002762010-12-02 19:12:36 -080076 ath_err(common, "keycache entry %u out of range\n", entry);
Bruno Randolf1bba5b72010-09-08 16:04:38 +090077 return false;
78 }
79
80 if (mac != NULL) {
81 /*
82 * AR_KEYTABLE_VALID indicates that the address is a unicast
83 * address, which must match the transmitter address for
84 * decrypting frames.
85 * Not setting this bit allows the hardware to use the key
86 * for multicast frame decryption.
87 */
88 if (mac[0] & 0x01)
89 unicast_flag = 0;
90
91 macHi = (mac[5] << 8) | mac[4];
92 macLo = (mac[3] << 24) |
93 (mac[2] << 16) |
94 (mac[1] << 8) |
95 mac[0];
96 macLo >>= 1;
97 macLo |= (macHi & 1) << 31;
98 macHi >>= 1;
99 } else {
100 macLo = macHi = 0;
101 }
102 REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
103 REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
104
105 return true;
106}
107
Luis R. Rodriguezf8c2a082010-10-20 06:59:37 -0700108static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
109 const struct ath_keyval *k,
110 const u8 *mac)
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900111{
112 void *ah = common->ah;
113 u32 key0, key1, key2, key3, key4;
114 u32 keyType;
115
116 if (entry >= common->keymax) {
Joe Perches38002762010-12-02 19:12:36 -0800117 ath_err(common, "keycache entry %u out of range\n", entry);
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900118 return false;
119 }
120
121 switch (k->kv_type) {
122 case ATH_CIPHER_AES_OCB:
123 keyType = AR_KEYTABLE_TYPE_AES;
124 break;
125 case ATH_CIPHER_AES_CCM:
126 if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) {
Joe Perches226afe62010-12-02 19:12:37 -0800127 ath_dbg(common, ATH_DBG_ANY,
128 "AES-CCM not supported by this mac rev\n");
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900129 return false;
130 }
131 keyType = AR_KEYTABLE_TYPE_CCM;
132 break;
133 case ATH_CIPHER_TKIP:
134 keyType = AR_KEYTABLE_TYPE_TKIP;
135 if (entry + 64 >= common->keymax) {
Joe Perches226afe62010-12-02 19:12:37 -0800136 ath_dbg(common, ATH_DBG_ANY,
137 "entry %u inappropriate for TKIP\n", entry);
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900138 return false;
139 }
140 break;
141 case ATH_CIPHER_WEP:
142 if (k->kv_len < WLAN_KEY_LEN_WEP40) {
Joe Perches226afe62010-12-02 19:12:37 -0800143 ath_dbg(common, ATH_DBG_ANY,
144 "WEP key length %u too small\n", k->kv_len);
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900145 return false;
146 }
147 if (k->kv_len <= WLAN_KEY_LEN_WEP40)
148 keyType = AR_KEYTABLE_TYPE_40;
149 else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
150 keyType = AR_KEYTABLE_TYPE_104;
151 else
152 keyType = AR_KEYTABLE_TYPE_128;
153 break;
154 case ATH_CIPHER_CLR:
155 keyType = AR_KEYTABLE_TYPE_CLR;
156 break;
157 default:
Joe Perches38002762010-12-02 19:12:36 -0800158 ath_err(common, "cipher %u not supported\n", k->kv_type);
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900159 return false;
160 }
161
162 key0 = get_unaligned_le32(k->kv_val + 0);
163 key1 = get_unaligned_le16(k->kv_val + 4);
164 key2 = get_unaligned_le32(k->kv_val + 6);
165 key3 = get_unaligned_le16(k->kv_val + 10);
166 key4 = get_unaligned_le32(k->kv_val + 12);
167 if (k->kv_len <= WLAN_KEY_LEN_WEP104)
168 key4 &= 0xff;
169
170 /*
171 * Note: Key cache registers access special memory area that requires
172 * two 32-bit writes to actually update the values in the internal
173 * memory. Consequently, the exact order and pairs used here must be
174 * maintained.
175 */
176
177 if (keyType == AR_KEYTABLE_TYPE_TKIP) {
178 u16 micentry = entry + 64;
179
180 /*
181 * Write inverted key[47:0] first to avoid Michael MIC errors
182 * on frames that could be sent or received at the same time.
183 * The correct key will be written in the end once everything
184 * else is ready.
185 */
186 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
187 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
188
189 /* Write key[95:48] */
190 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
191 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
192
193 /* Write key[127:96] and key type */
194 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
195 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
196
197 /* Write MAC address for the entry */
198 (void) ath_hw_keysetmac(common, entry, mac);
199
Bruno Randolf117675d2010-09-08 16:04:54 +0900200 if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900201 /*
202 * TKIP uses two key cache entries:
203 * Michael MIC TX/RX keys in the same key cache entry
204 * (idx = main index + 64):
205 * key0 [31:0] = RX key [31:0]
206 * key1 [15:0] = TX key [31:16]
207 * key1 [31:16] = reserved
208 * key2 [31:0] = RX key [63:32]
209 * key3 [15:0] = TX key [15:0]
210 * key3 [31:16] = reserved
211 * key4 [31:0] = TX key [63:32]
212 */
213 u32 mic0, mic1, mic2, mic3, mic4;
214
215 mic0 = get_unaligned_le32(k->kv_mic + 0);
216 mic2 = get_unaligned_le32(k->kv_mic + 4);
217 mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
218 mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
219 mic4 = get_unaligned_le32(k->kv_txmic + 4);
220
221 /* Write RX[31:0] and TX[31:16] */
222 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
223 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
224
225 /* Write RX[63:32] and TX[15:0] */
226 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
227 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
228
229 /* Write TX[63:32] and keyType(reserved) */
230 REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
231 REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
232 AR_KEYTABLE_TYPE_CLR);
233
234 } else {
235 /*
236 * TKIP uses four key cache entries (two for group
237 * keys):
238 * Michael MIC TX/RX keys are in different key cache
239 * entries (idx = main index + 64 for TX and
240 * main index + 32 + 96 for RX):
241 * key0 [31:0] = TX/RX MIC key [31:0]
242 * key1 [31:0] = reserved
243 * key2 [31:0] = TX/RX MIC key [63:32]
244 * key3 [31:0] = reserved
245 * key4 [31:0] = reserved
246 *
247 * Upper layer code will call this function separately
248 * for TX and RX keys when these registers offsets are
249 * used.
250 */
251 u32 mic0, mic2;
252
253 mic0 = get_unaligned_le32(k->kv_mic + 0);
254 mic2 = get_unaligned_le32(k->kv_mic + 4);
255
256 /* Write MIC key[31:0] */
257 REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
258 REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
259
260 /* Write MIC key[63:32] */
261 REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
262 REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
263
264 /* Write TX[63:32] and keyType(reserved) */
265 REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
266 REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
267 AR_KEYTABLE_TYPE_CLR);
268 }
269
270 /* MAC address registers are reserved for the MIC entry */
271 REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
272 REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
273
274 /*
275 * Write the correct (un-inverted) key[47:0] last to enable
276 * TKIP now that all other registers are set with correct
277 * values.
278 */
279 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
280 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
281 } else {
282 /* Write key[47:0] */
283 REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
284 REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
285
286 /* Write key[95:48] */
287 REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
288 REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
289
290 /* Write key[127:96] and key type */
291 REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
292 REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
293
294 /* Write MAC address for the entry */
295 (void) ath_hw_keysetmac(common, entry, mac);
296 }
297
298 return true;
299}
300
301static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
302 struct ath_keyval *hk, const u8 *addr,
303 bool authenticator)
304{
305 const u8 *key_rxmic;
306 const u8 *key_txmic;
307
308 key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
309 key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
310
311 if (addr == NULL) {
312 /*
313 * Group key installation - only two key cache entries are used
314 * regardless of splitmic capability since group key is only
315 * used either for TX or RX.
316 */
317 if (authenticator) {
318 memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
319 memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
320 } else {
321 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
322 memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
323 }
324 return ath_hw_set_keycache_entry(common, keyix, hk, addr);
325 }
Bruno Randolf117675d2010-09-08 16:04:54 +0900326 if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900327 /* TX and RX keys share the same key cache entry. */
328 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
329 memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
330 return ath_hw_set_keycache_entry(common, keyix, hk, addr);
331 }
332
333 /* Separate key cache entries for TX and RX */
334
335 /* TX key goes at first index, RX key at +32. */
336 memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
337 if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) {
338 /* TX MIC entry failed. No need to proceed further */
Joe Perches38002762010-12-02 19:12:36 -0800339 ath_err(common, "Setting TX MIC Key Failed\n");
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900340 return 0;
341 }
342
343 memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
344 /* XXX delete tx key on failure? */
345 return ath_hw_set_keycache_entry(common, keyix + 32, hk, addr);
346}
347
348static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
349{
350 int i;
351
352 for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
353 if (test_bit(i, common->keymap) ||
354 test_bit(i + 64, common->keymap))
355 continue; /* At least one part of TKIP key allocated */
Bruno Randolf117675d2010-09-08 16:04:54 +0900356 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) &&
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900357 (test_bit(i + 32, common->keymap) ||
358 test_bit(i + 64 + 32, common->keymap)))
359 continue; /* At least one part of TKIP key allocated */
360
361 /* Found a free slot for a TKIP key */
362 return i;
363 }
364 return -1;
365}
366
367static int ath_reserve_key_cache_slot(struct ath_common *common,
368 u32 cipher)
369{
370 int i;
371
372 if (cipher == WLAN_CIPHER_SUITE_TKIP)
373 return ath_reserve_key_cache_slot_tkip(common);
374
375 /* First, try to find slots that would not be available for TKIP. */
Bruno Randolf117675d2010-09-08 16:04:54 +0900376 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900377 for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
378 if (!test_bit(i, common->keymap) &&
379 (test_bit(i + 32, common->keymap) ||
380 test_bit(i + 64, common->keymap) ||
381 test_bit(i + 64 + 32, common->keymap)))
382 return i;
383 if (!test_bit(i + 32, common->keymap) &&
384 (test_bit(i, common->keymap) ||
385 test_bit(i + 64, common->keymap) ||
386 test_bit(i + 64 + 32, common->keymap)))
387 return i + 32;
388 if (!test_bit(i + 64, common->keymap) &&
389 (test_bit(i , common->keymap) ||
390 test_bit(i + 32, common->keymap) ||
391 test_bit(i + 64 + 32, common->keymap)))
392 return i + 64;
393 if (!test_bit(i + 64 + 32, common->keymap) &&
394 (test_bit(i, common->keymap) ||
395 test_bit(i + 32, common->keymap) ||
396 test_bit(i + 64, common->keymap)))
397 return i + 64 + 32;
398 }
399 } else {
400 for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
401 if (!test_bit(i, common->keymap) &&
402 test_bit(i + 64, common->keymap))
403 return i;
404 if (test_bit(i, common->keymap) &&
405 !test_bit(i + 64, common->keymap))
406 return i + 64;
407 }
408 }
409
410 /* No partially used TKIP slots, pick any available slot */
411 for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
412 /* Do not allow slots that could be needed for TKIP group keys
413 * to be used. This limitation could be removed if we know that
414 * TKIP will not be used. */
415 if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
416 continue;
Bruno Randolf117675d2010-09-08 16:04:54 +0900417 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900418 if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
419 continue;
420 if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
421 continue;
422 }
423
424 if (!test_bit(i, common->keymap))
425 return i; /* Found a free slot for a key */
426 }
427
428 /* No free slot found */
429 return -1;
430}
431
432/*
433 * Configure encryption in the HW.
434 */
435int ath_key_config(struct ath_common *common,
436 struct ieee80211_vif *vif,
437 struct ieee80211_sta *sta,
438 struct ieee80211_key_conf *key)
439{
440 struct ath_keyval hk;
441 const u8 *mac = NULL;
442 u8 gmac[ETH_ALEN];
443 int ret = 0;
444 int idx;
445
446 memset(&hk, 0, sizeof(hk));
447
448 switch (key->cipher) {
449 case WLAN_CIPHER_SUITE_WEP40:
450 case WLAN_CIPHER_SUITE_WEP104:
451 hk.kv_type = ATH_CIPHER_WEP;
452 break;
453 case WLAN_CIPHER_SUITE_TKIP:
454 hk.kv_type = ATH_CIPHER_TKIP;
455 break;
456 case WLAN_CIPHER_SUITE_CCMP:
457 hk.kv_type = ATH_CIPHER_AES_CCM;
458 break;
459 default:
460 return -EOPNOTSUPP;
461 }
462
463 hk.kv_len = key->keylen;
464 memcpy(hk.kv_val, key->key, key->keylen);
465
466 if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
467 switch (vif->type) {
468 case NL80211_IFTYPE_AP:
469 memcpy(gmac, vif->addr, ETH_ALEN);
470 gmac[0] |= 0x01;
471 mac = gmac;
472 idx = ath_reserve_key_cache_slot(common, key->cipher);
473 break;
474 case NL80211_IFTYPE_ADHOC:
475 if (!sta) {
476 idx = key->keyidx;
477 break;
478 }
479 memcpy(gmac, sta->addr, ETH_ALEN);
480 gmac[0] |= 0x01;
481 mac = gmac;
482 idx = ath_reserve_key_cache_slot(common, key->cipher);
483 break;
484 default:
485 idx = key->keyidx;
486 break;
487 }
488 } else if (key->keyidx) {
489 if (WARN_ON(!sta))
490 return -EOPNOTSUPP;
491 mac = sta->addr;
492
493 if (vif->type != NL80211_IFTYPE_AP) {
494 /* Only keyidx 0 should be used with unicast key, but
495 * allow this for client mode for now. */
496 idx = key->keyidx;
497 } else
498 return -EIO;
499 } else {
500 if (WARN_ON(!sta))
501 return -EOPNOTSUPP;
502 mac = sta->addr;
503
504 idx = ath_reserve_key_cache_slot(common, key->cipher);
505 }
506
507 if (idx < 0)
508 return -ENOSPC; /* no free key cache entries */
509
510 if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
511 ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
512 vif->type == NL80211_IFTYPE_AP);
513 else
514 ret = ath_hw_set_keycache_entry(common, idx, &hk, mac);
515
516 if (!ret)
517 return -EIO;
518
519 set_bit(idx, common->keymap);
520 if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
521 set_bit(idx + 64, common->keymap);
522 set_bit(idx, common->tkip_keymap);
523 set_bit(idx + 64, common->tkip_keymap);
Bruno Randolf117675d2010-09-08 16:04:54 +0900524 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900525 set_bit(idx + 32, common->keymap);
526 set_bit(idx + 64 + 32, common->keymap);
527 set_bit(idx + 32, common->tkip_keymap);
528 set_bit(idx + 64 + 32, common->tkip_keymap);
529 }
530 }
531
532 return idx;
533}
534EXPORT_SYMBOL(ath_key_config);
535
536/*
537 * Delete Key.
538 */
539void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
540{
541 ath_hw_keyreset(common, key->hw_key_idx);
542 if (key->hw_key_idx < IEEE80211_WEP_NKID)
543 return;
544
545 clear_bit(key->hw_key_idx, common->keymap);
546 if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
547 return;
548
549 clear_bit(key->hw_key_idx + 64, common->keymap);
550
551 clear_bit(key->hw_key_idx, common->tkip_keymap);
552 clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
553
Bruno Randolf117675d2010-09-08 16:04:54 +0900554 if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
Bruno Randolf1bba5b72010-09-08 16:04:38 +0900555 ath_hw_keyreset(common, key->hw_key_idx + 32);
556 clear_bit(key->hw_key_idx + 32, common->keymap);
557 clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
558
559 clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
560 clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
561 }
562}
563EXPORT_SYMBOL(ath_key_delete);