xref: /freebsd/sys/dev/ath/if_ath_keycache.c (revision d2d7a00aa9904d42eb05440c669a518711275d8a)
1*d2d7a00aSAdrian Chadd /*-
2*d2d7a00aSAdrian Chadd  * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3*d2d7a00aSAdrian Chadd  * All rights reserved.
4*d2d7a00aSAdrian Chadd  *
5*d2d7a00aSAdrian Chadd  * Redistribution and use in source and binary forms, with or without
6*d2d7a00aSAdrian Chadd  * modification, are permitted provided that the following conditions
7*d2d7a00aSAdrian Chadd  * are met:
8*d2d7a00aSAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
9*d2d7a00aSAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
10*d2d7a00aSAdrian Chadd  *    without modification.
11*d2d7a00aSAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12*d2d7a00aSAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13*d2d7a00aSAdrian Chadd  *    redistribution must be conditioned upon including a substantially
14*d2d7a00aSAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
15*d2d7a00aSAdrian Chadd  *
16*d2d7a00aSAdrian Chadd  * NO WARRANTY
17*d2d7a00aSAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*d2d7a00aSAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*d2d7a00aSAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20*d2d7a00aSAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21*d2d7a00aSAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22*d2d7a00aSAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*d2d7a00aSAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*d2d7a00aSAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*d2d7a00aSAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*d2d7a00aSAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27*d2d7a00aSAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
28*d2d7a00aSAdrian Chadd  */
29*d2d7a00aSAdrian Chadd 
30*d2d7a00aSAdrian Chadd #include <sys/cdefs.h>
31*d2d7a00aSAdrian Chadd __FBSDID("$FreeBSD$");
32*d2d7a00aSAdrian Chadd 
33*d2d7a00aSAdrian Chadd /*
34*d2d7a00aSAdrian Chadd  * Driver for the Atheros Wireless LAN controller.
35*d2d7a00aSAdrian Chadd  *
36*d2d7a00aSAdrian Chadd  * This software is derived from work of Atsushi Onoe; his contribution
37*d2d7a00aSAdrian Chadd  * is greatly appreciated.
38*d2d7a00aSAdrian Chadd  */
39*d2d7a00aSAdrian Chadd 
40*d2d7a00aSAdrian Chadd #include "opt_inet.h"
41*d2d7a00aSAdrian Chadd #include "opt_ath.h"
42*d2d7a00aSAdrian Chadd #include "opt_wlan.h"
43*d2d7a00aSAdrian Chadd 
44*d2d7a00aSAdrian Chadd #include <sys/param.h>
45*d2d7a00aSAdrian Chadd #include <sys/systm.h>
46*d2d7a00aSAdrian Chadd #include <sys/sysctl.h>
47*d2d7a00aSAdrian Chadd #include <sys/mbuf.h>
48*d2d7a00aSAdrian Chadd #include <sys/malloc.h>
49*d2d7a00aSAdrian Chadd #include <sys/lock.h>
50*d2d7a00aSAdrian Chadd #include <sys/mutex.h>
51*d2d7a00aSAdrian Chadd #include <sys/kernel.h>
52*d2d7a00aSAdrian Chadd #include <sys/socket.h>
53*d2d7a00aSAdrian Chadd #include <sys/sockio.h>
54*d2d7a00aSAdrian Chadd #include <sys/errno.h>
55*d2d7a00aSAdrian Chadd #include <sys/callout.h>
56*d2d7a00aSAdrian Chadd #include <sys/bus.h>
57*d2d7a00aSAdrian Chadd #include <sys/endian.h>
58*d2d7a00aSAdrian Chadd #include <sys/kthread.h>
59*d2d7a00aSAdrian Chadd #include <sys/taskqueue.h>
60*d2d7a00aSAdrian Chadd #include <sys/priv.h>
61*d2d7a00aSAdrian Chadd 
62*d2d7a00aSAdrian Chadd #include <machine/bus.h>
63*d2d7a00aSAdrian Chadd 
64*d2d7a00aSAdrian Chadd #include <net/if.h>
65*d2d7a00aSAdrian Chadd #include <net/if_dl.h>
66*d2d7a00aSAdrian Chadd #include <net/if_media.h>
67*d2d7a00aSAdrian Chadd #include <net/if_types.h>
68*d2d7a00aSAdrian Chadd #include <net/if_arp.h>
69*d2d7a00aSAdrian Chadd #include <net/ethernet.h>
70*d2d7a00aSAdrian Chadd #include <net/if_llc.h>
71*d2d7a00aSAdrian Chadd 
72*d2d7a00aSAdrian Chadd #include <net80211/ieee80211_var.h>
73*d2d7a00aSAdrian Chadd 
74*d2d7a00aSAdrian Chadd #include <net/bpf.h>
75*d2d7a00aSAdrian Chadd 
76*d2d7a00aSAdrian Chadd #include <dev/ath/if_athvar.h>
77*d2d7a00aSAdrian Chadd 
78*d2d7a00aSAdrian Chadd #include <dev/ath/if_ath_debug.h>
79*d2d7a00aSAdrian Chadd #include <dev/ath/if_ath_keycache.h>
80*d2d7a00aSAdrian Chadd 
81*d2d7a00aSAdrian Chadd #ifdef ATH_DEBUG
82*d2d7a00aSAdrian Chadd static void
83*d2d7a00aSAdrian Chadd ath_keyprint(struct ath_softc *sc, const char *tag, u_int ix,
84*d2d7a00aSAdrian Chadd 	const HAL_KEYVAL *hk, const u_int8_t mac[IEEE80211_ADDR_LEN])
85*d2d7a00aSAdrian Chadd {
86*d2d7a00aSAdrian Chadd 	static const char *ciphers[] = {
87*d2d7a00aSAdrian Chadd 		"WEP",
88*d2d7a00aSAdrian Chadd 		"AES-OCB",
89*d2d7a00aSAdrian Chadd 		"AES-CCM",
90*d2d7a00aSAdrian Chadd 		"CKIP",
91*d2d7a00aSAdrian Chadd 		"TKIP",
92*d2d7a00aSAdrian Chadd 		"CLR",
93*d2d7a00aSAdrian Chadd 	};
94*d2d7a00aSAdrian Chadd 	int i, n;
95*d2d7a00aSAdrian Chadd 
96*d2d7a00aSAdrian Chadd 	printf("%s: [%02u] %-7s ", tag, ix, ciphers[hk->kv_type]);
97*d2d7a00aSAdrian Chadd 	for (i = 0, n = hk->kv_len; i < n; i++)
98*d2d7a00aSAdrian Chadd 		printf("%02x", hk->kv_val[i]);
99*d2d7a00aSAdrian Chadd 	printf(" mac %s", ether_sprintf(mac));
100*d2d7a00aSAdrian Chadd 	if (hk->kv_type == HAL_CIPHER_TKIP) {
101*d2d7a00aSAdrian Chadd 		printf(" %s ", sc->sc_splitmic ? "mic" : "rxmic");
102*d2d7a00aSAdrian Chadd 		for (i = 0; i < sizeof(hk->kv_mic); i++)
103*d2d7a00aSAdrian Chadd 			printf("%02x", hk->kv_mic[i]);
104*d2d7a00aSAdrian Chadd 		if (!sc->sc_splitmic) {
105*d2d7a00aSAdrian Chadd 			printf(" txmic ");
106*d2d7a00aSAdrian Chadd 			for (i = 0; i < sizeof(hk->kv_txmic); i++)
107*d2d7a00aSAdrian Chadd 				printf("%02x", hk->kv_txmic[i]);
108*d2d7a00aSAdrian Chadd 		}
109*d2d7a00aSAdrian Chadd 	}
110*d2d7a00aSAdrian Chadd 	printf("\n");
111*d2d7a00aSAdrian Chadd }
112*d2d7a00aSAdrian Chadd #endif
113*d2d7a00aSAdrian Chadd 
114*d2d7a00aSAdrian Chadd /*
115*d2d7a00aSAdrian Chadd  * Set a TKIP key into the hardware.  This handles the
116*d2d7a00aSAdrian Chadd  * potential distribution of key state to multiple key
117*d2d7a00aSAdrian Chadd  * cache slots for TKIP.
118*d2d7a00aSAdrian Chadd  */
119*d2d7a00aSAdrian Chadd static int
120*d2d7a00aSAdrian Chadd ath_keyset_tkip(struct ath_softc *sc, const struct ieee80211_key *k,
121*d2d7a00aSAdrian Chadd 	HAL_KEYVAL *hk, const u_int8_t mac[IEEE80211_ADDR_LEN])
122*d2d7a00aSAdrian Chadd {
123*d2d7a00aSAdrian Chadd #define	IEEE80211_KEY_XR	(IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV)
124*d2d7a00aSAdrian Chadd 	static const u_int8_t zerobssid[IEEE80211_ADDR_LEN];
125*d2d7a00aSAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
126*d2d7a00aSAdrian Chadd 
127*d2d7a00aSAdrian Chadd 	KASSERT(k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP,
128*d2d7a00aSAdrian Chadd 		("got a non-TKIP key, cipher %u", k->wk_cipher->ic_cipher));
129*d2d7a00aSAdrian Chadd 	if ((k->wk_flags & IEEE80211_KEY_XR) == IEEE80211_KEY_XR) {
130*d2d7a00aSAdrian Chadd 		if (sc->sc_splitmic) {
131*d2d7a00aSAdrian Chadd 			/*
132*d2d7a00aSAdrian Chadd 			 * TX key goes at first index, RX key at the rx index.
133*d2d7a00aSAdrian Chadd 			 * The hal handles the MIC keys at index+64.
134*d2d7a00aSAdrian Chadd 			 */
135*d2d7a00aSAdrian Chadd 			memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_mic));
136*d2d7a00aSAdrian Chadd 			KEYPRINTF(sc, k->wk_keyix, hk, zerobssid);
137*d2d7a00aSAdrian Chadd 			if (!ath_hal_keyset(ah, k->wk_keyix, hk, zerobssid))
138*d2d7a00aSAdrian Chadd 				return 0;
139*d2d7a00aSAdrian Chadd 
140*d2d7a00aSAdrian Chadd 			memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic));
141*d2d7a00aSAdrian Chadd 			KEYPRINTF(sc, k->wk_keyix+32, hk, mac);
142*d2d7a00aSAdrian Chadd 			/* XXX delete tx key on failure? */
143*d2d7a00aSAdrian Chadd 			return ath_hal_keyset(ah, k->wk_keyix+32, hk, mac);
144*d2d7a00aSAdrian Chadd 		} else {
145*d2d7a00aSAdrian Chadd 			/*
146*d2d7a00aSAdrian Chadd 			 * Room for both TX+RX MIC keys in one key cache
147*d2d7a00aSAdrian Chadd 			 * slot, just set key at the first index; the hal
148*d2d7a00aSAdrian Chadd 			 * will handle the rest.
149*d2d7a00aSAdrian Chadd 			 */
150*d2d7a00aSAdrian Chadd 			memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic));
151*d2d7a00aSAdrian Chadd 			memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic));
152*d2d7a00aSAdrian Chadd 			KEYPRINTF(sc, k->wk_keyix, hk, mac);
153*d2d7a00aSAdrian Chadd 			return ath_hal_keyset(ah, k->wk_keyix, hk, mac);
154*d2d7a00aSAdrian Chadd 		}
155*d2d7a00aSAdrian Chadd 	} else if (k->wk_flags & IEEE80211_KEY_XMIT) {
156*d2d7a00aSAdrian Chadd 		if (sc->sc_splitmic) {
157*d2d7a00aSAdrian Chadd 			/*
158*d2d7a00aSAdrian Chadd 			 * NB: must pass MIC key in expected location when
159*d2d7a00aSAdrian Chadd 			 * the keycache only holds one MIC key per entry.
160*d2d7a00aSAdrian Chadd 			 */
161*d2d7a00aSAdrian Chadd 			memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_txmic));
162*d2d7a00aSAdrian Chadd 		} else
163*d2d7a00aSAdrian Chadd 			memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic));
164*d2d7a00aSAdrian Chadd 		KEYPRINTF(sc, k->wk_keyix, hk, mac);
165*d2d7a00aSAdrian Chadd 		return ath_hal_keyset(ah, k->wk_keyix, hk, mac);
166*d2d7a00aSAdrian Chadd 	} else if (k->wk_flags & IEEE80211_KEY_RECV) {
167*d2d7a00aSAdrian Chadd 		memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic));
168*d2d7a00aSAdrian Chadd 		KEYPRINTF(sc, k->wk_keyix, hk, mac);
169*d2d7a00aSAdrian Chadd 		return ath_hal_keyset(ah, k->wk_keyix, hk, mac);
170*d2d7a00aSAdrian Chadd 	}
171*d2d7a00aSAdrian Chadd 	return 0;
172*d2d7a00aSAdrian Chadd #undef IEEE80211_KEY_XR
173*d2d7a00aSAdrian Chadd }
174*d2d7a00aSAdrian Chadd 
175*d2d7a00aSAdrian Chadd /*
176*d2d7a00aSAdrian Chadd  * Set a net80211 key into the hardware.  This handles the
177*d2d7a00aSAdrian Chadd  * potential distribution of key state to multiple key
178*d2d7a00aSAdrian Chadd  * cache slots for TKIP with hardware MIC support.
179*d2d7a00aSAdrian Chadd  */
180*d2d7a00aSAdrian Chadd int
181*d2d7a00aSAdrian Chadd ath_keyset(struct ath_softc *sc, const struct ieee80211_key *k,
182*d2d7a00aSAdrian Chadd 	struct ieee80211_node *bss)
183*d2d7a00aSAdrian Chadd {
184*d2d7a00aSAdrian Chadd #define	N(a)	(sizeof(a)/sizeof(a[0]))
185*d2d7a00aSAdrian Chadd 	static const u_int8_t ciphermap[] = {
186*d2d7a00aSAdrian Chadd 		HAL_CIPHER_WEP,		/* IEEE80211_CIPHER_WEP */
187*d2d7a00aSAdrian Chadd 		HAL_CIPHER_TKIP,	/* IEEE80211_CIPHER_TKIP */
188*d2d7a00aSAdrian Chadd 		HAL_CIPHER_AES_OCB,	/* IEEE80211_CIPHER_AES_OCB */
189*d2d7a00aSAdrian Chadd 		HAL_CIPHER_AES_CCM,	/* IEEE80211_CIPHER_AES_CCM */
190*d2d7a00aSAdrian Chadd 		(u_int8_t) -1,		/* 4 is not allocated */
191*d2d7a00aSAdrian Chadd 		HAL_CIPHER_CKIP,	/* IEEE80211_CIPHER_CKIP */
192*d2d7a00aSAdrian Chadd 		HAL_CIPHER_CLR,		/* IEEE80211_CIPHER_NONE */
193*d2d7a00aSAdrian Chadd 	};
194*d2d7a00aSAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
195*d2d7a00aSAdrian Chadd 	const struct ieee80211_cipher *cip = k->wk_cipher;
196*d2d7a00aSAdrian Chadd 	u_int8_t gmac[IEEE80211_ADDR_LEN];
197*d2d7a00aSAdrian Chadd 	const u_int8_t *mac;
198*d2d7a00aSAdrian Chadd 	HAL_KEYVAL hk;
199*d2d7a00aSAdrian Chadd 
200*d2d7a00aSAdrian Chadd 	memset(&hk, 0, sizeof(hk));
201*d2d7a00aSAdrian Chadd 	/*
202*d2d7a00aSAdrian Chadd 	 * Software crypto uses a "clear key" so non-crypto
203*d2d7a00aSAdrian Chadd 	 * state kept in the key cache are maintained and
204*d2d7a00aSAdrian Chadd 	 * so that rx frames have an entry to match.
205*d2d7a00aSAdrian Chadd 	 */
206*d2d7a00aSAdrian Chadd 	if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) {
207*d2d7a00aSAdrian Chadd 		KASSERT(cip->ic_cipher < N(ciphermap),
208*d2d7a00aSAdrian Chadd 			("invalid cipher type %u", cip->ic_cipher));
209*d2d7a00aSAdrian Chadd 		hk.kv_type = ciphermap[cip->ic_cipher];
210*d2d7a00aSAdrian Chadd 		hk.kv_len = k->wk_keylen;
211*d2d7a00aSAdrian Chadd 		memcpy(hk.kv_val, k->wk_key, k->wk_keylen);
212*d2d7a00aSAdrian Chadd 	} else
213*d2d7a00aSAdrian Chadd 		hk.kv_type = HAL_CIPHER_CLR;
214*d2d7a00aSAdrian Chadd 
215*d2d7a00aSAdrian Chadd 	if ((k->wk_flags & IEEE80211_KEY_GROUP) && sc->sc_mcastkey) {
216*d2d7a00aSAdrian Chadd 		/*
217*d2d7a00aSAdrian Chadd 		 * Group keys on hardware that supports multicast frame
218*d2d7a00aSAdrian Chadd 		 * key search use a MAC that is the sender's address with
219*d2d7a00aSAdrian Chadd 		 * the multicast bit set instead of the app-specified address.
220*d2d7a00aSAdrian Chadd 		 */
221*d2d7a00aSAdrian Chadd 		IEEE80211_ADDR_COPY(gmac, bss->ni_macaddr);
222*d2d7a00aSAdrian Chadd 		gmac[0] |= 0x01;
223*d2d7a00aSAdrian Chadd 		mac = gmac;
224*d2d7a00aSAdrian Chadd 	} else
225*d2d7a00aSAdrian Chadd 		mac = k->wk_macaddr;
226*d2d7a00aSAdrian Chadd 
227*d2d7a00aSAdrian Chadd 	if (hk.kv_type == HAL_CIPHER_TKIP &&
228*d2d7a00aSAdrian Chadd 	    (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
229*d2d7a00aSAdrian Chadd 		return ath_keyset_tkip(sc, k, &hk, mac);
230*d2d7a00aSAdrian Chadd 	} else {
231*d2d7a00aSAdrian Chadd 		KEYPRINTF(sc, k->wk_keyix, &hk, mac);
232*d2d7a00aSAdrian Chadd 		return ath_hal_keyset(ah, k->wk_keyix, &hk, mac);
233*d2d7a00aSAdrian Chadd 	}
234*d2d7a00aSAdrian Chadd #undef N
235*d2d7a00aSAdrian Chadd }
236*d2d7a00aSAdrian Chadd 
237*d2d7a00aSAdrian Chadd /*
238*d2d7a00aSAdrian Chadd  * Allocate tx/rx key slots for TKIP.  We allocate two slots for
239*d2d7a00aSAdrian Chadd  * each key, one for decrypt/encrypt and the other for the MIC.
240*d2d7a00aSAdrian Chadd  */
241*d2d7a00aSAdrian Chadd static u_int16_t
242*d2d7a00aSAdrian Chadd key_alloc_2pair(struct ath_softc *sc,
243*d2d7a00aSAdrian Chadd 	ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix)
244*d2d7a00aSAdrian Chadd {
245*d2d7a00aSAdrian Chadd #define	N(a)	(sizeof(a)/sizeof(a[0]))
246*d2d7a00aSAdrian Chadd 	u_int i, keyix;
247*d2d7a00aSAdrian Chadd 
248*d2d7a00aSAdrian Chadd 	KASSERT(sc->sc_splitmic, ("key cache !split"));
249*d2d7a00aSAdrian Chadd 	/* XXX could optimize */
250*d2d7a00aSAdrian Chadd 	for (i = 0; i < N(sc->sc_keymap)/4; i++) {
251*d2d7a00aSAdrian Chadd 		u_int8_t b = sc->sc_keymap[i];
252*d2d7a00aSAdrian Chadd 		if (b != 0xff) {
253*d2d7a00aSAdrian Chadd 			/*
254*d2d7a00aSAdrian Chadd 			 * One or more slots in this byte are free.
255*d2d7a00aSAdrian Chadd 			 */
256*d2d7a00aSAdrian Chadd 			keyix = i*NBBY;
257*d2d7a00aSAdrian Chadd 			while (b & 1) {
258*d2d7a00aSAdrian Chadd 		again:
259*d2d7a00aSAdrian Chadd 				keyix++;
260*d2d7a00aSAdrian Chadd 				b >>= 1;
261*d2d7a00aSAdrian Chadd 			}
262*d2d7a00aSAdrian Chadd 			/* XXX IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV */
263*d2d7a00aSAdrian Chadd 			if (isset(sc->sc_keymap, keyix+32) ||
264*d2d7a00aSAdrian Chadd 			    isset(sc->sc_keymap, keyix+64) ||
265*d2d7a00aSAdrian Chadd 			    isset(sc->sc_keymap, keyix+32+64)) {
266*d2d7a00aSAdrian Chadd 				/* full pair unavailable */
267*d2d7a00aSAdrian Chadd 				/* XXX statistic */
268*d2d7a00aSAdrian Chadd 				if (keyix == (i+1)*NBBY) {
269*d2d7a00aSAdrian Chadd 					/* no slots were appropriate, advance */
270*d2d7a00aSAdrian Chadd 					continue;
271*d2d7a00aSAdrian Chadd 				}
272*d2d7a00aSAdrian Chadd 				goto again;
273*d2d7a00aSAdrian Chadd 			}
274*d2d7a00aSAdrian Chadd 			setbit(sc->sc_keymap, keyix);
275*d2d7a00aSAdrian Chadd 			setbit(sc->sc_keymap, keyix+64);
276*d2d7a00aSAdrian Chadd 			setbit(sc->sc_keymap, keyix+32);
277*d2d7a00aSAdrian Chadd 			setbit(sc->sc_keymap, keyix+32+64);
278*d2d7a00aSAdrian Chadd 			DPRINTF(sc, ATH_DEBUG_KEYCACHE,
279*d2d7a00aSAdrian Chadd 				"%s: key pair %u,%u %u,%u\n",
280*d2d7a00aSAdrian Chadd 				__func__, keyix, keyix+64,
281*d2d7a00aSAdrian Chadd 				keyix+32, keyix+32+64);
282*d2d7a00aSAdrian Chadd 			*txkeyix = keyix;
283*d2d7a00aSAdrian Chadd 			*rxkeyix = keyix+32;
284*d2d7a00aSAdrian Chadd 			return 1;
285*d2d7a00aSAdrian Chadd 		}
286*d2d7a00aSAdrian Chadd 	}
287*d2d7a00aSAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__);
288*d2d7a00aSAdrian Chadd 	return 0;
289*d2d7a00aSAdrian Chadd #undef N
290*d2d7a00aSAdrian Chadd }
291*d2d7a00aSAdrian Chadd 
292*d2d7a00aSAdrian Chadd /*
293*d2d7a00aSAdrian Chadd  * Allocate tx/rx key slots for TKIP.  We allocate two slots for
294*d2d7a00aSAdrian Chadd  * each key, one for decrypt/encrypt and the other for the MIC.
295*d2d7a00aSAdrian Chadd  */
296*d2d7a00aSAdrian Chadd static u_int16_t
297*d2d7a00aSAdrian Chadd key_alloc_pair(struct ath_softc *sc,
298*d2d7a00aSAdrian Chadd 	ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix)
299*d2d7a00aSAdrian Chadd {
300*d2d7a00aSAdrian Chadd #define	N(a)	(sizeof(a)/sizeof(a[0]))
301*d2d7a00aSAdrian Chadd 	u_int i, keyix;
302*d2d7a00aSAdrian Chadd 
303*d2d7a00aSAdrian Chadd 	KASSERT(!sc->sc_splitmic, ("key cache split"));
304*d2d7a00aSAdrian Chadd 	/* XXX could optimize */
305*d2d7a00aSAdrian Chadd 	for (i = 0; i < N(sc->sc_keymap)/4; i++) {
306*d2d7a00aSAdrian Chadd 		u_int8_t b = sc->sc_keymap[i];
307*d2d7a00aSAdrian Chadd 		if (b != 0xff) {
308*d2d7a00aSAdrian Chadd 			/*
309*d2d7a00aSAdrian Chadd 			 * One or more slots in this byte are free.
310*d2d7a00aSAdrian Chadd 			 */
311*d2d7a00aSAdrian Chadd 			keyix = i*NBBY;
312*d2d7a00aSAdrian Chadd 			while (b & 1) {
313*d2d7a00aSAdrian Chadd 		again:
314*d2d7a00aSAdrian Chadd 				keyix++;
315*d2d7a00aSAdrian Chadd 				b >>= 1;
316*d2d7a00aSAdrian Chadd 			}
317*d2d7a00aSAdrian Chadd 			if (isset(sc->sc_keymap, keyix+64)) {
318*d2d7a00aSAdrian Chadd 				/* full pair unavailable */
319*d2d7a00aSAdrian Chadd 				/* XXX statistic */
320*d2d7a00aSAdrian Chadd 				if (keyix == (i+1)*NBBY) {
321*d2d7a00aSAdrian Chadd 					/* no slots were appropriate, advance */
322*d2d7a00aSAdrian Chadd 					continue;
323*d2d7a00aSAdrian Chadd 				}
324*d2d7a00aSAdrian Chadd 				goto again;
325*d2d7a00aSAdrian Chadd 			}
326*d2d7a00aSAdrian Chadd 			setbit(sc->sc_keymap, keyix);
327*d2d7a00aSAdrian Chadd 			setbit(sc->sc_keymap, keyix+64);
328*d2d7a00aSAdrian Chadd 			DPRINTF(sc, ATH_DEBUG_KEYCACHE,
329*d2d7a00aSAdrian Chadd 				"%s: key pair %u,%u\n",
330*d2d7a00aSAdrian Chadd 				__func__, keyix, keyix+64);
331*d2d7a00aSAdrian Chadd 			*txkeyix = *rxkeyix = keyix;
332*d2d7a00aSAdrian Chadd 			return 1;
333*d2d7a00aSAdrian Chadd 		}
334*d2d7a00aSAdrian Chadd 	}
335*d2d7a00aSAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of pair space\n", __func__);
336*d2d7a00aSAdrian Chadd 	return 0;
337*d2d7a00aSAdrian Chadd #undef N
338*d2d7a00aSAdrian Chadd }
339*d2d7a00aSAdrian Chadd 
340*d2d7a00aSAdrian Chadd /*
341*d2d7a00aSAdrian Chadd  * Allocate a single key cache slot.
342*d2d7a00aSAdrian Chadd  */
343*d2d7a00aSAdrian Chadd static int
344*d2d7a00aSAdrian Chadd key_alloc_single(struct ath_softc *sc,
345*d2d7a00aSAdrian Chadd 	ieee80211_keyix *txkeyix, ieee80211_keyix *rxkeyix)
346*d2d7a00aSAdrian Chadd {
347*d2d7a00aSAdrian Chadd #define	N(a)	(sizeof(a)/sizeof(a[0]))
348*d2d7a00aSAdrian Chadd 	u_int i, keyix;
349*d2d7a00aSAdrian Chadd 
350*d2d7a00aSAdrian Chadd 	/* XXX try i,i+32,i+64,i+32+64 to minimize key pair conflicts */
351*d2d7a00aSAdrian Chadd 	for (i = 0; i < N(sc->sc_keymap); i++) {
352*d2d7a00aSAdrian Chadd 		u_int8_t b = sc->sc_keymap[i];
353*d2d7a00aSAdrian Chadd 		if (b != 0xff) {
354*d2d7a00aSAdrian Chadd 			/*
355*d2d7a00aSAdrian Chadd 			 * One or more slots are free.
356*d2d7a00aSAdrian Chadd 			 */
357*d2d7a00aSAdrian Chadd 			keyix = i*NBBY;
358*d2d7a00aSAdrian Chadd 			while (b & 1)
359*d2d7a00aSAdrian Chadd 				keyix++, b >>= 1;
360*d2d7a00aSAdrian Chadd 			setbit(sc->sc_keymap, keyix);
361*d2d7a00aSAdrian Chadd 			DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: key %u\n",
362*d2d7a00aSAdrian Chadd 				__func__, keyix);
363*d2d7a00aSAdrian Chadd 			*txkeyix = *rxkeyix = keyix;
364*d2d7a00aSAdrian Chadd 			return 1;
365*d2d7a00aSAdrian Chadd 		}
366*d2d7a00aSAdrian Chadd 	}
367*d2d7a00aSAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: out of space\n", __func__);
368*d2d7a00aSAdrian Chadd 	return 0;
369*d2d7a00aSAdrian Chadd #undef N
370*d2d7a00aSAdrian Chadd }
371*d2d7a00aSAdrian Chadd 
372*d2d7a00aSAdrian Chadd /*
373*d2d7a00aSAdrian Chadd  * Allocate one or more key cache slots for a uniacst key.  The
374*d2d7a00aSAdrian Chadd  * key itself is needed only to identify the cipher.  For hardware
375*d2d7a00aSAdrian Chadd  * TKIP with split cipher+MIC keys we allocate two key cache slot
376*d2d7a00aSAdrian Chadd  * pairs so that we can setup separate TX and RX MIC keys.  Note
377*d2d7a00aSAdrian Chadd  * that the MIC key for a TKIP key at slot i is assumed by the
378*d2d7a00aSAdrian Chadd  * hardware to be at slot i+64.  This limits TKIP keys to the first
379*d2d7a00aSAdrian Chadd  * 64 entries.
380*d2d7a00aSAdrian Chadd  */
381*d2d7a00aSAdrian Chadd int
382*d2d7a00aSAdrian Chadd ath_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
383*d2d7a00aSAdrian Chadd 	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
384*d2d7a00aSAdrian Chadd {
385*d2d7a00aSAdrian Chadd 	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
386*d2d7a00aSAdrian Chadd 
387*d2d7a00aSAdrian Chadd 	/*
388*d2d7a00aSAdrian Chadd 	 * Group key allocation must be handled specially for
389*d2d7a00aSAdrian Chadd 	 * parts that do not support multicast key cache search
390*d2d7a00aSAdrian Chadd 	 * functionality.  For those parts the key id must match
391*d2d7a00aSAdrian Chadd 	 * the h/w key index so lookups find the right key.  On
392*d2d7a00aSAdrian Chadd 	 * parts w/ the key search facility we install the sender's
393*d2d7a00aSAdrian Chadd 	 * mac address (with the high bit set) and let the hardware
394*d2d7a00aSAdrian Chadd 	 * find the key w/o using the key id.  This is preferred as
395*d2d7a00aSAdrian Chadd 	 * it permits us to support multiple users for adhoc and/or
396*d2d7a00aSAdrian Chadd 	 * multi-station operation.
397*d2d7a00aSAdrian Chadd 	 */
398*d2d7a00aSAdrian Chadd 	if (k->wk_keyix != IEEE80211_KEYIX_NONE) {
399*d2d7a00aSAdrian Chadd 		/*
400*d2d7a00aSAdrian Chadd 		 * Only global keys should have key index assigned.
401*d2d7a00aSAdrian Chadd 		 */
402*d2d7a00aSAdrian Chadd 		if (!(&vap->iv_nw_keys[0] <= k &&
403*d2d7a00aSAdrian Chadd 		      k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) {
404*d2d7a00aSAdrian Chadd 			/* should not happen */
405*d2d7a00aSAdrian Chadd 			DPRINTF(sc, ATH_DEBUG_KEYCACHE,
406*d2d7a00aSAdrian Chadd 				"%s: bogus group key\n", __func__);
407*d2d7a00aSAdrian Chadd 			return 0;
408*d2d7a00aSAdrian Chadd 		}
409*d2d7a00aSAdrian Chadd 		if (vap->iv_opmode != IEEE80211_M_HOSTAP ||
410*d2d7a00aSAdrian Chadd 		    !(k->wk_flags & IEEE80211_KEY_GROUP) ||
411*d2d7a00aSAdrian Chadd 		    !sc->sc_mcastkey) {
412*d2d7a00aSAdrian Chadd 			/*
413*d2d7a00aSAdrian Chadd 			 * XXX we pre-allocate the global keys so
414*d2d7a00aSAdrian Chadd 			 * have no way to check if they've already
415*d2d7a00aSAdrian Chadd 			 * been allocated.
416*d2d7a00aSAdrian Chadd 			 */
417*d2d7a00aSAdrian Chadd 			*keyix = *rxkeyix = k - vap->iv_nw_keys;
418*d2d7a00aSAdrian Chadd 			return 1;
419*d2d7a00aSAdrian Chadd 		}
420*d2d7a00aSAdrian Chadd 		/*
421*d2d7a00aSAdrian Chadd 		 * Group key and device supports multicast key search.
422*d2d7a00aSAdrian Chadd 		 */
423*d2d7a00aSAdrian Chadd 		k->wk_keyix = IEEE80211_KEYIX_NONE;
424*d2d7a00aSAdrian Chadd 	}
425*d2d7a00aSAdrian Chadd 
426*d2d7a00aSAdrian Chadd 	/*
427*d2d7a00aSAdrian Chadd 	 * We allocate two pair for TKIP when using the h/w to do
428*d2d7a00aSAdrian Chadd 	 * the MIC.  For everything else, including software crypto,
429*d2d7a00aSAdrian Chadd 	 * we allocate a single entry.  Note that s/w crypto requires
430*d2d7a00aSAdrian Chadd 	 * a pass-through slot on the 5211 and 5212.  The 5210 does
431*d2d7a00aSAdrian Chadd 	 * not support pass-through cache entries and we map all
432*d2d7a00aSAdrian Chadd 	 * those requests to slot 0.
433*d2d7a00aSAdrian Chadd 	 */
434*d2d7a00aSAdrian Chadd 	if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
435*d2d7a00aSAdrian Chadd 		return key_alloc_single(sc, keyix, rxkeyix);
436*d2d7a00aSAdrian Chadd 	} else if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP &&
437*d2d7a00aSAdrian Chadd 	    (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
438*d2d7a00aSAdrian Chadd 		if (sc->sc_splitmic)
439*d2d7a00aSAdrian Chadd 			return key_alloc_2pair(sc, keyix, rxkeyix);
440*d2d7a00aSAdrian Chadd 		else
441*d2d7a00aSAdrian Chadd 			return key_alloc_pair(sc, keyix, rxkeyix);
442*d2d7a00aSAdrian Chadd 	} else {
443*d2d7a00aSAdrian Chadd 		return key_alloc_single(sc, keyix, rxkeyix);
444*d2d7a00aSAdrian Chadd 	}
445*d2d7a00aSAdrian Chadd }
446*d2d7a00aSAdrian Chadd 
447*d2d7a00aSAdrian Chadd /*
448*d2d7a00aSAdrian Chadd  * Delete an entry in the key cache allocated by ath_key_alloc.
449*d2d7a00aSAdrian Chadd  */
450*d2d7a00aSAdrian Chadd int
451*d2d7a00aSAdrian Chadd ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
452*d2d7a00aSAdrian Chadd {
453*d2d7a00aSAdrian Chadd 	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
454*d2d7a00aSAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
455*d2d7a00aSAdrian Chadd 	const struct ieee80211_cipher *cip = k->wk_cipher;
456*d2d7a00aSAdrian Chadd 	u_int keyix = k->wk_keyix;
457*d2d7a00aSAdrian Chadd 
458*d2d7a00aSAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s: delete key %u\n", __func__, keyix);
459*d2d7a00aSAdrian Chadd 
460*d2d7a00aSAdrian Chadd 	ath_hal_keyreset(ah, keyix);
461*d2d7a00aSAdrian Chadd 	/*
462*d2d7a00aSAdrian Chadd 	 * Handle split tx/rx keying required for TKIP with h/w MIC.
463*d2d7a00aSAdrian Chadd 	 */
464*d2d7a00aSAdrian Chadd 	if (cip->ic_cipher == IEEE80211_CIPHER_TKIP &&
465*d2d7a00aSAdrian Chadd 	    (k->wk_flags & IEEE80211_KEY_SWMIC) == 0 && sc->sc_splitmic)
466*d2d7a00aSAdrian Chadd 		ath_hal_keyreset(ah, keyix+32);		/* RX key */
467*d2d7a00aSAdrian Chadd 	if (keyix >= IEEE80211_WEP_NKID) {
468*d2d7a00aSAdrian Chadd 		/*
469*d2d7a00aSAdrian Chadd 		 * Don't touch keymap entries for global keys so
470*d2d7a00aSAdrian Chadd 		 * they are never considered for dynamic allocation.
471*d2d7a00aSAdrian Chadd 		 */
472*d2d7a00aSAdrian Chadd 		clrbit(sc->sc_keymap, keyix);
473*d2d7a00aSAdrian Chadd 		if (cip->ic_cipher == IEEE80211_CIPHER_TKIP &&
474*d2d7a00aSAdrian Chadd 		    (k->wk_flags & IEEE80211_KEY_SWMIC) == 0) {
475*d2d7a00aSAdrian Chadd 			clrbit(sc->sc_keymap, keyix+64);	/* TX key MIC */
476*d2d7a00aSAdrian Chadd 			if (sc->sc_splitmic) {
477*d2d7a00aSAdrian Chadd 				/* +32 for RX key, +32+64 for RX key MIC */
478*d2d7a00aSAdrian Chadd 				clrbit(sc->sc_keymap, keyix+32);
479*d2d7a00aSAdrian Chadd 				clrbit(sc->sc_keymap, keyix+32+64);
480*d2d7a00aSAdrian Chadd 			}
481*d2d7a00aSAdrian Chadd 		}
482*d2d7a00aSAdrian Chadd 	}
483*d2d7a00aSAdrian Chadd 	return 1;
484*d2d7a00aSAdrian Chadd }
485*d2d7a00aSAdrian Chadd 
486*d2d7a00aSAdrian Chadd /*
487*d2d7a00aSAdrian Chadd  * Set the key cache contents for the specified key.  Key cache
488*d2d7a00aSAdrian Chadd  * slot(s) must already have been allocated by ath_key_alloc.
489*d2d7a00aSAdrian Chadd  */
490*d2d7a00aSAdrian Chadd int
491*d2d7a00aSAdrian Chadd ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
492*d2d7a00aSAdrian Chadd 	const u_int8_t mac[IEEE80211_ADDR_LEN])
493*d2d7a00aSAdrian Chadd {
494*d2d7a00aSAdrian Chadd 	struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc;
495*d2d7a00aSAdrian Chadd 
496*d2d7a00aSAdrian Chadd 	return ath_keyset(sc, k, vap->iv_bss);
497*d2d7a00aSAdrian Chadd }
498