xref: /freebsd/sys/dev/ath/ath_hal/ar5212/ar5212_keycache.c (revision 0b3105a37d7adcadcb720112fed4dc4e8040be99)
1 /*
2  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
3  * Copyright (c) 2002-2008 Atheros Communications, Inc.
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  * $FreeBSD$
18  */
19 #include "opt_ah.h"
20 
21 #include "ah.h"
22 #include "ah_internal.h"
23 
24 #include "ar5212/ar5212.h"
25 #include "ar5212/ar5212reg.h"
26 #include "ar5212/ar5212desc.h"
27 
28 /*
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!
33  */
34 #define	KEY_XOR			0xaa
35 
36 #define	IS_MIC_ENABLED(ah) \
37 	(AH5212(ah)->ah_staId1Defaults & AR_STA_ID1_CRPT_MIC_ENABLE)
38 
39 /*
40  * Return the size of the hardware key cache.
41  */
42 uint32_t
43 ar5212GetKeyCacheSize(struct ath_hal *ah)
44 {
45 	return AH_PRIVATE(ah)->ah_caps.halKeyCacheSize;
46 }
47 
48 /*
49  * Return true if the specific key cache entry is valid.
50  */
51 HAL_BOOL
52 ar5212IsKeyCacheEntryValid(struct ath_hal *ah, uint16_t entry)
53 {
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)
57 			return AH_TRUE;
58 	}
59 	return AH_FALSE;
60 }
61 
62 /*
63  * Clear the specified key cache entry and any associated MIC entry.
64  */
65 HAL_BOOL
66 ar5212ResetKeyCacheEntry(struct ath_hal *ah, uint16_t entry)
67 {
68 	uint32_t keyType;
69 
70 	if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
71 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n",
72 		    __func__, entry);
73 		return AH_FALSE;
74 	}
75 	keyType = OS_REG_READ(ah, AR_KEYTABLE_TYPE(entry));
76 
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 */
88 
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 */
95 	}
96 	return AH_TRUE;
97 }
98 
99 /*
100  * Sets the mac part of the specified key cache entry (and any
101  * associated MIC entry) and mark them valid.
102  *
103  * Since mac[0] is shifted off and not presented to the hardware,
104  * it does double duty as a "don't use for unicast, use for multicast
105  * matching" flag. This interface should later be extended to
106  * explicitly do that rather than overloading a bit in the MAC
107  * address.
108  */
109 HAL_BOOL
110 ar5212SetKeyCacheEntryMac(struct ath_hal *ah, uint16_t entry, const uint8_t *mac)
111 {
112 	uint32_t macHi, macLo;
113 	uint32_t unicast_flag = AR_KEYTABLE_VALID;
114 
115 	if (entry >= AH_PRIVATE(ah)->ah_caps.halKeyCacheSize) {
116 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n",
117 		    __func__, entry);
118 		return AH_FALSE;
119 	}
120 	/*
121 	 * Set MAC address -- shifted right by 1.  MacLo is
122 	 * the 4 MSBs, and MacHi is the 2 LSBs.
123 	 */
124 	if (mac != AH_NULL) {
125 		/*
126 		 * AR_KEYTABLE_VALID indicates that the address is a unicast
127 		 * address, which must match the transmitter address for
128 		 * decrypting frames.
129 		 * Not setting this bit allows the hardware to use the key
130 		 * for multicast frame decryption.
131 		 */
132 		if (mac[0] & 0x01)
133 			unicast_flag = 0;
134 
135 		macHi = (mac[5] << 8) | mac[4];
136 		macLo = (mac[3] << 24)| (mac[2] << 16)
137 		      | (mac[1] << 8) | mac[0];
138 		macLo >>= 1;
139 		macLo |= (macHi & 1) << 31;	/* carry */
140 		macHi >>= 1;
141 	} else {
142 		macLo = macHi = 0;
143 	}
144 	OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
145 	OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | unicast_flag);
146 	return AH_TRUE;
147 }
148 
149 /*
150  * Sets the contents of the specified key cache entry
151  * and any associated MIC entry.
152  */
153 HAL_BOOL
154 ar5212SetKeyCacheEntry(struct ath_hal *ah, uint16_t entry,
155                        const HAL_KEYVAL *k, const uint8_t *mac,
156                        int xorKey)
157 {
158 	struct ath_hal_5212 *ahp = AH5212(ah);
159 	const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
160 	uint32_t key0, key1, key2, key3, key4;
161 	uint32_t keyType;
162 	uint32_t xorMask = xorKey ?
163 		(KEY_XOR << 24 | KEY_XOR << 16 | KEY_XOR << 8 | KEY_XOR) : 0;
164 
165 	if (entry >= pCap->halKeyCacheSize) {
166 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: entry %u out of range\n",
167 		    __func__, entry);
168 		return AH_FALSE;
169 	}
170 	switch (k->kv_type) {
171 	case HAL_CIPHER_AES_OCB:
172 		keyType = AR_KEYTABLE_TYPE_AES;
173 		break;
174 	case HAL_CIPHER_AES_CCM:
175 		if (!pCap->halCipherAesCcmSupport) {
176 			HALDEBUG(ah, HAL_DEBUG_ANY,
177 			    "%s: AES-CCM not supported by mac rev 0x%x\n",
178 			    __func__, AH_PRIVATE(ah)->ah_macRev);
179 			return AH_FALSE;
180 		}
181 		keyType = AR_KEYTABLE_TYPE_CCM;
182 		break;
183 	case HAL_CIPHER_TKIP:
184 		keyType = AR_KEYTABLE_TYPE_TKIP;
185 		if (IS_MIC_ENABLED(ah) && entry+64 >= pCap->halKeyCacheSize) {
186 			HALDEBUG(ah, HAL_DEBUG_ANY,
187 			    "%s: entry %u inappropriate for TKIP\n",
188 			    __func__, entry);
189 			return AH_FALSE;
190 		}
191 		break;
192 	case HAL_CIPHER_WEP:
193 		if (k->kv_len < 40 / NBBY) {
194 			HALDEBUG(ah, HAL_DEBUG_ANY,
195 			    "%s: WEP key length %u too small\n",
196 			    __func__, k->kv_len);
197 			return AH_FALSE;
198 		}
199 		if (k->kv_len <= 40 / NBBY)
200 			keyType = AR_KEYTABLE_TYPE_40;
201 		else if (k->kv_len <= 104 / NBBY)
202 			keyType = AR_KEYTABLE_TYPE_104;
203 		else
204 			keyType = AR_KEYTABLE_TYPE_128;
205 		break;
206 	case HAL_CIPHER_CLR:
207 		keyType = AR_KEYTABLE_TYPE_CLR;
208 		break;
209 	default:
210 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: cipher %u not supported\n",
211 		    __func__, k->kv_type);
212 		return AH_FALSE;
213 	}
214 
215 	key0 = LE_READ_4(k->kv_val+0) ^ xorMask;
216 	key1 = (LE_READ_2(k->kv_val+4) ^ xorMask) & 0xffff;
217 	key2 = LE_READ_4(k->kv_val+6) ^ xorMask;
218 	key3 = (LE_READ_2(k->kv_val+10) ^ xorMask) & 0xffff;
219 	key4 = LE_READ_4(k->kv_val+12) ^ xorMask;
220 	if (k->kv_len <= 104 / NBBY)
221 		key4 &= 0xff;
222 
223 	/*
224 	 * Note: key cache hardware requires that each double-word
225 	 * pair be written in even/odd order (since the destination is
226 	 * a 64-bit register).  Don't reorder these writes w/o
227 	 * considering this!
228 	 */
229 	if (keyType == AR_KEYTABLE_TYPE_TKIP && IS_MIC_ENABLED(ah)) {
230 		uint16_t micentry = entry+64;	/* MIC goes at slot+64 */
231 		uint32_t mic0, mic1, mic2, mic3, mic4;
232 
233 		/*
234 		 * Invalidate the encrypt/decrypt key until the MIC
235 		 * key is installed so pending rx frames will fail
236 		 * with decrypt errors rather than a MIC error.
237 		 */
238 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
239 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
240 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
241 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
242 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
243 		OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
244 		(void) ar5212SetKeyCacheEntryMac(ah, entry, mac);
245 
246 
247 		/*
248 		 * Write MIC entry according to new or old key layout.
249 		 * The MISC_MODE register is assumed already set so
250 		 * these writes will be handled properly (happens on
251 		 * attach and at every reset).
252 		 */
253 		/* RX mic */
254 		mic0 = LE_READ_4(k->kv_mic+0);
255 		mic2 = LE_READ_4(k->kv_mic+4);
256 		if (ahp->ah_miscMode & AR_MISC_MODE_MIC_NEW_LOC_ENABLE) {
257 			/*
258 			 * Both RX and TX mic values can be combined into
259 			 * one cache slot entry:
260 			 *  8*N + 800         31:0    RX Michael key 0
261 			 *  8*N + 804         15:0    TX Michael key 0 [31:16]
262 			 *  8*N + 808         31:0    RX Michael key 1
263 			 *  8*N + 80C         15:0    TX Michael key 0 [15:0]
264 			 *  8*N + 810         31:0    TX Michael key 1
265 			 *  8*N + 814         15:0    reserved
266 			 *  8*N + 818         31:0    reserved
267 			 *  8*N + 81C         14:0    reserved
268 			 *                    15      key valid == 0
269 			 */
270 			/* TX mic */
271 			mic1 = LE_READ_2(k->kv_txmic+2) & 0xffff;
272 			mic3 = LE_READ_2(k->kv_txmic+0) & 0xffff;
273 			mic4 = LE_READ_4(k->kv_txmic+4);
274 		} else {
275 			mic1 = mic3 = mic4 = 0;
276 		}
277 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
278 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
279 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
280 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
281 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
282 		OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
283 			AR_KEYTABLE_TYPE_CLR);
284 		/* NB: MIC key is not marked valid and has no MAC address */
285 		OS_REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
286 		OS_REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
287 
288 		/* correct intentionally corrupted key */
289 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
290 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
291 	} else {
292 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
293 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
294 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
295 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
296 		OS_REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
297 		OS_REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
298 
299 		(void) ar5212SetKeyCacheEntryMac(ah, entry, mac);
300 	}
301 	return AH_TRUE;
302 }
303