2 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3 * Copyright (c) 2002-2008 Atheros Communications, Inc.
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.
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.
17 * $Id: ar5212_keycache.c,v 1.1.1.1 2008/12/11 04:46:40 alc Exp $
22 #include "ah_internal.h"
24 #include "ar5212/ar5212.h"
25 #include "ar5212/ar5212reg.h"
26 #include "ar5212/ar5212desc.h"
29 * Note: The key cache hardware requires that each double-word
30 * pair be written in even/odd order (since the destination is
31 * a 64-bit register). Don't reorder the writes in this code
32 * w/o considering this!
36 #define IS_MIC_ENABLED(ah) \
37 (AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
40 * Return the size of the hardware key cache.
43 ar5212GetKeyCacheSize(struct ath_hal
*ah
)
45 return AH_PRIVATE(ah
)->ah_caps
.halKeyCacheSize
;
49 * Return true if the specific key cache entry is valid.
52 ar5212IsKeyCacheEntryValid(struct ath_hal
*ah
, uint16_t entry
)
54 if (entry
< AH_PRIVATE(ah
)->ah_caps
.halKeyCacheSize
) {
55 uint32_t val
= OS_REG_READ(ah
, AR_KEYTABLE_MAC1(entry
));
56 if (val
& AR_KEYTABLE_VALID
)
63 * Clear the specified key cache entry and any associated MIC entry.
66 ar5212ResetKeyCacheEntry(struct ath_hal
*ah
, uint16_t entry
)
70 if (entry
>= AH_PRIVATE(ah
)->ah_caps
.halKeyCacheSize
) {
71 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: entry %u out of range\n",
75 keyType
= OS_REG_READ(ah
, AR_KEYTABLE_TYPE(entry
));
77 /* XXX why not clear key type/valid bit first? */
78 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY0(entry
), 0);
79 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY1(entry
), 0);
80 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY2(entry
), 0);
81 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY3(entry
), 0);
82 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY4(entry
), 0);
83 OS_REG_WRITE(ah
, AR_KEYTABLE_TYPE(entry
), AR_KEYTABLE_TYPE_CLR
);
84 OS_REG_WRITE(ah
, AR_KEYTABLE_MAC0(entry
), 0);
85 OS_REG_WRITE(ah
, AR_KEYTABLE_MAC1(entry
), 0);
86 if (keyType
== AR_KEYTABLE_TYPE_TKIP
&& IS_MIC_ENABLED(ah
)) {
87 uint16_t micentry
= entry
+64; /* MIC goes at slot+64 */
89 HALASSERT(micentry
< AH_PRIVATE(ah
)->ah_caps
.halKeyCacheSize
);
90 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY0(micentry
), 0);
91 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY1(micentry
), 0);
92 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY2(micentry
), 0);
93 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY3(micentry
), 0);
94 /* NB: key type and MAC are known to be ok */
100 * Sets the mac part of the specified key cache entry (and any
101 * associated MIC entry) and mark them valid.
104 ar5212SetKeyCacheEntryMac(struct ath_hal
*ah
, uint16_t entry
, const uint8_t *mac
)
106 uint32_t macHi
, macLo
;
108 if (entry
>= AH_PRIVATE(ah
)->ah_caps
.halKeyCacheSize
) {
109 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: entry %u out of range\n",
114 * Set MAC address -- shifted right by 1. MacLo is
115 * the 4 MSBs, and MacHi is the 2 LSBs.
117 if (mac
!= AH_NULL
) {
118 macHi
= (mac
[5] << 8) | mac
[4];
119 macLo
= (mac
[3] << 24)| (mac
[2] << 16)
120 | (mac
[1] << 8) | mac
[0];
122 macLo
|= (macHi
& 1) << 31; /* carry */
127 OS_REG_WRITE(ah
, AR_KEYTABLE_MAC0(entry
), macLo
);
128 OS_REG_WRITE(ah
, AR_KEYTABLE_MAC1(entry
), macHi
| AR_KEYTABLE_VALID
);
133 * Sets the contents of the specified key cache entry
134 * and any associated MIC entry.
137 ar5212SetKeyCacheEntry(struct ath_hal
*ah
, uint16_t entry
,
138 const HAL_KEYVAL
*k
, const uint8_t *mac
,
141 struct ath_hal_5212
*ahp
= AH5212(ah
);
142 const HAL_CAPABILITIES
*pCap
= &AH_PRIVATE(ah
)->ah_caps
;
143 uint32_t key0
, key1
, key2
, key3
, key4
;
145 uint32_t xorMask
= xorKey
?
146 (KEY_XOR
<< 24 | KEY_XOR
<< 16 | KEY_XOR
<< 8 | KEY_XOR
) : 0;
148 if (entry
>= pCap
->halKeyCacheSize
) {
149 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: entry %u out of range\n",
153 switch (k
->kv_type
) {
154 case HAL_CIPHER_AES_OCB
:
155 keyType
= AR_KEYTABLE_TYPE_AES
;
157 case HAL_CIPHER_AES_CCM
:
158 if (!pCap
->halCipherAesCcmSupport
) {
159 HALDEBUG(ah
, HAL_DEBUG_ANY
,
160 "%s: AES-CCM not supported by mac rev 0x%x\n",
161 __func__
, AH_PRIVATE(ah
)->ah_macRev
);
164 keyType
= AR_KEYTABLE_TYPE_CCM
;
166 case HAL_CIPHER_TKIP
:
167 keyType
= AR_KEYTABLE_TYPE_TKIP
;
168 if (IS_MIC_ENABLED(ah
) && entry
+64 >= pCap
->halKeyCacheSize
) {
169 HALDEBUG(ah
, HAL_DEBUG_ANY
,
170 "%s: entry %u inappropriate for TKIP\n",
176 if (k
->kv_len
< 40 / NBBY
) {
177 HALDEBUG(ah
, HAL_DEBUG_ANY
,
178 "%s: WEP key length %u too small\n",
179 __func__
, k
->kv_len
);
182 if (k
->kv_len
<= 40 / NBBY
)
183 keyType
= AR_KEYTABLE_TYPE_40
;
184 else if (k
->kv_len
<= 104 / NBBY
)
185 keyType
= AR_KEYTABLE_TYPE_104
;
187 keyType
= AR_KEYTABLE_TYPE_128
;
190 keyType
= AR_KEYTABLE_TYPE_CLR
;
193 HALDEBUG(ah
, HAL_DEBUG_ANY
, "%s: cipher %u not supported\n",
194 __func__
, k
->kv_type
);
198 key0
= LE_READ_4(k
->kv_val
+0) ^ xorMask
;
199 key1
= (LE_READ_2(k
->kv_val
+4) ^ xorMask
) & 0xffff;
200 key2
= LE_READ_4(k
->kv_val
+6) ^ xorMask
;
201 key3
= (LE_READ_2(k
->kv_val
+10) ^ xorMask
) & 0xffff;
202 key4
= LE_READ_4(k
->kv_val
+12) ^ xorMask
;
203 if (k
->kv_len
<= 104 / NBBY
)
207 * Note: key cache hardware requires that each double-word
208 * pair be written in even/odd order (since the destination is
209 * a 64-bit register). Don't reorder these writes w/o
212 if (keyType
== AR_KEYTABLE_TYPE_TKIP
&& IS_MIC_ENABLED(ah
)) {
213 uint16_t micentry
= entry
+64; /* MIC goes at slot+64 */
214 uint32_t mic0
, mic1
, mic2
, mic3
, mic4
;
217 * Invalidate the encrypt/decrypt key until the MIC
218 * key is installed so pending rx frames will fail
219 * with decrypt errors rather than a MIC error.
221 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY0(entry
), ~key0
);
222 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY1(entry
), ~key1
);
223 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY2(entry
), key2
);
224 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY3(entry
), key3
);
225 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY4(entry
), key4
);
226 OS_REG_WRITE(ah
, AR_KEYTABLE_TYPE(entry
), keyType
);
227 (void) ar5212SetKeyCacheEntryMac(ah
, entry
, mac
);
231 * Write MIC entry according to new or old key layout.
232 * The MISC_MODE register is assumed already set so
233 * these writes will be handled properly (happens on
234 * attach and at every reset).
237 mic0
= LE_READ_4(k
->kv_mic
+0);
238 mic2
= LE_READ_4(k
->kv_mic
+4);
239 if (ahp
->ah_miscMode
& AR_MISC_MODE_MIC_NEW_LOC_ENABLE
) {
241 * Both RX and TX mic values can be combined into
242 * one cache slot entry:
243 * 8*N + 800 31:0 RX Michael key 0
244 * 8*N + 804 15:0 TX Michael key 0 [31:16]
245 * 8*N + 808 31:0 RX Michael key 1
246 * 8*N + 80C 15:0 TX Michael key 0 [15:0]
247 * 8*N + 810 31:0 TX Michael key 1
248 * 8*N + 814 15:0 reserved
249 * 8*N + 818 31:0 reserved
250 * 8*N + 81C 14:0 reserved
254 mic1
= LE_READ_2(k
->kv_txmic
+2) & 0xffff;
255 mic3
= LE_READ_2(k
->kv_txmic
+0) & 0xffff;
256 mic4
= LE_READ_4(k
->kv_txmic
+4);
258 mic1
= mic3
= mic4
= 0;
260 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY0(micentry
), mic0
);
261 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY1(micentry
), mic1
);
262 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY2(micentry
), mic2
);
263 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY3(micentry
), mic3
);
264 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY4(micentry
), mic4
);
265 OS_REG_WRITE(ah
, AR_KEYTABLE_TYPE(micentry
),
266 AR_KEYTABLE_TYPE_CLR
);
267 /* NB: MIC key is not marked valid and has no MAC address */
268 OS_REG_WRITE(ah
, AR_KEYTABLE_MAC0(micentry
), 0);
269 OS_REG_WRITE(ah
, AR_KEYTABLE_MAC1(micentry
), 0);
271 /* correct intentionally corrupted key */
272 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY0(entry
), key0
);
273 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY1(entry
), key1
);
275 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY0(entry
), key0
);
276 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY1(entry
), key1
);
277 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY2(entry
), key2
);
278 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY3(entry
), key3
);
279 OS_REG_WRITE(ah
, AR_KEYTABLE_KEY4(entry
), key4
);
280 OS_REG_WRITE(ah
, AR_KEYTABLE_TYPE(entry
), keyType
);
282 (void) ar5212SetKeyCacheEntryMac(ah
, entry
, mac
);