Branch data Line data Source code
1 : : /*
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 <linux/export.h>
19 : : #include <asm/unaligned.h>
20 : : #include <net/mac80211.h>
21 : :
22 : : #include "ath.h"
23 : : #include "reg.h"
24 : :
25 : : #define REG_READ (common->ops->read)
26 : : #define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg)
27 : : #define ENABLE_REGWRITE_BUFFER(_ah) \
28 : : if (common->ops->enable_write_buffer) \
29 : : common->ops->enable_write_buffer((_ah));
30 : :
31 : : #define REGWRITE_BUFFER_FLUSH(_ah) \
32 : : if (common->ops->write_flush) \
33 : : common->ops->write_flush((_ah));
34 : :
35 : :
36 : : #define IEEE80211_WEP_NKID 4 /* number of key ids */
37 : :
38 : : /************************/
39 : : /* Key Cache Management */
40 : : /************************/
41 : :
42 : 0 : bool ath_hw_keyreset(struct ath_common *common, u16 entry)
43 : : {
44 : 0 : u32 keyType;
45 : 0 : void *ah = common->ah;
46 : :
47 [ # # ]: 0 : if (entry >= common->keymax) {
48 : 0 : ath_err(common, "keyreset: keycache entry %u out of range\n",
49 : : entry);
50 : 0 : return false;
51 : : }
52 : :
53 : 0 : keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
54 : :
55 [ # # ]: 0 : ENABLE_REGWRITE_BUFFER(ah);
56 : :
57 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
58 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
59 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
60 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
61 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
62 : 0 : REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
63 : 0 : REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
64 : 0 : REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
65 : :
66 [ # # ]: 0 : if (keyType == AR_KEYTABLE_TYPE_TKIP) {
67 : 0 : u16 micentry = entry + 64;
68 : :
69 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
70 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
71 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
72 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
73 [ # # ]: 0 : if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
74 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
75 : 0 : REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
76 : : AR_KEYTABLE_TYPE_CLR);
77 : : }
78 : :
79 : : }
80 : :
81 [ # # ]: 0 : REGWRITE_BUFFER_FLUSH(ah);
82 : :
83 : : return true;
84 : : }
85 : : EXPORT_SYMBOL(ath_hw_keyreset);
86 : :
87 : 0 : static bool ath_hw_keysetmac(struct ath_common *common,
88 : : u16 entry, const u8 *mac)
89 : : {
90 : 0 : u32 macHi, macLo;
91 : 0 : u32 unicast_flag = AR_KEYTABLE_VALID;
92 : 0 : void *ah = common->ah;
93 : :
94 [ # # ]: 0 : if (entry >= common->keymax) {
95 : 0 : ath_err(common, "keysetmac: keycache entry %u out of range\n",
96 : : entry);
97 : 0 : return false;
98 : : }
99 : :
100 [ # # ]: 0 : if (mac != NULL) {
101 : : /*
102 : : * AR_KEYTABLE_VALID indicates that the address is a unicast
103 : : * address, which must match the transmitter address for
104 : : * decrypting frames.
105 : : * Not setting this bit allows the hardware to use the key
106 : : * for multicast frame decryption.
107 : : */
108 [ # # ]: 0 : if (mac[0] & 0x01)
109 : 0 : unicast_flag = 0;
110 : :
111 : 0 : macLo = get_unaligned_le32(mac);
112 : 0 : macHi = get_unaligned_le16(mac + 4);
113 : 0 : macLo >>= 1;
114 : 0 : macLo |= (macHi & 1) << 31;
115 : 0 : macHi >>= 1;
116 : : } else {
117 : : macLo = macHi = 0;
118 : : }
119 [ # # ]: 0 : ENABLE_REGWRITE_BUFFER(ah);
120 : :
121 : 0 : REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
122 : 0 : REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
123 : :
124 [ # # ]: 0 : REGWRITE_BUFFER_FLUSH(ah);
125 : :
126 : : return true;
127 : : }
128 : :
129 : 0 : static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
130 : : const struct ath_keyval *k,
131 : : const u8 *mac)
132 : : {
133 : 0 : void *ah = common->ah;
134 : 0 : u32 key0, key1, key2, key3, key4;
135 : 0 : u32 keyType;
136 : :
137 [ # # ]: 0 : if (entry >= common->keymax) {
138 : 0 : ath_err(common, "set-entry: keycache entry %u out of range\n",
139 : : entry);
140 : 0 : return false;
141 : : }
142 : :
143 [ # # # # : 0 : switch (k->kv_type) {
# # ]
144 : : case ATH_CIPHER_AES_OCB:
145 : : keyType = AR_KEYTABLE_TYPE_AES;
146 : : break;
147 : 0 : case ATH_CIPHER_AES_CCM:
148 [ # # ]: 0 : if (!(common->crypt_caps & ATH_CRYPT_CAP_CIPHER_AESCCM)) {
149 [ # # ]: 0 : ath_dbg(common, ANY,
150 : : "AES-CCM not supported by this mac rev\n");
151 : 0 : return false;
152 : : }
153 : : keyType = AR_KEYTABLE_TYPE_CCM;
154 : : break;
155 : 0 : case ATH_CIPHER_TKIP:
156 : 0 : keyType = AR_KEYTABLE_TYPE_TKIP;
157 [ # # ]: 0 : if (entry + 64 >= common->keymax) {
158 [ # # ]: 0 : ath_dbg(common, ANY,
159 : : "entry %u inappropriate for TKIP\n", entry);
160 : 0 : return false;
161 : : }
162 : : break;
163 : 0 : case ATH_CIPHER_WEP:
164 [ # # ]: 0 : if (k->kv_len < WLAN_KEY_LEN_WEP40) {
165 [ # # ]: 0 : ath_dbg(common, ANY, "WEP key length %u too small\n",
166 : : k->kv_len);
167 : 0 : return false;
168 : : }
169 [ # # ]: 0 : if (k->kv_len <= WLAN_KEY_LEN_WEP40)
170 : : keyType = AR_KEYTABLE_TYPE_40;
171 [ # # ]: 0 : else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
172 : : keyType = AR_KEYTABLE_TYPE_104;
173 : : else
174 : 0 : keyType = AR_KEYTABLE_TYPE_128;
175 : : break;
176 : 0 : case ATH_CIPHER_CLR:
177 : 0 : keyType = AR_KEYTABLE_TYPE_CLR;
178 : 0 : break;
179 : 0 : default:
180 : 0 : ath_err(common, "cipher %u not supported\n", k->kv_type);
181 : 0 : return false;
182 : : }
183 : :
184 [ # # ]: 0 : key0 = get_unaligned_le32(k->kv_val + 0);
185 [ # # ]: 0 : key1 = get_unaligned_le16(k->kv_val + 4);
186 : 0 : key2 = get_unaligned_le32(k->kv_val + 6);
187 : 0 : key3 = get_unaligned_le16(k->kv_val + 10);
188 : 0 : key4 = get_unaligned_le32(k->kv_val + 12);
189 [ # # ]: 0 : if (k->kv_len <= WLAN_KEY_LEN_WEP104)
190 : 0 : key4 &= 0xff;
191 : :
192 : : /*
193 : : * Note: Key cache registers access special memory area that requires
194 : : * two 32-bit writes to actually update the values in the internal
195 : : * memory. Consequently, the exact order and pairs used here must be
196 : : * maintained.
197 : : */
198 : :
199 [ # # ]: 0 : if (keyType == AR_KEYTABLE_TYPE_TKIP) {
200 : 0 : u16 micentry = entry + 64;
201 : :
202 : : /*
203 : : * Write inverted key[47:0] first to avoid Michael MIC errors
204 : : * on frames that could be sent or received at the same time.
205 : : * The correct key will be written in the end once everything
206 : : * else is ready.
207 : : */
208 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
209 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
210 : :
211 : : /* Write key[95:48] */
212 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
213 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
214 : :
215 : : /* Write key[127:96] and key type */
216 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
217 : 0 : REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
218 : :
219 : : /* Write MAC address for the entry */
220 : 0 : (void) ath_hw_keysetmac(common, entry, mac);
221 : :
222 [ # # ]: 0 : if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
223 : : /*
224 : : * TKIP uses two key cache entries:
225 : : * Michael MIC TX/RX keys in the same key cache entry
226 : : * (idx = main index + 64):
227 : : * key0 [31:0] = RX key [31:0]
228 : : * key1 [15:0] = TX key [31:16]
229 : : * key1 [31:16] = reserved
230 : : * key2 [31:0] = RX key [63:32]
231 : : * key3 [15:0] = TX key [15:0]
232 : : * key3 [31:16] = reserved
233 : : * key4 [31:0] = TX key [63:32]
234 : : */
235 : 0 : u32 mic0, mic1, mic2, mic3, mic4;
236 : :
237 [ # # ]: 0 : mic0 = get_unaligned_le32(k->kv_mic + 0);
238 : 0 : mic2 = get_unaligned_le32(k->kv_mic + 4);
239 [ # # ]: 0 : mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
240 : 0 : mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
241 : 0 : mic4 = get_unaligned_le32(k->kv_txmic + 4);
242 : :
243 [ # # ]: 0 : ENABLE_REGWRITE_BUFFER(ah);
244 : :
245 : : /* Write RX[31:0] and TX[31:16] */
246 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
247 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
248 : :
249 : : /* Write RX[63:32] and TX[15:0] */
250 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
251 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
252 : :
253 : : /* Write TX[63:32] and keyType(reserved) */
254 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
255 : 0 : REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
256 : : AR_KEYTABLE_TYPE_CLR);
257 : :
258 [ # # ]: 0 : REGWRITE_BUFFER_FLUSH(ah);
259 : :
260 : : } else {
261 : : /*
262 : : * TKIP uses four key cache entries (two for group
263 : : * keys):
264 : : * Michael MIC TX/RX keys are in different key cache
265 : : * entries (idx = main index + 64 for TX and
266 : : * main index + 32 + 96 for RX):
267 : : * key0 [31:0] = TX/RX MIC key [31:0]
268 : : * key1 [31:0] = reserved
269 : : * key2 [31:0] = TX/RX MIC key [63:32]
270 : : * key3 [31:0] = reserved
271 : : * key4 [31:0] = reserved
272 : : *
273 : : * Upper layer code will call this function separately
274 : : * for TX and RX keys when these registers offsets are
275 : : * used.
276 : : */
277 : 0 : u32 mic0, mic2;
278 : :
279 [ # # ]: 0 : mic0 = get_unaligned_le32(k->kv_mic + 0);
280 : 0 : mic2 = get_unaligned_le32(k->kv_mic + 4);
281 : :
282 [ # # ]: 0 : ENABLE_REGWRITE_BUFFER(ah);
283 : :
284 : : /* Write MIC key[31:0] */
285 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
286 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
287 : :
288 : : /* Write MIC key[63:32] */
289 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
290 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
291 : :
292 : : /* Write TX[63:32] and keyType(reserved) */
293 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
294 : 0 : REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
295 : : AR_KEYTABLE_TYPE_CLR);
296 : :
297 [ # # ]: 0 : REGWRITE_BUFFER_FLUSH(ah);
298 : : }
299 : :
300 [ # # ]: 0 : ENABLE_REGWRITE_BUFFER(ah);
301 : :
302 : : /* MAC address registers are reserved for the MIC entry */
303 : 0 : REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
304 : 0 : REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
305 : :
306 : : /*
307 : : * Write the correct (un-inverted) key[47:0] last to enable
308 : : * TKIP now that all other registers are set with correct
309 : : * values.
310 : : */
311 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
312 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
313 : :
314 [ # # ]: 0 : REGWRITE_BUFFER_FLUSH(ah);
315 : : } else {
316 [ # # ]: 0 : ENABLE_REGWRITE_BUFFER(ah);
317 : :
318 : : /* Write key[47:0] */
319 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
320 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
321 : :
322 : : /* Write key[95:48] */
323 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
324 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
325 : :
326 : : /* Write key[127:96] and key type */
327 : 0 : REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
328 : 0 : REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
329 : :
330 [ # # ]: 0 : REGWRITE_BUFFER_FLUSH(ah);
331 : :
332 : : /* Write MAC address for the entry */
333 : 0 : (void) ath_hw_keysetmac(common, entry, mac);
334 : : }
335 : :
336 : : return true;
337 : : }
338 : :
339 : 0 : static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
340 : : struct ath_keyval *hk, const u8 *addr,
341 : : bool authenticator)
342 : : {
343 : 0 : const u8 *key_rxmic;
344 : 0 : const u8 *key_txmic;
345 : :
346 : 0 : key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
347 : 0 : key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
348 : :
349 [ # # ]: 0 : if (addr == NULL) {
350 : : /*
351 : : * Group key installation - only two key cache entries are used
352 : : * regardless of splitmic capability since group key is only
353 : : * used either for TX or RX.
354 : : */
355 [ # # ]: 0 : if (authenticator) {
356 : 0 : memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
357 : 0 : memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic));
358 : : } else {
359 : 0 : memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
360 : 0 : memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
361 : : }
362 : 0 : return ath_hw_set_keycache_entry(common, keyix, hk, addr);
363 : : }
364 [ # # ]: 0 : if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
365 : : /* TX and RX keys share the same key cache entry. */
366 : 0 : memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
367 : 0 : memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
368 : 0 : return ath_hw_set_keycache_entry(common, keyix, hk, addr);
369 : : }
370 : :
371 : : /* Separate key cache entries for TX and RX */
372 : :
373 : : /* TX key goes at first index, RX key at +32. */
374 : 0 : memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
375 [ # # ]: 0 : if (!ath_hw_set_keycache_entry(common, keyix, hk, NULL)) {
376 : : /* TX MIC entry failed. No need to proceed further */
377 : 0 : ath_err(common, "Setting TX MIC Key Failed\n");
378 : 0 : return 0;
379 : : }
380 : :
381 : 0 : memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
382 : : /* XXX delete tx key on failure? */
383 : 0 : return ath_hw_set_keycache_entry(common, keyix + 32, hk, addr);
384 : : }
385 : :
386 : 0 : static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
387 : : {
388 : 0 : int i;
389 : :
390 [ # # ]: 0 : for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
391 [ # # # # ]: 0 : if (test_bit(i, common->keymap) ||
392 : 0 : test_bit(i + 64, common->keymap))
393 : 0 : continue; /* At least one part of TKIP key allocated */
394 [ # # # # ]: 0 : if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) &&
395 [ # # ]: 0 : (test_bit(i + 32, common->keymap) ||
396 : 0 : test_bit(i + 64 + 32, common->keymap)))
397 : 0 : continue; /* At least one part of TKIP key allocated */
398 : :
399 : : /* Found a free slot for a TKIP key */
400 : : return i;
401 : : }
402 : : return -1;
403 : : }
404 : :
405 : 0 : static int ath_reserve_key_cache_slot(struct ath_common *common,
406 : : u32 cipher)
407 : : {
408 : 0 : int i;
409 : :
410 [ # # ]: 0 : if (cipher == WLAN_CIPHER_SUITE_TKIP)
411 : 0 : return ath_reserve_key_cache_slot_tkip(common);
412 : :
413 : : /* First, try to find slots that would not be available for TKIP. */
414 [ # # ]: 0 : if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
415 [ # # ]: 0 : for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
416 [ # # # # ]: 0 : if (!test_bit(i, common->keymap) &&
417 [ # # ]: 0 : (test_bit(i + 32, common->keymap) ||
418 [ # # ]: 0 : test_bit(i + 64, common->keymap) ||
419 : 0 : test_bit(i + 64 + 32, common->keymap)))
420 : 0 : return i;
421 [ # # # # ]: 0 : if (!test_bit(i + 32, common->keymap) &&
422 [ # # ]: 0 : (test_bit(i, common->keymap) ||
423 [ # # ]: 0 : test_bit(i + 64, common->keymap) ||
424 : 0 : test_bit(i + 64 + 32, common->keymap)))
425 : 0 : return i + 32;
426 [ # # # # ]: 0 : if (!test_bit(i + 64, common->keymap) &&
427 [ # # ]: 0 : (test_bit(i , common->keymap) ||
428 [ # # ]: 0 : test_bit(i + 32, common->keymap) ||
429 : 0 : test_bit(i + 64 + 32, common->keymap)))
430 : 0 : return i + 64;
431 [ # # # # ]: 0 : if (!test_bit(i + 64 + 32, common->keymap) &&
432 [ # # ]: 0 : (test_bit(i, common->keymap) ||
433 [ # # ]: 0 : test_bit(i + 32, common->keymap) ||
434 : 0 : test_bit(i + 64, common->keymap)))
435 : 0 : return i + 64 + 32;
436 : : }
437 : : } else {
438 [ # # ]: 0 : for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
439 [ # # # # ]: 0 : if (!test_bit(i, common->keymap) &&
440 : 0 : test_bit(i + 64, common->keymap))
441 : 0 : return i;
442 [ # # # # ]: 0 : if (test_bit(i, common->keymap) &&
443 : 0 : !test_bit(i + 64, common->keymap))
444 : 0 : return i + 64;
445 : : }
446 : : }
447 : :
448 : : /* No partially used TKIP slots, pick any available slot */
449 [ # # ]: 0 : for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
450 : : /* Do not allow slots that could be needed for TKIP group keys
451 : : * to be used. This limitation could be removed if we know that
452 : : * TKIP will not be used. */
453 [ # # ]: 0 : if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
454 : 0 : continue;
455 [ # # ]: 0 : if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
456 [ # # ]: 0 : if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
457 : 0 : continue;
458 [ # # ]: 0 : if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
459 : 0 : continue;
460 : : }
461 : :
462 [ # # ]: 0 : if (!test_bit(i, common->keymap))
463 : 0 : return i; /* Found a free slot for a key */
464 : : }
465 : :
466 : : /* No free slot found */
467 : : return -1;
468 : : }
469 : :
470 : : /*
471 : : * Configure encryption in the HW.
472 : : */
473 : 0 : int ath_key_config(struct ath_common *common,
474 : : struct ieee80211_vif *vif,
475 : : struct ieee80211_sta *sta,
476 : : struct ieee80211_key_conf *key)
477 : : {
478 : 0 : struct ath_keyval hk;
479 : 0 : const u8 *mac = NULL;
480 : 0 : u8 gmac[ETH_ALEN];
481 : 0 : int ret = 0;
482 : 0 : int idx;
483 : :
484 : 0 : memset(&hk, 0, sizeof(hk));
485 : :
486 [ # # # # : 0 : switch (key->cipher) {
# ]
487 : 0 : case 0:
488 : 0 : hk.kv_type = ATH_CIPHER_CLR;
489 : 0 : break;
490 : 0 : case WLAN_CIPHER_SUITE_WEP40:
491 : : case WLAN_CIPHER_SUITE_WEP104:
492 : 0 : hk.kv_type = ATH_CIPHER_WEP;
493 : 0 : break;
494 : 0 : case WLAN_CIPHER_SUITE_TKIP:
495 : 0 : hk.kv_type = ATH_CIPHER_TKIP;
496 : 0 : break;
497 : 0 : case WLAN_CIPHER_SUITE_CCMP:
498 : 0 : hk.kv_type = ATH_CIPHER_AES_CCM;
499 : 0 : break;
500 : : default:
501 : : return -EOPNOTSUPP;
502 : : }
503 : :
504 : 0 : hk.kv_len = key->keylen;
505 [ # # ]: 0 : if (key->keylen)
506 : 0 : memcpy(hk.kv_val, key->key, key->keylen);
507 : :
508 [ # # ]: 0 : if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
509 [ # # # ]: 0 : switch (vif->type) {
510 : 0 : case NL80211_IFTYPE_AP:
511 : 0 : memcpy(gmac, vif->addr, ETH_ALEN);
512 : 0 : gmac[0] |= 0x01;
513 : 0 : mac = gmac;
514 : 0 : idx = ath_reserve_key_cache_slot(common, key->cipher);
515 : 0 : break;
516 : 0 : case NL80211_IFTYPE_ADHOC:
517 [ # # ]: 0 : if (!sta) {
518 : 0 : idx = key->keyidx;
519 : 0 : break;
520 : : }
521 : 0 : memcpy(gmac, sta->addr, ETH_ALEN);
522 : 0 : gmac[0] |= 0x01;
523 : 0 : mac = gmac;
524 : 0 : idx = ath_reserve_key_cache_slot(common, key->cipher);
525 : 0 : break;
526 : 0 : default:
527 : 0 : idx = key->keyidx;
528 : 0 : break;
529 : : }
530 [ # # ]: 0 : } else if (key->keyidx) {
531 [ # # # # ]: 0 : if (WARN_ON(!sta))
532 : : return -EOPNOTSUPP;
533 : 0 : mac = sta->addr;
534 : :
535 [ # # ]: 0 : if (vif->type != NL80211_IFTYPE_AP) {
536 : : /* Only keyidx 0 should be used with unicast key, but
537 : : * allow this for client mode for now. */
538 : 0 : idx = key->keyidx;
539 : : } else
540 : : return -EIO;
541 : : } else {
542 [ # # # # ]: 0 : if (WARN_ON(!sta))
543 : : return -EOPNOTSUPP;
544 : 0 : mac = sta->addr;
545 : :
546 : 0 : idx = ath_reserve_key_cache_slot(common, key->cipher);
547 : : }
548 : :
549 [ # # ]: 0 : if (idx < 0)
550 : : return -ENOSPC; /* no free key cache entries */
551 : :
552 [ # # ]: 0 : if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
553 : 0 : ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
554 : 0 : vif->type == NL80211_IFTYPE_AP);
555 : : else
556 : 0 : ret = ath_hw_set_keycache_entry(common, idx, &hk, mac);
557 : :
558 [ # # ]: 0 : if (!ret)
559 : : return -EIO;
560 : :
561 : 0 : set_bit(idx, common->keymap);
562 [ # # ]: 0 : if (key->cipher == WLAN_CIPHER_SUITE_CCMP)
563 : 0 : set_bit(idx, common->ccmp_keymap);
564 : :
565 [ # # ]: 0 : if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
566 : 0 : set_bit(idx + 64, common->keymap);
567 : 0 : set_bit(idx, common->tkip_keymap);
568 : 0 : set_bit(idx + 64, common->tkip_keymap);
569 [ # # ]: 0 : if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
570 : 0 : set_bit(idx + 32, common->keymap);
571 : 0 : set_bit(idx + 64 + 32, common->keymap);
572 : 0 : set_bit(idx + 32, common->tkip_keymap);
573 : 0 : set_bit(idx + 64 + 32, common->tkip_keymap);
574 : : }
575 : : }
576 : :
577 : : return idx;
578 : : }
579 : : EXPORT_SYMBOL(ath_key_config);
580 : :
581 : : /*
582 : : * Delete Key.
583 : : */
584 : 0 : void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
585 : : {
586 : 0 : ath_hw_keyreset(common, key->hw_key_idx);
587 [ # # ]: 0 : if (key->hw_key_idx < IEEE80211_WEP_NKID)
588 : : return;
589 : :
590 : 0 : clear_bit(key->hw_key_idx, common->keymap);
591 : 0 : clear_bit(key->hw_key_idx, common->ccmp_keymap);
592 [ # # ]: 0 : if (key->cipher != WLAN_CIPHER_SUITE_TKIP)
593 : : return;
594 : :
595 : 0 : clear_bit(key->hw_key_idx + 64, common->keymap);
596 : :
597 : 0 : clear_bit(key->hw_key_idx, common->tkip_keymap);
598 : 0 : clear_bit(key->hw_key_idx + 64, common->tkip_keymap);
599 : :
600 [ # # ]: 0 : if (!(common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)) {
601 : 0 : ath_hw_keyreset(common, key->hw_key_idx + 32);
602 : 0 : clear_bit(key->hw_key_idx + 32, common->keymap);
603 : 0 : clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
604 : :
605 : 0 : clear_bit(key->hw_key_idx + 32, common->tkip_keymap);
606 : 0 : clear_bit(key->hw_key_idx + 64 + 32, common->tkip_keymap);
607 : : }
608 : : }
609 : : EXPORT_SYMBOL(ath_key_delete);
|