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