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