ieee80211_crypto.c revision 167433
10SN/A/*-
216682Sserb * Copyright (c) 2001 Atsushi Onoe
30SN/A * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
40SN/A * All rights reserved.
50SN/A *
60SN/A * Redistribution and use in source and binary forms, with or without
72362SN/A * modification, are permitted provided that the following conditions
80SN/A * are met:
92362SN/A * 1. Redistributions of source code must retain the above copyright
100SN/A *    notice, this list of conditions and the following disclaimer.
110SN/A * 2. Redistributions in binary form must reproduce the above copyright
120SN/A *    notice, this list of conditions and the following disclaimer in the
130SN/A *    documentation and/or other materials provided with the distribution.
140SN/A * 3. The name of the author may not be used to endorse or promote products
150SN/A *    derived from this software without specific prior written permission.
160SN/A *
170SN/A * Alternatively, this software may be distributed under the terms of the
180SN/A * GNU General Public License ("GPL") version 2 as published by the Free
190SN/A * Software Foundation.
200SN/A *
212362SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
222362SN/A * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
232362SN/A * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
240SN/A * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
250SN/A * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
260SN/A * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
270SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
280SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
290SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
300SN/A * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
310SN/A */
322859SN/A
332859SN/A#include <sys/cdefs.h>
342859SN/A__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_crypto.c 167433 2007-03-11 06:38:26Z sam $");
358979SN/A
361696SN/A/*
370SN/A * IEEE 802.11 generic crypto support.
380SN/A */
390SN/A#include <sys/param.h>
400SN/A#include <sys/mbuf.h>
410SN/A
420SN/A#include <sys/socket.h>
430SN/A
440SN/A#include <net/if.h>
450SN/A#include <net/if_media.h>
460SN/A#include <net/ethernet.h>		/* XXX ETHER_HDR_LEN */
470SN/A
480SN/A#include <net80211/ieee80211_var.h>
490SN/A
500SN/A/*
510SN/A * Table of registered cipher modules.
520SN/A */
530SN/Astatic	const struct ieee80211_cipher *ciphers[IEEE80211_CIPHER_MAX];
540SN/A
550SN/Astatic	int _ieee80211_crypto_delkey(struct ieee80211com *,
560SN/A		struct ieee80211_key *);
570SN/A
580SN/A/*
590SN/A * Default "null" key management routines.
602859SN/A */
611696SN/Astatic int
620SN/Anull_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k,
630SN/A	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
640SN/A{
6516682Sserb	if (!(&ic->ic_nw_keys[0] <= k &&
6616682Sserb	     k < &ic->ic_nw_keys[IEEE80211_WEP_NKID])) {
6716682Sserb		/*
680SN/A		 * Not in the global key table, the driver should handle this
6916682Sserb		 * by allocating a slot in the h/w key table/cache.  In
700SN/A		 * lieu of that return key slot 0 for any unicast key
710SN/A		 * request.  We disallow the request if this is a group key.
720SN/A		 * This default policy does the right thing for legacy hardware
730SN/A		 * with a 4 key table.  It also handles devices that pass
7416682Sserb		 * packets through untouched when marked with the WEP bit
7516682Sserb		 * and key index 0.
7616682Sserb		 */
770SN/A		if (k->wk_flags & IEEE80211_KEY_GROUP)
7816682Sserb			return 0;
790SN/A		*keyix = 0;	/* NB: use key index 0 for ucast key */
800SN/A	} else {
810SN/A		*keyix = k - ic->ic_nw_keys;
820SN/A	}
8316682Sserb	*rxkeyix = IEEE80211_KEYIX_NONE;	/* XXX maybe *keyix? */
8416682Sserb	return 1;
8516682Sserb}
860SN/Astatic int
8716682Sserbnull_key_delete(struct ieee80211com *ic, const struct ieee80211_key *k)
880SN/A{
890SN/A	return 1;
900SN/A}
910SN/Astatic 	int
9216682Sserbnull_key_set(struct ieee80211com *ic, const struct ieee80211_key *k,
9316682Sserb	const u_int8_t mac[IEEE80211_ADDR_LEN])
9416682Sserb{
950SN/A	return 1;
9616682Sserb}
970SN/Astatic void null_key_update(struct ieee80211com *ic) {}
980SN/A
990SN/A/*
1000SN/A * Write-arounds for common operations.
10116682Sserb */
10216682Sserbstatic __inline void
10316682Sserbcipher_detach(struct ieee80211_key *key)
1040SN/A{
10516682Sserb	key->wk_cipher->ic_detach(key);
1060SN/A}
1070SN/A
1080SN/Astatic __inline void *
1090SN/Acipher_attach(struct ieee80211com *ic, struct ieee80211_key *key)
11016682Sserb{
11116682Sserb	return key->wk_cipher->ic_attach(ic, key);
11216682Sserb}
1130SN/A
11416682Sserb/*
1150SN/A * Wrappers for driver key management methods.
1160SN/A */
1170SN/Astatic __inline int
1180SN/Adev_key_alloc(struct ieee80211com *ic,
11916682Sserb	const struct ieee80211_key *key,
12016682Sserb	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
12116682Sserb{
12216682Sserb	return ic->ic_crypto.cs_key_alloc(ic, key, keyix, rxkeyix);
1230SN/A}
12416682Sserb
1250SN/Astatic __inline int
1260SN/Adev_key_delete(struct ieee80211com *ic,
1270SN/A	const struct ieee80211_key *key)
1280SN/A{
12916682Sserb	return ic->ic_crypto.cs_key_delete(ic, key);
13016682Sserb}
13116682Sserb
13216682Sserbstatic __inline int
1330SN/Adev_key_set(struct ieee80211com *ic, const struct ieee80211_key *key,
13416682Sserb	const u_int8_t mac[IEEE80211_ADDR_LEN])
1350SN/A{
1360SN/A	return ic->ic_crypto.cs_key_set(ic, key, mac);
1370SN/A}
1380SN/A
1390SN/A/*
1400SN/A * Setup crypto support.
1410SN/A */
1420SN/Avoid
1430SN/Aieee80211_crypto_attach(struct ieee80211com *ic)
1440SN/A{
1450SN/A	struct ieee80211_crypto_state *cs = &ic->ic_crypto;
1460SN/A	int i;
1470SN/A
1480SN/A	/* NB: we assume everything is pre-zero'd */
1490SN/A	cs->cs_def_txkey = IEEE80211_KEYIX_NONE;
1500SN/A	cs->cs_max_keyix = IEEE80211_WEP_NKID;
1510SN/A	ciphers[IEEE80211_CIPHER_NONE] = &ieee80211_cipher_none;
1520SN/A	for (i = 0; i < IEEE80211_WEP_NKID; i++)
1530SN/A		ieee80211_crypto_resetkey(ic, &cs->cs_nw_keys[i],
1540SN/A			IEEE80211_KEYIX_NONE);
1550SN/A	/*
1560SN/A	 * Initialize the driver key support routines to noop entries.
1570SN/A	 * This is useful especially for the cipher test modules.
1580SN/A	 */
1590SN/A	cs->cs_key_alloc = null_key_alloc;
1600SN/A	cs->cs_key_set = null_key_set;
1610SN/A	cs->cs_key_delete = null_key_delete;
1620SN/A	cs->cs_key_update_begin = null_key_update;
1630SN/A	cs->cs_key_update_end = null_key_update;
1640SN/A}
1650SN/A
1660SN/A/*
1670SN/A * Teardown crypto support.
1680SN/A */
1690SN/Avoid
1700SN/Aieee80211_crypto_detach(struct ieee80211com *ic)
1710SN/A{
1720SN/A	ieee80211_crypto_delglobalkeys(ic);
1730SN/A}
1740SN/A
1750SN/A/*
1760SN/A * Register a crypto cipher module.
1770SN/A */
1780SN/Avoid
1790SN/Aieee80211_crypto_register(const struct ieee80211_cipher *cip)
1800SN/A{
1810SN/A	if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) {
1820SN/A		printf("%s: cipher %s has an invalid cipher index %u\n",
1830SN/A			__func__, cip->ic_name, cip->ic_cipher);
1840SN/A		return;
185870SN/A	}
186870SN/A	if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) {
18716682Sserb		printf("%s: cipher %s registered with a different template\n",
1881224SN/A			__func__, cip->ic_name);
1891224SN/A		return;
19010071SN/A	}
191870SN/A	ciphers[cip->ic_cipher] = cip;
192870SN/A}
193870SN/A
194870SN/A/*
19510729Sserb * Unregister a crypto cipher module.
196870SN/A */
197870SN/Avoid
198870SN/Aieee80211_crypto_unregister(const struct ieee80211_cipher *cip)
199870SN/A{
200870SN/A	if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) {
201870SN/A		printf("%s: cipher %s has an invalid cipher index %u\n",
2021224SN/A			__func__, cip->ic_name, cip->ic_cipher);
2031224SN/A		return;
2041224SN/A	}
2051224SN/A	if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) {
2061224SN/A		printf("%s: cipher %s registered with a different template\n",
2071224SN/A			__func__, cip->ic_name);
2081224SN/A		return;
2091224SN/A	}
2101224SN/A	/* NB: don't complain about not being registered */
2111224SN/A	/* XXX disallow if references */
212870SN/A	ciphers[cip->ic_cipher] = NULL;
213870SN/A}
214870SN/A
21510071SN/Aint
216870SN/Aieee80211_crypto_available(u_int cipher)
217870SN/A{
218870SN/A	return cipher < IEEE80211_CIPHER_MAX && ciphers[cipher] != NULL;
219870SN/A}
220870SN/A
221870SN/A/* XXX well-known names! */
222870SN/Astatic const char *cipher_modnames[] = {
223870SN/A	"wlan_wep",	/* IEEE80211_CIPHER_WEP */
224870SN/A	"wlan_tkip",	/* IEEE80211_CIPHER_TKIP */
225870SN/A	"wlan_aes_ocb",	/* IEEE80211_CIPHER_AES_OCB */
226870SN/A	"wlan_ccmp",	/* IEEE80211_CIPHER_AES_CCM */
227870SN/A	"wlan_ckip",	/* IEEE80211_CIPHER_CKIP */
228870SN/A};
229870SN/A
230870SN/A/*
231870SN/A * Establish a relationship between the specified key and cipher
232870SN/A * and, if necessary, allocate a hardware index from the driver.
233870SN/A * Note that when a fixed key index is required it must be specified
234870SN/A * and we blindly assign it w/o consulting the driver (XXX).
235870SN/A *
236870SN/A * This must be the first call applied to a key; all the other key
237870SN/A * routines assume wk_cipher is setup.
238870SN/A *
239870SN/A * Locking must be handled by the caller using:
240870SN/A *	ieee80211_key_update_begin(ic);
241870SN/A *	ieee80211_key_update_end(ic);
242870SN/A */
243870SN/Aint
244870SN/Aieee80211_crypto_newkey(struct ieee80211com *ic,
245870SN/A	int cipher, int flags, struct ieee80211_key *key)
246870SN/A{
247870SN/A#define	N(a)	(sizeof(a) / sizeof(a[0]))
248870SN/A	const struct ieee80211_cipher *cip;
249870SN/A	ieee80211_keyix keyix, rxkeyix;
250870SN/A	void *keyctx;
251870SN/A	int oflags;
252870SN/A
253870SN/A	/*
254870SN/A	 * Validate cipher and set reference to cipher routines.
255870SN/A	 */
256870SN/A	if (cipher >= IEEE80211_CIPHER_MAX) {
257870SN/A		IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
258870SN/A			"%s: invalid cipher %u\n", __func__, cipher);
259870SN/A		ic->ic_stats.is_crypto_badcipher++;
260870SN/A		return 0;
2619048SN/A	}
2629048SN/A	cip = ciphers[cipher];
263870SN/A	if (cip == NULL) {
264870SN/A		/*
26510071SN/A		 * Auto-load cipher module if we have a well-known name
266870SN/A		 * for it.  It might be better to use string names rather
267870SN/A		 * than numbers and craft a module name based on the cipher
268870SN/A		 * name; e.g. wlan_cipher_<cipher-name>.
269870SN/A		 */
270870SN/A		if (cipher < N(cipher_modnames)) {
271870SN/A			IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
272870SN/A				"%s: unregistered cipher %u, load module %s\n",
27310729Sserb				__func__, cipher, cipher_modnames[cipher]);
274870SN/A			ieee80211_load_module(cipher_modnames[cipher]);
275870SN/A			/*
276870SN/A			 * If cipher module loaded it should immediately
277870SN/A			 * call ieee80211_crypto_register which will fill
2780SN/A			 * in the entry in the ciphers array.
2790SN/A			 */
2800SN/A			cip = ciphers[cipher];
2810SN/A		}
2820SN/A		if (cip == NULL) {
2831224SN/A			IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
2840SN/A				"%s: unable to load cipher %u, module %s\n",
2850SN/A				__func__, cipher,
2860SN/A				cipher < N(cipher_modnames) ?
2870SN/A					cipher_modnames[cipher] : "<unknown>");
2880SN/A			ic->ic_stats.is_crypto_nocipher++;
2890SN/A			return 0;
2900SN/A		}
2910SN/A	}
2920SN/A
2930SN/A	oflags = key->wk_flags;
2940SN/A	flags &= IEEE80211_KEY_COMMON;
2950SN/A	/*
2960SN/A	 * If the hardware does not support the cipher then
2970SN/A	 * fallback to a host-based implementation.
2980SN/A	 */
2990SN/A	if ((ic->ic_caps & (1<<cipher)) == 0) {
3000SN/A		IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
3010SN/A		    "%s: no h/w support for cipher %s, falling back to s/w\n",
3020SN/A		    __func__, cip->ic_name);
3030SN/A		flags |= IEEE80211_KEY_SWCRYPT;
3040SN/A	}
3050SN/A	/*
3060SN/A	 * Hardware TKIP with software MIC is an important
3070SN/A	 * combination; we handle it by flagging each key,
3080SN/A	 * the cipher modules honor it.
3090SN/A	 */
3100SN/A	if (cipher == IEEE80211_CIPHER_TKIP &&
3110SN/A	    (ic->ic_caps & IEEE80211_C_TKIPMIC) == 0) {
3120SN/A		IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
3130SN/A		    "%s: no h/w support for TKIP MIC, falling back to s/w\n",
3140SN/A		    __func__);
3150SN/A		flags |= IEEE80211_KEY_SWMIC;
3160SN/A	}
3170SN/A
3180SN/A	/*
3190SN/A	 * Bind cipher to key instance.  Note we do this
3200SN/A	 * after checking the device capabilities so the
3212859SN/A	 * cipher module can optimize space usage based on
3222859SN/A	 * whether or not it needs to do the cipher work.
3232859SN/A	 */
3242944SN/A	if (key->wk_cipher != cip || key->wk_flags != flags) {
3252859SN/Aagain:
3269449SN/A		/*
3279449SN/A		 * Fillin the flags so cipher modules can see s/w
3289449SN/A		 * crypto requirements and potentially allocate
3299449SN/A		 * different state and/or attach different method
33015526Salexsch		 * pointers.
33115526Salexsch		 *
33215526Salexsch		 * XXX this is not right when s/w crypto fallback
33315526Salexsch		 *     fails and we try to restore previous state.
33415526Salexsch		 */
33515526Salexsch		key->wk_flags = flags;
3362859SN/A		keyctx = cip->ic_attach(ic, key);
3370SN/A		if (keyctx == NULL) {
3380SN/A			IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
3390SN/A				"%s: unable to attach cipher %s\n",
3400SN/A				__func__, cip->ic_name);
3410SN/A			key->wk_flags = oflags;	/* restore old flags */
3420SN/A			ic->ic_stats.is_crypto_attachfail++;
3430SN/A			return 0;
3440SN/A		}
3450SN/A		cipher_detach(key);
3460SN/A		key->wk_cipher = cip;		/* XXX refcnt? */
3470SN/A		key->wk_private = keyctx;
348217SN/A	}
34913629Savstepan	/*
35013629Savstepan	 * Commit to requested usage so driver can see the flags.
3510SN/A	 */
3520SN/A	key->wk_flags = flags;
353217SN/A
354217SN/A	/*
355217SN/A	 * Ask the driver for a key index if we don't have one.
356217SN/A	 * Note that entries in the global key table always have
357217SN/A	 * an index; this means it's safe to call this routine
358217SN/A	 * for these entries just to setup the reference to the
359217SN/A	 * cipher template.  Note also that when using software
360217SN/A	 * crypto we also call the driver to give us a key index.
3615003SN/A	 */
3625003SN/A	if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
3635003SN/A		if (!dev_key_alloc(ic, key, &keyix, &rxkeyix)) {
3645003SN/A			/*
3655003SN/A			 * Driver has no room; fallback to doing crypto
3665003SN/A			 * in the host.  We change the flags and start the
3675003SN/A			 * procedure over.  If we get back here then there's
3685003SN/A			 * no hope and we bail.  Note that this can leave
3695003SN/A			 * the key in a inconsistent state if the caller
37013629Savstepan			 * continues to use it.
371217SN/A			 */
372217SN/A			if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) {
373217SN/A				ic->ic_stats.is_crypto_swfallback++;
374217SN/A				IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
3750SN/A				    "%s: no h/w resources for cipher %s, "
3760SN/A				    "falling back to s/w\n", __func__,
3770SN/A				    cip->ic_name);
3780SN/A				oflags = key->wk_flags;
3790SN/A				flags |= IEEE80211_KEY_SWCRYPT;
3800SN/A				if (cipher == IEEE80211_CIPHER_TKIP)
3810SN/A					flags |= IEEE80211_KEY_SWMIC;
3820SN/A				goto again;
3830SN/A			}
3840SN/A			ic->ic_stats.is_crypto_keyfail++;
3850SN/A			IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
3860SN/A			    "%s: unable to setup cipher %s\n",
3870SN/A			    __func__, cip->ic_name);
3880SN/A			return 0;
3890SN/A		}
3908979SN/A		key->wk_keyix = keyix;
3910SN/A		key->wk_rxkeyix = rxkeyix;
3920SN/A	}
3937387SN/A	return 1;
3941696SN/A#undef N
3950SN/A}
3960SN/A
3970SN/A/*
3980SN/A * Remove the key (no locking, for internal use).
3990SN/A */
4000SN/Astatic int
4010SN/A_ieee80211_crypto_delkey(struct ieee80211com *ic, struct ieee80211_key *key)
4020SN/A{
4030SN/A	ieee80211_keyix keyix;
4040SN/A
4050SN/A	KASSERT(key->wk_cipher != NULL, ("No cipher!"));
4060SN/A
4079048SN/A	IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
4080SN/A	    "%s: %s keyix %u flags 0x%x rsc %ju tsc %ju len %u\n",
4090SN/A	    __func__, key->wk_cipher->ic_name,
41016682Sserb	    key->wk_keyix, key->wk_flags,
4110SN/A	    key->wk_keyrsc, key->wk_keytsc, key->wk_keylen);
4120SN/A
4130SN/A	keyix = key->wk_keyix;
4140SN/A	if (keyix != IEEE80211_KEYIX_NONE) {
4159048SN/A		/*
4160SN/A		 * Remove hardware entry.
4170SN/A		 */
41816682Sserb		/* XXX key cache */
4190SN/A		if (!dev_key_delete(ic, key)) {
4200SN/A			IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
4210SN/A			    "%s: driver did not delete key index %u\n",
4220SN/A			    __func__, keyix);
4239048SN/A			ic->ic_stats.is_crypto_delkey++;
4240SN/A			/* XXX recovery? */
4250SN/A		}
42616682Sserb	}
4270SN/A	cipher_detach(key);
4280SN/A	memset(key, 0, sizeof(*key));
4290SN/A	ieee80211_crypto_resetkey(ic, key, IEEE80211_KEYIX_NONE);
4300SN/A	return 1;
4319048SN/A}
4320SN/A
4330SN/A/*
43416682Sserb * Remove the specified key.
4350SN/A */
4360SN/Aint
4370SN/Aieee80211_crypto_delkey(struct ieee80211com *ic, struct ieee80211_key *key)
4380SN/A{
4399048SN/A	int status;
4400SN/A
4410SN/A	ieee80211_key_update_begin(ic);
44216682Sserb	status = _ieee80211_crypto_delkey(ic, key);
4430SN/A	ieee80211_key_update_end(ic);
4440SN/A	return status;
4450SN/A}
446217SN/A
447217SN/A/*
4489048SN/A * Clear the global key table.
4490SN/A */
4500SN/Avoid
4510SN/Aieee80211_crypto_delglobalkeys(struct ieee80211com *ic)
4520SN/A{
4530SN/A	int i;
4540SN/A
4550SN/A	ieee80211_key_update_begin(ic);
45616682Sserb	for (i = 0; i < IEEE80211_WEP_NKID; i++)
4579048SN/A		(void) _ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[i]);
45816682Sserb	ieee80211_key_update_end(ic);
45916682Sserb}
4600SN/A
46116682Sserb/*
4620SN/A * Set the contents of the specified key.
4630SN/A *
4640SN/A * Locking must be handled by the caller using:
4650SN/A *	ieee80211_key_update_begin(ic);
4660SN/A *	ieee80211_key_update_end(ic);
4670SN/A */
4685003SN/Aint
4695003SN/Aieee80211_crypto_setkey(struct ieee80211com *ic, struct ieee80211_key *key,
4705003SN/A		const u_int8_t macaddr[IEEE80211_ADDR_LEN])
4715003SN/A{
4720SN/A	const struct ieee80211_cipher *cip = key->wk_cipher;
4730SN/A
4745003SN/A	KASSERT(cip != NULL, ("No cipher!"));
4750SN/A
4760SN/A	IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
4770SN/A	    "%s: %s keyix %u flags 0x%x mac %s rsc %ju tsc %ju len %u\n",
4780SN/A	    __func__, cip->ic_name, key->wk_keyix,
4790SN/A	    key->wk_flags, ether_sprintf(macaddr),
48013629Savstepan	    key->wk_keyrsc, key->wk_keytsc, key->wk_keylen);
48113629Savstepan
48213629Savstepan	/*
48313629Savstepan	 * Give cipher a chance to validate key contents.
48413629Savstepan	 * XXX should happen before modifying state.
48513629Savstepan	 */
4860SN/A	if (!cip->ic_setkey(key)) {
4870SN/A		IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
4880SN/A		    "%s: cipher %s rejected key index %u len %u flags 0x%x\n",
48913629Savstepan		    __func__, cip->ic_name, key->wk_keyix,
4900SN/A		    key->wk_keylen, key->wk_flags);
4910SN/A		ic->ic_stats.is_crypto_setkey_cipher++;
4920SN/A		return 0;
4930SN/A	}
4940SN/A	if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
4958242SN/A		/* XXX nothing allocated, should not happen */
4960SN/A		IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
4970SN/A		    "%s: no key index; should not happen!\n", __func__);
4980SN/A		ic->ic_stats.is_crypto_setkey_nokey++;
4990SN/A		return 0;
5000SN/A	}
5019048SN/A	return dev_key_set(ic, key, macaddr);
5020SN/A}
5030SN/A
5040SN/A/*
5050SN/A * Add privacy headers appropriate for the specified key.
5060SN/A */
5070SN/Astruct ieee80211_key *
5080SN/Aieee80211_crypto_encap(struct ieee80211com *ic,
5090SN/A	struct ieee80211_node *ni, struct mbuf *m)
5100SN/A{
5110SN/A	struct ieee80211_key *k;
5120SN/A	struct ieee80211_frame *wh;
5130SN/A	const struct ieee80211_cipher *cip;
5140SN/A	u_int8_t keyid;
5150SN/A
5160SN/A	/*
5170SN/A	 * Multicast traffic always uses the multicast key.
5189048SN/A	 * Otherwise if a unicast key is set we use that and
5190SN/A	 * it is always key index 0.  When no unicast key is
5200SN/A	 * set we fall back to the default transmit key.
5210SN/A	 */
5220SN/A	wh = mtod(m, struct ieee80211_frame *);
5230SN/A	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
5240SN/A	    IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) {
5250SN/A		if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) {
5260SN/A			IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
5270SN/A			    "[%s] no default transmit key (%s) deftxkey %u\n",
5280SN/A			    ether_sprintf(wh->i_addr1), __func__,
5290SN/A			    ic->ic_def_txkey);
5300SN/A			ic->ic_stats.is_tx_nodefkey++;
5310SN/A			return NULL;
53213629Savstepan		}
533217SN/A		keyid = ic->ic_def_txkey;
534217SN/A		k = &ic->ic_nw_keys[ic->ic_def_txkey];
535217SN/A	} else {
536217SN/A		keyid = 0;
537217SN/A		k = &ni->ni_ucastkey;
5380SN/A	}
5399048SN/A	cip = k->wk_cipher;
5409048SN/A	return (cip->ic_encap(k, m, keyid<<6) ? k : NULL);
5419048SN/A}
5420SN/A
543870SN/A/*
5440SN/A * Validate and strip privacy headers (and trailer) for a
5450SN/A * received frame that has the WEP/Privacy bit set.
5460SN/A */
5470SN/Astruct ieee80211_key *
5480SN/Aieee80211_crypto_decap(struct ieee80211com *ic,
5490SN/A	struct ieee80211_node *ni, struct mbuf *m, int hdrlen)
5500SN/A{
5510SN/A#define	IEEE80211_WEP_HDRLEN	(IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
5520SN/A#define	IEEE80211_WEP_MINLEN \
5530SN/A	(sizeof(struct ieee80211_frame) + \
5540SN/A	IEEE80211_WEP_HDRLEN + IEEE80211_WEP_CRCLEN)
5550SN/A	struct ieee80211_key *k;
5560SN/A	struct ieee80211_frame *wh;
5570SN/A	const struct ieee80211_cipher *cip;
5580SN/A	const u_int8_t *ivp;
5590SN/A	u_int8_t keyid;
5600SN/A
5610SN/A	/* NB: this minimum size data frame could be bigger */
5620SN/A	if (m->m_pkthdr.len < IEEE80211_WEP_MINLEN) {
5630SN/A		IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
5640SN/A			"%s: WEP data frame too short, len %u\n",
5650SN/A			__func__, m->m_pkthdr.len);
5660SN/A		ic->ic_stats.is_rx_tooshort++;	/* XXX need unique stat? */
5670SN/A		return NULL;
5680SN/A	}
5690SN/A
5700SN/A	/*
571870SN/A	 * Locate the key. If unicast and there is no unicast
572870SN/A	 * key then we fall back to the key id in the header.
573870SN/A	 * This assumes unicast keys are only configured when
574870SN/A	 * the key id in the header is meaningless (typically 0).
575870SN/A	 */
576870SN/A	wh = mtod(m, struct ieee80211_frame *);
577870SN/A	ivp = mtod(m, const u_int8_t *) + hdrlen;	/* XXX contig */
578870SN/A	keyid = ivp[IEEE80211_WEP_IVLEN];
5790SN/A	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
5800SN/A	    IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey))
5810SN/A		k = &ic->ic_nw_keys[keyid >> 6];
5820SN/A	else
5830SN/A		k = &ni->ni_ucastkey;
5840SN/A
5850SN/A	/*
586	 * Insure crypto header is contiguous for all decap work.
587	 */
588	cip = k->wk_cipher;
589	if (m->m_len < hdrlen + cip->ic_header &&
590	    (m = m_pullup(m, hdrlen + cip->ic_header)) == NULL) {
591		IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
592		    "[%s] unable to pullup %s header\n",
593		    ether_sprintf(wh->i_addr2), cip->ic_name);
594		ic->ic_stats.is_rx_wepfail++;	/* XXX */
595		return 0;
596	}
597
598	return (cip->ic_decap(k, m, hdrlen) ? k : NULL);
599#undef IEEE80211_WEP_MINLEN
600#undef IEEE80211_WEP_HDRLEN
601}
602