1*3147Sxc151355 /*
2*3147Sxc151355  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
3*3147Sxc151355  * Use is subject to license terms.
4*3147Sxc151355  */
5*3147Sxc151355 
6*3147Sxc151355 /*
7*3147Sxc151355  * Copyright (c) 2001 Atsushi Onoe
8*3147Sxc151355  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
9*3147Sxc151355  * All rights reserved.
10*3147Sxc151355  *
11*3147Sxc151355  * Redistribution and use in source and binary forms, with or without
12*3147Sxc151355  * modification, are permitted provided that the following conditions
13*3147Sxc151355  * are met:
14*3147Sxc151355  * 1. Redistributions of source code must retain the above copyright
15*3147Sxc151355  *    notice, this list of conditions and the following disclaimer.
16*3147Sxc151355  * 2. Redistributions in binary form must reproduce the above copyright
17*3147Sxc151355  *    notice, this list of conditions and the following disclaimer in the
18*3147Sxc151355  *    documentation and/or other materials provided with the distribution.
19*3147Sxc151355  * 3. The name of the author may not be used to endorse or promote products
20*3147Sxc151355  *    derived from this software without specific prior written permission.
21*3147Sxc151355  *
22*3147Sxc151355  * Alternatively, this software may be distributed under the terms of the
23*3147Sxc151355  * GNU General Public License ("GPL") version 2 as published by the Free
24*3147Sxc151355  * Software Foundation.
25*3147Sxc151355  *
26*3147Sxc151355  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27*3147Sxc151355  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28*3147Sxc151355  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29*3147Sxc151355  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30*3147Sxc151355  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31*3147Sxc151355  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32*3147Sxc151355  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33*3147Sxc151355  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34*3147Sxc151355  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35*3147Sxc151355  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36*3147Sxc151355  */
37*3147Sxc151355 
38*3147Sxc151355 #pragma ident	"%Z%%M%	%I%	%E% SMI"
39*3147Sxc151355 
40*3147Sxc151355 /*
41*3147Sxc151355  * IEEE 802.11 generic crypto support
42*3147Sxc151355  */
43*3147Sxc151355 #include <sys/types.h>
44*3147Sxc151355 #include <sys/note.h>
45*3147Sxc151355 #include "net80211_impl.h"
46*3147Sxc151355 
47*3147Sxc151355 extern const struct ieee80211_cipher wep;
48*3147Sxc151355 
49*3147Sxc151355 /*
50*3147Sxc151355  * Table of registered cipher modules.
51*3147Sxc151355  */
52*3147Sxc151355 static const struct ieee80211_cipher *ciphers[IEEE80211_CIPHER_MAX];
53*3147Sxc151355 static const char *cipher_modnames[] = {
54*3147Sxc151355 	"wlan_wep",	/* IEEE80211_CIPHER_WEP */
55*3147Sxc151355 	"wlan_tkip",	/* IEEE80211_CIPHER_TKIP */
56*3147Sxc151355 	"wlan_aes_ocb",	/* IEEE80211_CIPHER_AES_OCB */
57*3147Sxc151355 	"wlan_ccmp",	/* IEEE80211_CIPHER_AES_CCM */
58*3147Sxc151355 	"wlan_ckip",	/* IEEE80211_CIPHER_CKIP */
59*3147Sxc151355 };
60*3147Sxc151355 
61*3147Sxc151355 /*
62*3147Sxc151355  * Default "null" key management routines.
63*3147Sxc151355  */
64*3147Sxc151355 /* ARGSUSED */
65*3147Sxc151355 static int
66*3147Sxc151355 nulldev_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k,
67*3147Sxc151355 	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
68*3147Sxc151355 {
69*3147Sxc151355 	*keyix = 0;	/* use key index 0 for ucast key */
70*3147Sxc151355 	*rxkeyix = IEEE80211_KEYIX_NONE;
71*3147Sxc151355 	return (1);
72*3147Sxc151355 }
73*3147Sxc151355 
74*3147Sxc151355 /* ARGSUSED */
75*3147Sxc151355 static int
76*3147Sxc151355 nulldev_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k)
77*3147Sxc151355 {
78*3147Sxc151355 	return (1);
79*3147Sxc151355 }
80*3147Sxc151355 
81*3147Sxc151355 /* ARGSUSED */
82*3147Sxc151355 static int
83*3147Sxc151355 nulldev_key_set(ieee80211com_t *ic, const struct ieee80211_key *k,
84*3147Sxc151355 	const uint8_t *mac)
85*3147Sxc151355 {
86*3147Sxc151355 	return (1);
87*3147Sxc151355 }
88*3147Sxc151355 
89*3147Sxc151355 /* ARGSUSED */
90*3147Sxc151355 static void
91*3147Sxc151355 nulldev_key_update(ieee80211com_t *ic)
92*3147Sxc151355 {
93*3147Sxc151355 	/* noop */
94*3147Sxc151355 }
95*3147Sxc151355 
96*3147Sxc151355 /*
97*3147Sxc151355  * Reset key state to an unused state.  The crypto
98*3147Sxc151355  * key allocation mechanism insures other state (e.g.
99*3147Sxc151355  * key data) is properly setup before a key is used.
100*3147Sxc151355  */
101*3147Sxc151355 void
102*3147Sxc151355 ieee80211_crypto_resetkey(ieee80211com_t *ic,
103*3147Sxc151355 	struct ieee80211_key *k, ieee80211_keyix ix)
104*3147Sxc151355 {
105*3147Sxc151355 	k->wk_cipher = &ieee80211_cipher_none;
106*3147Sxc151355 	k->wk_private = k->wk_cipher->ic_attach(ic, k);
107*3147Sxc151355 	k->wk_keyix = ix;
108*3147Sxc151355 	k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV;
109*3147Sxc151355 }
110*3147Sxc151355 
111*3147Sxc151355 /*
112*3147Sxc151355  * Establish a relationship between the specified key and cipher
113*3147Sxc151355  * and, if necessary, allocate a hardware index from the driver.
114*3147Sxc151355  * Note that when a fixed key index is required it must be specified
115*3147Sxc151355  * and we blindly assign it w/o consulting the driver.
116*3147Sxc151355  *
117*3147Sxc151355  * This must be the first call applied to a key; all the other key
118*3147Sxc151355  * routines assume wk_cipher is setup.
119*3147Sxc151355  *
120*3147Sxc151355  * Locking must be handled by the caller using:
121*3147Sxc151355  *	ieee80211_key_update_begin(ic);
122*3147Sxc151355  *	ieee80211_key_update_end(ic);
123*3147Sxc151355  */
124*3147Sxc151355 int
125*3147Sxc151355 ieee80211_crypto_newkey(ieee80211com_t *ic, int cipher, int flags,
126*3147Sxc151355     struct ieee80211_key *key)
127*3147Sxc151355 {
128*3147Sxc151355 	const struct ieee80211_cipher *cip;
129*3147Sxc151355 	ieee80211_keyix keyix, rxkeyix;
130*3147Sxc151355 	void *keyctx;
131*3147Sxc151355 	uint16_t oflags;
132*3147Sxc151355 
133*3147Sxc151355 	/*
134*3147Sxc151355 	 * Validate cipher and set reference to cipher routines.
135*3147Sxc151355 	 */
136*3147Sxc151355 	if (cipher >= IEEE80211_CIPHER_MAX) {
137*3147Sxc151355 		ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: "
138*3147Sxc151355 			"invalid cipher %u\n", cipher);
139*3147Sxc151355 		return (0);
140*3147Sxc151355 	}
141*3147Sxc151355 	cip = ciphers[cipher];
142*3147Sxc151355 	/* already load all the ciphers, cip can't be NULL */
143*3147Sxc151355 	if (cip == NULL) {
144*3147Sxc151355 		ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: "
145*3147Sxc151355 			"unable to load cipher %u, module %s\n",
146*3147Sxc151355 			cipher, cipher < IEEE80211_N(cipher_modnames) ?
147*3147Sxc151355 			cipher_modnames[cipher] : "<unknown>");
148*3147Sxc151355 		return (0);
149*3147Sxc151355 	}
150*3147Sxc151355 
151*3147Sxc151355 	oflags = key->wk_flags;
152*3147Sxc151355 	flags &= IEEE80211_KEY_COMMON;
153*3147Sxc151355 	/*
154*3147Sxc151355 	 * If the hardware does not support the cipher then
155*3147Sxc151355 	 * fallback to a host-based implementation.
156*3147Sxc151355 	 */
157*3147Sxc151355 	if ((ic->ic_caps & (1<<cipher)) == 0) {
158*3147Sxc151355 		ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: "
159*3147Sxc151355 			"no h/w support for cipher %s, falling back to s/w\n",
160*3147Sxc151355 			cip->ic_name);
161*3147Sxc151355 		flags |= IEEE80211_KEY_SWCRYPT;
162*3147Sxc151355 	}
163*3147Sxc151355 
164*3147Sxc151355 	/*
165*3147Sxc151355 	 * Bind cipher to key instance.  Note we do this
166*3147Sxc151355 	 * after checking the device capabilities so the
167*3147Sxc151355 	 * cipher module can optimize space usage based on
168*3147Sxc151355 	 * whether or not it needs to do the cipher work.
169*3147Sxc151355 	 */
170*3147Sxc151355 	if (key->wk_cipher != cip || key->wk_flags != flags) {
171*3147Sxc151355 again:
172*3147Sxc151355 		/*
173*3147Sxc151355 		 * Fillin the flags so cipher modules can see s/w
174*3147Sxc151355 		 * crypto requirements and potentially allocate
175*3147Sxc151355 		 * different state and/or attach different method
176*3147Sxc151355 		 * pointers.
177*3147Sxc151355 		 */
178*3147Sxc151355 		key->wk_flags = (uint16_t)flags;
179*3147Sxc151355 		keyctx = cip->ic_attach(ic, key);
180*3147Sxc151355 		if (keyctx == NULL) {
181*3147Sxc151355 			ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: "
182*3147Sxc151355 				"unable to attach cipher %s\n", cip->ic_name);
183*3147Sxc151355 			key->wk_flags = oflags;	/* restore old flags */
184*3147Sxc151355 			return (0);
185*3147Sxc151355 		}
186*3147Sxc151355 		CIPHER_DETACH(key);		/* Detach old cipher */
187*3147Sxc151355 		key->wk_cipher = cip;
188*3147Sxc151355 		key->wk_private = keyctx;
189*3147Sxc151355 	}
190*3147Sxc151355 	/*
191*3147Sxc151355 	 * Commit to requested usage so driver can see the flags.
192*3147Sxc151355 	 */
193*3147Sxc151355 	key->wk_flags = (uint16_t)flags;
194*3147Sxc151355 
195*3147Sxc151355 	/*
196*3147Sxc151355 	 * Ask the driver for a key index if we don't have one.
197*3147Sxc151355 	 * Note that entries in the global key table always have
198*3147Sxc151355 	 * an index; this means it's safe to call this routine
199*3147Sxc151355 	 * for these entries just to setup the reference to the
200*3147Sxc151355 	 * cipher template.  Note also that when using software
201*3147Sxc151355 	 * crypto we also call the driver to give us a key index.
202*3147Sxc151355 	 */
203*3147Sxc151355 	if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
204*3147Sxc151355 		if (!DEV_KEY_ALLOC(ic, key, &keyix, &rxkeyix)) {
205*3147Sxc151355 			/*
206*3147Sxc151355 			 * Driver has no room; fallback to doing crypto
207*3147Sxc151355 			 * in the host.  We change the flags and start the
208*3147Sxc151355 			 * procedure over.  If we get back here then there's
209*3147Sxc151355 			 * no hope and we bail.  Note that this can leave
210*3147Sxc151355 			 * the key in a inconsistent state if the caller
211*3147Sxc151355 			 * continues to use it.
212*3147Sxc151355 			 */
213*3147Sxc151355 			if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) {
214*3147Sxc151355 				ieee80211_dbg(IEEE80211_MSG_CRYPTO,
215*3147Sxc151355 					"crypto_setkey: "
216*3147Sxc151355 					"no h/w resources for cipher %s, "
217*3147Sxc151355 					"falling back to s/w\n", cip->ic_name);
218*3147Sxc151355 				oflags = key->wk_flags;
219*3147Sxc151355 				flags |= IEEE80211_KEY_SWCRYPT;
220*3147Sxc151355 				if (cipher == IEEE80211_CIPHER_TKIP)
221*3147Sxc151355 					flags |= IEEE80211_KEY_SWMIC;
222*3147Sxc151355 				goto again;
223*3147Sxc151355 			}
224*3147Sxc151355 			ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: "
225*3147Sxc151355 				"unable to setup cipher %s\n", cip->ic_name);
226*3147Sxc151355 			return (0);
227*3147Sxc151355 		}
228*3147Sxc151355 		key->wk_keyix = keyix;
229*3147Sxc151355 		key->wk_rxkeyix = rxkeyix;
230*3147Sxc151355 	}
231*3147Sxc151355 	return (1);
232*3147Sxc151355 }
233*3147Sxc151355 
234*3147Sxc151355 /*
235*3147Sxc151355  * Remove the key (no locking, for internal use).
236*3147Sxc151355  */
237*3147Sxc151355 static int
238*3147Sxc151355 ieee80211_crypto_delkey_locked(ieee80211com_t *ic, struct ieee80211_key *key)
239*3147Sxc151355 {
240*3147Sxc151355 	uint16_t keyix;
241*3147Sxc151355 
242*3147Sxc151355 	ASSERT(key->wk_cipher != NULL);
243*3147Sxc151355 
244*3147Sxc151355 	keyix = key->wk_keyix;
245*3147Sxc151355 	if (keyix != IEEE80211_KEYIX_NONE) {
246*3147Sxc151355 		/*
247*3147Sxc151355 		 * Remove hardware entry.
248*3147Sxc151355 		 */
249*3147Sxc151355 		if (!DEV_KEY_DELETE(ic, key)) {
250*3147Sxc151355 			ieee80211_dbg(IEEE80211_MSG_CRYPTO,
251*3147Sxc151355 				"ieee80211_crypto_delkey_locked: ",
252*3147Sxc151355 				"driverdeletes key %u failed\n", keyix);
253*3147Sxc151355 		}
254*3147Sxc151355 	}
255*3147Sxc151355 	CIPHER_DETACH(key);
256*3147Sxc151355 	bzero(key, sizeof (struct ieee80211_key));
257*3147Sxc151355 	/* NB: cannot depend on key index to decide this */
258*3147Sxc151355 	ieee80211_crypto_resetkey(ic, key, IEEE80211_KEYIX_NONE);
259*3147Sxc151355 	return (1);
260*3147Sxc151355 }
261*3147Sxc151355 
262*3147Sxc151355 /*
263*3147Sxc151355  * Remove the specified key.
264*3147Sxc151355  */
265*3147Sxc151355 int
266*3147Sxc151355 ieee80211_crypto_delkey(ieee80211com_t *ic, struct ieee80211_key *key)
267*3147Sxc151355 {
268*3147Sxc151355 	int status;
269*3147Sxc151355 
270*3147Sxc151355 	KEY_UPDATE_BEGIN(ic);
271*3147Sxc151355 	status = ieee80211_crypto_delkey_locked(ic, key);
272*3147Sxc151355 	KEY_UPDATE_END(ic);
273*3147Sxc151355 	return (status);
274*3147Sxc151355 }
275*3147Sxc151355 
276*3147Sxc151355 /*
277*3147Sxc151355  * Clear the global key table.
278*3147Sxc151355  */
279*3147Sxc151355 static void
280*3147Sxc151355 ieee80211_crypto_delglobalkeys(ieee80211com_t *ic)
281*3147Sxc151355 {
282*3147Sxc151355 	int i;
283*3147Sxc151355 
284*3147Sxc151355 	KEY_UPDATE_BEGIN(ic);
285*3147Sxc151355 	for (i = 0; i < IEEE80211_WEP_NKID; i++)
286*3147Sxc151355 		(void) ieee80211_crypto_delkey_locked(ic, &ic->ic_nw_keys[i]);
287*3147Sxc151355 	KEY_UPDATE_END(ic);
288*3147Sxc151355 }
289*3147Sxc151355 
290*3147Sxc151355 /*
291*3147Sxc151355  * Set the contents of the specified key.
292*3147Sxc151355  *
293*3147Sxc151355  * Locking must be handled by the caller using:
294*3147Sxc151355  *	ieee80211_key_update_begin(ic);
295*3147Sxc151355  *	ieee80211_key_update_end(ic);
296*3147Sxc151355  */
297*3147Sxc151355 int
298*3147Sxc151355 ieee80211_crypto_setkey(ieee80211com_t *ic, struct ieee80211_key *key,
299*3147Sxc151355     const uint8_t *macaddr)
300*3147Sxc151355 {
301*3147Sxc151355 	const struct ieee80211_cipher *cip = key->wk_cipher;
302*3147Sxc151355 
303*3147Sxc151355 	ASSERT(cip != NULL);
304*3147Sxc151355 
305*3147Sxc151355 	ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: "
306*3147Sxc151355 		"%s keyix %u flags 0x%x mac %s len %u\n",
307*3147Sxc151355 		cip->ic_name, key->wk_keyix, key->wk_flags,
308*3147Sxc151355 		ieee80211_macaddr_sprintf(macaddr), key->wk_keylen);
309*3147Sxc151355 
310*3147Sxc151355 	/*
311*3147Sxc151355 	 * Give cipher a chance to validate key contents.
312*3147Sxc151355 	 * should happen before modifying state.
313*3147Sxc151355 	 */
314*3147Sxc151355 	if (cip->ic_setkey(key) == 0) {
315*3147Sxc151355 		ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: "
316*3147Sxc151355 			"cipher %s rejected key index %u len %u flags 0x%x\n",
317*3147Sxc151355 			cip->ic_name, key->wk_keyix, key->wk_keylen,
318*3147Sxc151355 			key->wk_flags);
319*3147Sxc151355 		return (0);
320*3147Sxc151355 	}
321*3147Sxc151355 	if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
322*3147Sxc151355 		ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: "
323*3147Sxc151355 			"no key index; should not happen!\n");
324*3147Sxc151355 		return (0);
325*3147Sxc151355 	}
326*3147Sxc151355 	return (DEV_KEY_SET(ic, key, macaddr));
327*3147Sxc151355 }
328*3147Sxc151355 
329*3147Sxc151355 /*
330*3147Sxc151355  * Return the transmit key to use in sending a frame.
331*3147Sxc151355  */
332*3147Sxc151355 struct ieee80211_key *
333*3147Sxc151355 ieee80211_crypto_getkey(ieee80211com_t *ic)
334*3147Sxc151355 {
335*3147Sxc151355 	if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE ||
336*3147Sxc151355 	    KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey]))
337*3147Sxc151355 		return (NULL);
338*3147Sxc151355 	return (&ic->ic_nw_keys[ic->ic_def_txkey]);
339*3147Sxc151355 }
340*3147Sxc151355 
341*3147Sxc151355 uint8_t
342*3147Sxc151355 ieee80211_crypto_getciphertype(ieee80211com_t *ic)
343*3147Sxc151355 {
344*3147Sxc151355 	struct ieee80211_key *key;
345*3147Sxc151355 	uint32_t cipher;
346*3147Sxc151355 	static const uint8_t ciphermap[] = {
347*3147Sxc151355 		WIFI_SEC_WEP,	/* IEEE80211_CIPHER_WEP */
348*3147Sxc151355 		(uint8_t)-1,	/* IEEE80211_CIPHER_TKIP */
349*3147Sxc151355 		(uint8_t)-1,	/* IEEE80211_CIPHER_AES_OCB */
350*3147Sxc151355 		(uint8_t)-1,	/* IEEE80211_CIPHER_AES_CCM */
351*3147Sxc151355 		(uint8_t)-1,	/* 4 is not allocated */
352*3147Sxc151355 		(uint8_t)-1,	/* IEEE80211_CIPHER_CKIP */
353*3147Sxc151355 		WIFI_SEC_NONE,	/* IEEE80211_CIPHER_NONE */
354*3147Sxc151355 	};
355*3147Sxc151355 
356*3147Sxc151355 	if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0)
357*3147Sxc151355 		return (WIFI_SEC_NONE);
358*3147Sxc151355 
359*3147Sxc151355 	key = ieee80211_crypto_getkey(ic);
360*3147Sxc151355 	if (key == NULL)
361*3147Sxc151355 		return (WIFI_SEC_NONE);
362*3147Sxc151355 
363*3147Sxc151355 	cipher = key->wk_cipher->ic_cipher;
364*3147Sxc151355 	ASSERT(cipher < IEEE80211_N(ciphermap));
365*3147Sxc151355 	return (ciphermap[cipher]);
366*3147Sxc151355 }
367*3147Sxc151355 
368*3147Sxc151355 /*
369*3147Sxc151355  * Add privacy headers appropriate for the specified key.
370*3147Sxc151355  */
371*3147Sxc151355 struct ieee80211_key *
372*3147Sxc151355 ieee80211_crypto_encap(ieee80211com_t *ic, mblk_t *mp)
373*3147Sxc151355 {
374*3147Sxc151355 	struct ieee80211_key *k;
375*3147Sxc151355 	const struct ieee80211_cipher *cip;
376*3147Sxc151355 	uint8_t keyix;
377*3147Sxc151355 
378*3147Sxc151355 	if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) {
379*3147Sxc151355 		ieee80211_dbg(IEEE80211_MSG_CRYPTO,
380*3147Sxc151355 			"ieee80211_crypto_encap: %s",
381*3147Sxc151355 			" No default xmit key for frame\n");
382*3147Sxc151355 		return (NULL);
383*3147Sxc151355 	}
384*3147Sxc151355 	keyix = ic->ic_def_txkey;
385*3147Sxc151355 	k = &ic->ic_nw_keys[ic->ic_def_txkey];
386*3147Sxc151355 	cip = k->wk_cipher;
387*3147Sxc151355 	return (cip->ic_encap(k, mp, keyix<<6) ? k : NULL);
388*3147Sxc151355 }
389*3147Sxc151355 
390*3147Sxc151355 /*
391*3147Sxc151355  * Validate and strip privacy headers (and trailer) for a
392*3147Sxc151355  * received frame that has the WEP/Privacy bit set.
393*3147Sxc151355  */
394*3147Sxc151355 struct ieee80211_key *
395*3147Sxc151355 ieee80211_crypto_decap(ieee80211com_t *ic, mblk_t *mp, int hdrlen)
396*3147Sxc151355 {
397*3147Sxc151355 	struct ieee80211_key *k;
398*3147Sxc151355 	const struct ieee80211_cipher *cip;
399*3147Sxc151355 	uint8_t *ivp;
400*3147Sxc151355 	uint8_t keyid;
401*3147Sxc151355 
402*3147Sxc151355 	/* NB: this minimum size data frame could be bigger */
403*3147Sxc151355 	if ((mp->b_wptr - mp->b_rptr) < IEEE80211_WEP_MINLEN) {
404*3147Sxc151355 		ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_decap:"
405*3147Sxc151355 			" WEP data frame too short, len %u\n",
406*3147Sxc151355 			mp->b_wptr - mp->b_rptr);
407*3147Sxc151355 		return (NULL);
408*3147Sxc151355 	}
409*3147Sxc151355 	/*
410*3147Sxc151355 	 * Locate the key. If unicast and there is no unicast
411*3147Sxc151355 	 * key then we fall back to the key id in the header.
412*3147Sxc151355 	 * This assumes unicast keys are only configured when
413*3147Sxc151355 	 * the key id in the header is meaningless (typically 0).
414*3147Sxc151355 	 */
415*3147Sxc151355 	ivp = mp->b_rptr + hdrlen;
416*3147Sxc151355 	keyid = ivp[IEEE80211_WEP_IVLEN];
417*3147Sxc151355 	k = &ic->ic_nw_keys[keyid >> 6];
418*3147Sxc151355 
419*3147Sxc151355 	/* check to avoid panic when wep is on but key is not set */
420*3147Sxc151355 	if (k->wk_cipher == &ieee80211_cipher_none ||
421*3147Sxc151355 	    k->wk_cipher == NULL)
422*3147Sxc151355 		return (NULL);
423*3147Sxc151355 
424*3147Sxc151355 	cip = k->wk_cipher;
425*3147Sxc151355 	return ((cip->ic_decap)(k, mp, hdrlen) ? k : NULL);
426*3147Sxc151355 }
427*3147Sxc151355 
428*3147Sxc151355 
429*3147Sxc151355 /*
430*3147Sxc151355  * Setup crypto support.
431*3147Sxc151355  */
432*3147Sxc151355 void
433*3147Sxc151355 ieee80211_crypto_attach(ieee80211com_t *ic)
434*3147Sxc151355 {
435*3147Sxc151355 	struct ieee80211_crypto_state *cs = &ic->ic_crypto;
436*3147Sxc151355 	int i;
437*3147Sxc151355 
438*3147Sxc151355 	/* NB: we assume everything is pre-zero'd */
439*3147Sxc151355 	cs->cs_def_txkey = IEEE80211_KEYIX_NONE;
440*3147Sxc151355 	for (i = 0; i < IEEE80211_WEP_NKID; i++) {
441*3147Sxc151355 		ieee80211_crypto_resetkey(ic, &cs->cs_nw_keys[i],
442*3147Sxc151355 			IEEE80211_KEYIX_NONE);
443*3147Sxc151355 	}
444*3147Sxc151355 
445*3147Sxc151355 	/*
446*3147Sxc151355 	 * Initialize the driver key support routines to noop entries.
447*3147Sxc151355 	 * This is useful especially for the cipher test modules.
448*3147Sxc151355 	 */
449*3147Sxc151355 	cs->cs_key_alloc = nulldev_key_alloc;
450*3147Sxc151355 	cs->cs_key_set = nulldev_key_set;
451*3147Sxc151355 	cs->cs_key_delete = nulldev_key_delete;
452*3147Sxc151355 	cs->cs_key_update_begin = nulldev_key_update;
453*3147Sxc151355 	cs->cs_key_update_end = nulldev_key_update;
454*3147Sxc151355 
455*3147Sxc151355 	ieee80211_crypto_register(&wep);
456*3147Sxc151355 }
457*3147Sxc151355 
458*3147Sxc151355 /*
459*3147Sxc151355  * Teardown crypto support.
460*3147Sxc151355  */
461*3147Sxc151355 void
462*3147Sxc151355 ieee80211_crypto_detach(ieee80211com_t *ic)
463*3147Sxc151355 {
464*3147Sxc151355 	ieee80211_crypto_delglobalkeys(ic);
465*3147Sxc151355 
466*3147Sxc151355 	ieee80211_crypto_unregister(&wep);
467*3147Sxc151355 }
468*3147Sxc151355 
469*3147Sxc151355 /*
470*3147Sxc151355  * Register a crypto cipher module.
471*3147Sxc151355  */
472*3147Sxc151355 void
473*3147Sxc151355 ieee80211_crypto_register(const struct ieee80211_cipher *cip)
474*3147Sxc151355 {
475*3147Sxc151355 	if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) {
476*3147Sxc151355 		ieee80211_err("ieee80211_crypto_register: "
477*3147Sxc151355 			"cipher %s has an invalid cipher index %u\n",
478*3147Sxc151355 			cip->ic_name, cip->ic_cipher);
479*3147Sxc151355 		return;
480*3147Sxc151355 	}
481*3147Sxc151355 	if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) {
482*3147Sxc151355 		ieee80211_err("ieee80211_crypto_register: "
483*3147Sxc151355 			"cipher %s registered with a different template\n",
484*3147Sxc151355 			cip->ic_name);
485*3147Sxc151355 		return;
486*3147Sxc151355 	}
487*3147Sxc151355 	ciphers[cip->ic_cipher] = cip;
488*3147Sxc151355 }
489*3147Sxc151355 
490*3147Sxc151355 /*
491*3147Sxc151355  * Unregister a crypto cipher module.
492*3147Sxc151355  */
493*3147Sxc151355 void
494*3147Sxc151355 ieee80211_crypto_unregister(const struct ieee80211_cipher *cip)
495*3147Sxc151355 {
496*3147Sxc151355 	if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) {
497*3147Sxc151355 		ieee80211_err("ieee80211_crypto_unregister: "
498*3147Sxc151355 			"cipher %s has an invalid cipher index %u\n",
499*3147Sxc151355 			cip->ic_name, cip->ic_cipher);
500*3147Sxc151355 		return;
501*3147Sxc151355 	}
502*3147Sxc151355 	if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) {
503*3147Sxc151355 		ieee80211_err("ieee80211_crypto_unregister: "
504*3147Sxc151355 			"cipher %s registered with a different template\n",
505*3147Sxc151355 			cip->ic_name);
506*3147Sxc151355 		return;
507*3147Sxc151355 	}
508*3147Sxc151355 	/* NB: don't complain about not being registered */
509*3147Sxc151355 	ciphers[cip->ic_cipher] = NULL;
510*3147Sxc151355 }
511