xref: /dflybsd-src/sys/netproto/802_11/wlan/ieee80211_crypto.c (revision bff82488b6f45c2f067e4c552e649b1d3e07cd7c)
132176cfdSRui Paulo /*-
2f186073cSJoerg Sonnenberger  * Copyright (c) 2001 Atsushi Onoe
332176cfdSRui Paulo  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
4f186073cSJoerg Sonnenberger  * All rights reserved.
5f186073cSJoerg Sonnenberger  *
6f186073cSJoerg Sonnenberger  * Redistribution and use in source and binary forms, with or without
7f186073cSJoerg Sonnenberger  * modification, are permitted provided that the following conditions
8f186073cSJoerg Sonnenberger  * are met:
9f186073cSJoerg Sonnenberger  * 1. Redistributions of source code must retain the above copyright
10f186073cSJoerg Sonnenberger  *    notice, this list of conditions and the following disclaimer.
11f186073cSJoerg Sonnenberger  * 2. Redistributions in binary form must reproduce the above copyright
12f186073cSJoerg Sonnenberger  *    notice, this list of conditions and the following disclaimer in the
13f186073cSJoerg Sonnenberger  *    documentation and/or other materials provided with the distribution.
14f186073cSJoerg Sonnenberger  *
15f186073cSJoerg Sonnenberger  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16f186073cSJoerg Sonnenberger  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17f186073cSJoerg Sonnenberger  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18f186073cSJoerg Sonnenberger  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19f186073cSJoerg Sonnenberger  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20f186073cSJoerg Sonnenberger  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21f186073cSJoerg Sonnenberger  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22f186073cSJoerg Sonnenberger  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23f186073cSJoerg Sonnenberger  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24f186073cSJoerg Sonnenberger  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25f186073cSJoerg Sonnenberger  */
26f186073cSJoerg Sonnenberger 
27085ff963SMatthew Dillon #include <sys/cdefs.h>
28085ff963SMatthew Dillon __FBSDID("$FreeBSD$");
29085ff963SMatthew Dillon 
30841ab66cSSepherosa Ziehau /*
31841ab66cSSepherosa Ziehau  * IEEE 802.11 generic crypto support.
32841ab66cSSepherosa Ziehau  */
3332176cfdSRui Paulo #include "opt_wlan.h"
3432176cfdSRui Paulo 
35f186073cSJoerg Sonnenberger #include <sys/param.h>
3632176cfdSRui Paulo #include <sys/kernel.h>
3732176cfdSRui Paulo #include <sys/malloc.h>
38f186073cSJoerg Sonnenberger #include <sys/mbuf.h>
39f186073cSJoerg Sonnenberger 
40841ab66cSSepherosa Ziehau #include <sys/socket.h>
41f186073cSJoerg Sonnenberger 
42f186073cSJoerg Sonnenberger #include <net/if.h>
43*bff82488SAaron LI #include <net/if_var.h>
44841ab66cSSepherosa Ziehau #include <net/if_media.h>
45841ab66cSSepherosa Ziehau #include <net/ethernet.h>		/* XXX ETHER_HDR_LEN */
46f186073cSJoerg Sonnenberger 
47f186073cSJoerg Sonnenberger #include <netproto/802_11/ieee80211_var.h>
48f186073cSJoerg Sonnenberger 
4932176cfdSRui Paulo MALLOC_DEFINE(M_80211_CRYPTO, "80211crypto", "802.11 crypto state");
5032176cfdSRui Paulo 
5132176cfdSRui Paulo static	int _ieee80211_crypto_delkey(struct ieee80211vap *,
5232176cfdSRui Paulo 		struct ieee80211_key *);
5332176cfdSRui Paulo 
54841ab66cSSepherosa Ziehau /*
55841ab66cSSepherosa Ziehau  * Table of registered cipher modules.
56841ab66cSSepherosa Ziehau  */
57841ab66cSSepherosa Ziehau static	const struct ieee80211_cipher *ciphers[IEEE80211_CIPHER_MAX];
58f186073cSJoerg Sonnenberger 
59841ab66cSSepherosa Ziehau /*
60841ab66cSSepherosa Ziehau  * Default "null" key management routines.
61841ab66cSSepherosa Ziehau  */
62841ab66cSSepherosa Ziehau static int
null_key_alloc(struct ieee80211vap * vap,struct ieee80211_key * k,ieee80211_keyix * keyix,ieee80211_keyix * rxkeyix)6332176cfdSRui Paulo null_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
64841ab66cSSepherosa Ziehau 	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
65f186073cSJoerg Sonnenberger {
6632176cfdSRui Paulo 	if (!(&vap->iv_nw_keys[0] <= k &&
6732176cfdSRui Paulo 	     k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) {
68841ab66cSSepherosa Ziehau 		/*
69841ab66cSSepherosa Ziehau 		 * Not in the global key table, the driver should handle this
70841ab66cSSepherosa Ziehau 		 * by allocating a slot in the h/w key table/cache.  In
71841ab66cSSepherosa Ziehau 		 * lieu of that return key slot 0 for any unicast key
72841ab66cSSepherosa Ziehau 		 * request.  We disallow the request if this is a group key.
73841ab66cSSepherosa Ziehau 		 * This default policy does the right thing for legacy hardware
74841ab66cSSepherosa Ziehau 		 * with a 4 key table.  It also handles devices that pass
75841ab66cSSepherosa Ziehau 		 * packets through untouched when marked with the WEP bit
76841ab66cSSepherosa Ziehau 		 * and key index 0.
77841ab66cSSepherosa Ziehau 		 */
78841ab66cSSepherosa Ziehau 		if (k->wk_flags & IEEE80211_KEY_GROUP)
79841ab66cSSepherosa Ziehau 			return 0;
80841ab66cSSepherosa Ziehau 		*keyix = 0;	/* NB: use key index 0 for ucast key */
81841ab66cSSepherosa Ziehau 	} else {
8232176cfdSRui Paulo 		*keyix = k - vap->iv_nw_keys;
83841ab66cSSepherosa Ziehau 	}
84841ab66cSSepherosa Ziehau 	*rxkeyix = IEEE80211_KEYIX_NONE;	/* XXX maybe *keyix? */
85841ab66cSSepherosa Ziehau 	return 1;
86841ab66cSSepherosa Ziehau }
87841ab66cSSepherosa Ziehau static int
null_key_delete(struct ieee80211vap * vap,const struct ieee80211_key * k)8832176cfdSRui Paulo null_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
89841ab66cSSepherosa Ziehau {
90841ab66cSSepherosa Ziehau 	return 1;
91841ab66cSSepherosa Ziehau }
92841ab66cSSepherosa Ziehau static 	int
null_key_set(struct ieee80211vap * vap,const struct ieee80211_key * k)934f655ef5SMatthew Dillon null_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
94841ab66cSSepherosa Ziehau {
95841ab66cSSepherosa Ziehau 	return 1;
96841ab66cSSepherosa Ziehau }
null_key_update(struct ieee80211vap * vap)9732176cfdSRui Paulo static void null_key_update(struct ieee80211vap *vap) {}
98841ab66cSSepherosa Ziehau 
99841ab66cSSepherosa Ziehau /*
100841ab66cSSepherosa Ziehau  * Write-arounds for common operations.
101841ab66cSSepherosa Ziehau  */
102841ab66cSSepherosa Ziehau static __inline void
cipher_detach(struct ieee80211_key * key)103841ab66cSSepherosa Ziehau cipher_detach(struct ieee80211_key *key)
104841ab66cSSepherosa Ziehau {
105841ab66cSSepherosa Ziehau 	key->wk_cipher->ic_detach(key);
106841ab66cSSepherosa Ziehau }
107841ab66cSSepherosa Ziehau 
108841ab66cSSepherosa Ziehau static __inline void *
cipher_attach(struct ieee80211vap * vap,struct ieee80211_key * key)10932176cfdSRui Paulo cipher_attach(struct ieee80211vap *vap, struct ieee80211_key *key)
110841ab66cSSepherosa Ziehau {
11132176cfdSRui Paulo 	return key->wk_cipher->ic_attach(vap, key);
112841ab66cSSepherosa Ziehau }
113841ab66cSSepherosa Ziehau 
114841ab66cSSepherosa Ziehau /*
115841ab66cSSepherosa Ziehau  * Wrappers for driver key management methods.
116841ab66cSSepherosa Ziehau  */
117841ab66cSSepherosa Ziehau static __inline int
dev_key_alloc(struct ieee80211vap * vap,struct ieee80211_key * key,ieee80211_keyix * keyix,ieee80211_keyix * rxkeyix)11832176cfdSRui Paulo dev_key_alloc(struct ieee80211vap *vap,
11932176cfdSRui Paulo 	struct ieee80211_key *key,
120841ab66cSSepherosa Ziehau 	ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
121841ab66cSSepherosa Ziehau {
12232176cfdSRui Paulo 	return vap->iv_key_alloc(vap, key, keyix, rxkeyix);
123841ab66cSSepherosa Ziehau }
124841ab66cSSepherosa Ziehau 
125841ab66cSSepherosa Ziehau static __inline int
dev_key_delete(struct ieee80211vap * vap,const struct ieee80211_key * key)12632176cfdSRui Paulo dev_key_delete(struct ieee80211vap *vap,
127841ab66cSSepherosa Ziehau 	const struct ieee80211_key *key)
128841ab66cSSepherosa Ziehau {
12932176cfdSRui Paulo 	return vap->iv_key_delete(vap, key);
130841ab66cSSepherosa Ziehau }
131841ab66cSSepherosa Ziehau 
132841ab66cSSepherosa Ziehau static __inline int
dev_key_set(struct ieee80211vap * vap,const struct ieee80211_key * key)13332176cfdSRui Paulo dev_key_set(struct ieee80211vap *vap, const struct ieee80211_key *key)
134841ab66cSSepherosa Ziehau {
1354f655ef5SMatthew Dillon 	return vap->iv_key_set(vap, key);
136841ab66cSSepherosa Ziehau }
137f186073cSJoerg Sonnenberger 
138f186073cSJoerg Sonnenberger /*
13932176cfdSRui Paulo  * Setup crypto support for a device/shared instance.
140f186073cSJoerg Sonnenberger  */
141f186073cSJoerg Sonnenberger void
ieee80211_crypto_attach(struct ieee80211com * ic)142841ab66cSSepherosa Ziehau ieee80211_crypto_attach(struct ieee80211com *ic)
143f186073cSJoerg Sonnenberger {
144841ab66cSSepherosa Ziehau 	/* NB: we assume everything is pre-zero'd */
145841ab66cSSepherosa Ziehau 	ciphers[IEEE80211_CIPHER_NONE] = &ieee80211_cipher_none;
146f186073cSJoerg Sonnenberger }
147f186073cSJoerg Sonnenberger 
148841ab66cSSepherosa Ziehau /*
149841ab66cSSepherosa Ziehau  * Teardown crypto support.
150841ab66cSSepherosa Ziehau  */
151841ab66cSSepherosa Ziehau void
ieee80211_crypto_detach(struct ieee80211com * ic)152841ab66cSSepherosa Ziehau ieee80211_crypto_detach(struct ieee80211com *ic)
153841ab66cSSepherosa Ziehau {
15432176cfdSRui Paulo }
15532176cfdSRui Paulo 
15632176cfdSRui Paulo /*
15732176cfdSRui Paulo  * Setup crypto support for a vap.
15832176cfdSRui Paulo  */
15932176cfdSRui Paulo void
ieee80211_crypto_vattach(struct ieee80211vap * vap)16032176cfdSRui Paulo ieee80211_crypto_vattach(struct ieee80211vap *vap)
16132176cfdSRui Paulo {
16232176cfdSRui Paulo 	int i;
16332176cfdSRui Paulo 
16432176cfdSRui Paulo 	/* NB: we assume everything is pre-zero'd */
16532176cfdSRui Paulo 	vap->iv_max_keyix = IEEE80211_WEP_NKID;
16632176cfdSRui Paulo 	vap->iv_def_txkey = IEEE80211_KEYIX_NONE;
16732176cfdSRui Paulo 	for (i = 0; i < IEEE80211_WEP_NKID; i++)
16832176cfdSRui Paulo 		ieee80211_crypto_resetkey(vap, &vap->iv_nw_keys[i],
16932176cfdSRui Paulo 			IEEE80211_KEYIX_NONE);
17032176cfdSRui Paulo 	/*
17132176cfdSRui Paulo 	 * Initialize the driver key support routines to noop entries.
17232176cfdSRui Paulo 	 * This is useful especially for the cipher test modules.
17332176cfdSRui Paulo 	 */
17432176cfdSRui Paulo 	vap->iv_key_alloc = null_key_alloc;
17532176cfdSRui Paulo 	vap->iv_key_set = null_key_set;
17632176cfdSRui Paulo 	vap->iv_key_delete = null_key_delete;
17732176cfdSRui Paulo 	vap->iv_key_update_begin = null_key_update;
17832176cfdSRui Paulo 	vap->iv_key_update_end = null_key_update;
17932176cfdSRui Paulo }
18032176cfdSRui Paulo 
18132176cfdSRui Paulo /*
18232176cfdSRui Paulo  * Teardown crypto support for a vap.
18332176cfdSRui Paulo  */
18432176cfdSRui Paulo void
ieee80211_crypto_vdetach(struct ieee80211vap * vap)18532176cfdSRui Paulo ieee80211_crypto_vdetach(struct ieee80211vap *vap)
18632176cfdSRui Paulo {
18732176cfdSRui Paulo 	ieee80211_crypto_delglobalkeys(vap);
188f186073cSJoerg Sonnenberger }
189f186073cSJoerg Sonnenberger 
190841ab66cSSepherosa Ziehau /*
191841ab66cSSepherosa Ziehau  * Register a crypto cipher module.
192841ab66cSSepherosa Ziehau  */
193841ab66cSSepherosa Ziehau void
ieee80211_crypto_register(const struct ieee80211_cipher * cip)194841ab66cSSepherosa Ziehau ieee80211_crypto_register(const struct ieee80211_cipher *cip)
195841ab66cSSepherosa Ziehau {
196841ab66cSSepherosa Ziehau 	if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) {
197a6ec04bcSSascha Wildner 		kprintf("%s: cipher %s has an invalid cipher index %u\n",
198841ab66cSSepherosa Ziehau 			__func__, cip->ic_name, cip->ic_cipher);
199841ab66cSSepherosa Ziehau 		return;
200841ab66cSSepherosa Ziehau 	}
201841ab66cSSepherosa Ziehau 	if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) {
202a6ec04bcSSascha Wildner 		kprintf("%s: cipher %s registered with a different template\n",
203841ab66cSSepherosa Ziehau 			__func__, cip->ic_name);
204841ab66cSSepherosa Ziehau 		return;
205841ab66cSSepherosa Ziehau 	}
206841ab66cSSepherosa Ziehau 	ciphers[cip->ic_cipher] = cip;
207841ab66cSSepherosa Ziehau }
208841ab66cSSepherosa Ziehau 
209841ab66cSSepherosa Ziehau /*
210841ab66cSSepherosa Ziehau  * Unregister a crypto cipher module.
211841ab66cSSepherosa Ziehau  */
212841ab66cSSepherosa Ziehau void
ieee80211_crypto_unregister(const struct ieee80211_cipher * cip)213841ab66cSSepherosa Ziehau ieee80211_crypto_unregister(const struct ieee80211_cipher *cip)
214841ab66cSSepherosa Ziehau {
215841ab66cSSepherosa Ziehau 	if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) {
216a6ec04bcSSascha Wildner 		kprintf("%s: cipher %s has an invalid cipher index %u\n",
217841ab66cSSepherosa Ziehau 			__func__, cip->ic_name, cip->ic_cipher);
218841ab66cSSepherosa Ziehau 		return;
219841ab66cSSepherosa Ziehau 	}
220841ab66cSSepherosa Ziehau 	if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) {
221a6ec04bcSSascha Wildner 		kprintf("%s: cipher %s registered with a different template\n",
222841ab66cSSepherosa Ziehau 			__func__, cip->ic_name);
223841ab66cSSepherosa Ziehau 		return;
224841ab66cSSepherosa Ziehau 	}
225841ab66cSSepherosa Ziehau 	/* NB: don't complain about not being registered */
226841ab66cSSepherosa Ziehau 	/* XXX disallow if references */
227841ab66cSSepherosa Ziehau 	ciphers[cip->ic_cipher] = NULL;
228841ab66cSSepherosa Ziehau }
229841ab66cSSepherosa Ziehau 
230841ab66cSSepherosa Ziehau int
ieee80211_crypto_available(u_int cipher)231841ab66cSSepherosa Ziehau ieee80211_crypto_available(u_int cipher)
232841ab66cSSepherosa Ziehau {
233841ab66cSSepherosa Ziehau 	return cipher < IEEE80211_CIPHER_MAX && ciphers[cipher] != NULL;
234841ab66cSSepherosa Ziehau }
235841ab66cSSepherosa Ziehau 
236841ab66cSSepherosa Ziehau /* XXX well-known names! */
23732176cfdSRui Paulo static const char *cipher_modnames[IEEE80211_CIPHER_MAX] = {
23832176cfdSRui Paulo 	[IEEE80211_CIPHER_WEP]	   = "wlan_wep",
23932176cfdSRui Paulo 	[IEEE80211_CIPHER_TKIP]	   = "wlan_tkip",
24032176cfdSRui Paulo 	[IEEE80211_CIPHER_AES_OCB] = "wlan_aes_ocb",
24132176cfdSRui Paulo 	[IEEE80211_CIPHER_AES_CCM] = "wlan_ccmp",
24232176cfdSRui Paulo 	[IEEE80211_CIPHER_TKIPMIC] = "#4",	/* NB: reserved */
24332176cfdSRui Paulo 	[IEEE80211_CIPHER_CKIP]	   = "wlan_ckip",
24432176cfdSRui Paulo 	[IEEE80211_CIPHER_NONE]	   = "wlan_none",
245841ab66cSSepherosa Ziehau };
246841ab66cSSepherosa Ziehau 
24732176cfdSRui Paulo /* NB: there must be no overlap between user-supplied and device-owned flags */
24832176cfdSRui Paulo CTASSERT((IEEE80211_KEY_COMMON & IEEE80211_KEY_DEVICE) == 0);
24932176cfdSRui Paulo 
250841ab66cSSepherosa Ziehau /*
251841ab66cSSepherosa Ziehau  * Establish a relationship between the specified key and cipher
252841ab66cSSepherosa Ziehau  * and, if necessary, allocate a hardware index from the driver.
25332176cfdSRui Paulo  * Note that when a fixed key index is required it must be specified.
254841ab66cSSepherosa Ziehau  *
255841ab66cSSepherosa Ziehau  * This must be the first call applied to a key; all the other key
256841ab66cSSepherosa Ziehau  * routines assume wk_cipher is setup.
257841ab66cSSepherosa Ziehau  *
258841ab66cSSepherosa Ziehau  * Locking must be handled by the caller using:
25932176cfdSRui Paulo  *	ieee80211_key_update_begin(vap);
26032176cfdSRui Paulo  *	ieee80211_key_update_end(vap);
261841ab66cSSepherosa Ziehau  */
262841ab66cSSepherosa Ziehau int
ieee80211_crypto_newkey(struct ieee80211vap * vap,int cipher,int flags,struct ieee80211_key * key)26332176cfdSRui Paulo ieee80211_crypto_newkey(struct ieee80211vap *vap,
264841ab66cSSepherosa Ziehau 	int cipher, int flags, struct ieee80211_key *key)
265841ab66cSSepherosa Ziehau {
26632176cfdSRui Paulo 	struct ieee80211com *ic = vap->iv_ic;
267841ab66cSSepherosa Ziehau 	const struct ieee80211_cipher *cip;
268841ab66cSSepherosa Ziehau 	ieee80211_keyix keyix, rxkeyix;
269841ab66cSSepherosa Ziehau 	void *keyctx;
270841ab66cSSepherosa Ziehau 	int oflags;
271841ab66cSSepherosa Ziehau 
27232176cfdSRui Paulo 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
27332176cfdSRui Paulo 	    "%s: cipher %u flags 0x%x keyix %u\n",
27432176cfdSRui Paulo 	    __func__, cipher, flags, key->wk_keyix);
27532176cfdSRui Paulo 
276841ab66cSSepherosa Ziehau 	/*
277841ab66cSSepherosa Ziehau 	 * Validate cipher and set reference to cipher routines.
278841ab66cSSepherosa Ziehau 	 */
279841ab66cSSepherosa Ziehau 	if (cipher >= IEEE80211_CIPHER_MAX) {
28032176cfdSRui Paulo 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
281841ab66cSSepherosa Ziehau 		    "%s: invalid cipher %u\n", __func__, cipher);
28232176cfdSRui Paulo 		vap->iv_stats.is_crypto_badcipher++;
283841ab66cSSepherosa Ziehau 		return 0;
284841ab66cSSepherosa Ziehau 	}
285841ab66cSSepherosa Ziehau 	cip = ciphers[cipher];
286841ab66cSSepherosa Ziehau 	if (cip == NULL) {
287841ab66cSSepherosa Ziehau 		/*
288841ab66cSSepherosa Ziehau 		 * Auto-load cipher module if we have a well-known name
289841ab66cSSepherosa Ziehau 		 * for it.  It might be better to use string names rather
290841ab66cSSepherosa Ziehau 		 * than numbers and craft a module name based on the cipher
291841ab66cSSepherosa Ziehau 		 * name; e.g. wlan_cipher_<cipher-name>.
292841ab66cSSepherosa Ziehau 		 */
29332176cfdSRui Paulo 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
294841ab66cSSepherosa Ziehau 		    "%s: unregistered cipher %u, load module %s\n",
295841ab66cSSepherosa Ziehau 		    __func__, cipher, cipher_modnames[cipher]);
296841ab66cSSepherosa Ziehau 		ieee80211_load_module(cipher_modnames[cipher]);
297841ab66cSSepherosa Ziehau 		/*
298841ab66cSSepherosa Ziehau 		 * If cipher module loaded it should immediately
299841ab66cSSepherosa Ziehau 		 * call ieee80211_crypto_register which will fill
300841ab66cSSepherosa Ziehau 		 * in the entry in the ciphers array.
301841ab66cSSepherosa Ziehau 		 */
302841ab66cSSepherosa Ziehau 		cip = ciphers[cipher];
303841ab66cSSepherosa Ziehau 		if (cip == NULL) {
30432176cfdSRui Paulo 			IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
305841ab66cSSepherosa Ziehau 			    "%s: unable to load cipher %u, module %s\n",
30632176cfdSRui Paulo 			    __func__, cipher, cipher_modnames[cipher]);
30732176cfdSRui Paulo 			vap->iv_stats.is_crypto_nocipher++;
308841ab66cSSepherosa Ziehau 			return 0;
309841ab66cSSepherosa Ziehau 		}
310841ab66cSSepherosa Ziehau 	}
311841ab66cSSepherosa Ziehau 
312841ab66cSSepherosa Ziehau 	oflags = key->wk_flags;
313841ab66cSSepherosa Ziehau 	flags &= IEEE80211_KEY_COMMON;
31432176cfdSRui Paulo 	/* NB: preserve device attributes */
31532176cfdSRui Paulo 	flags |= (oflags & IEEE80211_KEY_DEVICE);
316841ab66cSSepherosa Ziehau 	/*
317841ab66cSSepherosa Ziehau 	 * If the hardware does not support the cipher then
318841ab66cSSepherosa Ziehau 	 * fallback to a host-based implementation.
319841ab66cSSepherosa Ziehau 	 */
32032176cfdSRui Paulo 	if ((ic->ic_cryptocaps & (1<<cipher)) == 0) {
32132176cfdSRui Paulo 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
322841ab66cSSepherosa Ziehau 		    "%s: no h/w support for cipher %s, falling back to s/w\n",
323841ab66cSSepherosa Ziehau 		    __func__, cip->ic_name);
324841ab66cSSepherosa Ziehau 		flags |= IEEE80211_KEY_SWCRYPT;
325841ab66cSSepherosa Ziehau 	}
326841ab66cSSepherosa Ziehau 	/*
327841ab66cSSepherosa Ziehau 	 * Hardware TKIP with software MIC is an important
328841ab66cSSepherosa Ziehau 	 * combination; we handle it by flagging each key,
329841ab66cSSepherosa Ziehau 	 * the cipher modules honor it.
330841ab66cSSepherosa Ziehau 	 */
331841ab66cSSepherosa Ziehau 	if (cipher == IEEE80211_CIPHER_TKIP &&
33232176cfdSRui Paulo 	    (ic->ic_cryptocaps & IEEE80211_CRYPTO_TKIPMIC) == 0) {
33332176cfdSRui Paulo 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
334841ab66cSSepherosa Ziehau 		    "%s: no h/w support for TKIP MIC, falling back to s/w\n",
335841ab66cSSepherosa Ziehau 		    __func__);
336841ab66cSSepherosa Ziehau 		flags |= IEEE80211_KEY_SWMIC;
337841ab66cSSepherosa Ziehau 	}
338841ab66cSSepherosa Ziehau 
339841ab66cSSepherosa Ziehau 	/*
340841ab66cSSepherosa Ziehau 	 * Bind cipher to key instance.  Note we do this
341841ab66cSSepherosa Ziehau 	 * after checking the device capabilities so the
342841ab66cSSepherosa Ziehau 	 * cipher module can optimize space usage based on
343841ab66cSSepherosa Ziehau 	 * whether or not it needs to do the cipher work.
344841ab66cSSepherosa Ziehau 	 */
345841ab66cSSepherosa Ziehau 	if (key->wk_cipher != cip || key->wk_flags != flags) {
346841ab66cSSepherosa Ziehau 		/*
347841ab66cSSepherosa Ziehau 		 * Fillin the flags so cipher modules can see s/w
348841ab66cSSepherosa Ziehau 		 * crypto requirements and potentially allocate
349841ab66cSSepherosa Ziehau 		 * different state and/or attach different method
350841ab66cSSepherosa Ziehau 		 * pointers.
351841ab66cSSepherosa Ziehau 		 */
352841ab66cSSepherosa Ziehau 		key->wk_flags = flags;
35332176cfdSRui Paulo 		keyctx = cip->ic_attach(vap, key);
354841ab66cSSepherosa Ziehau 		if (keyctx == NULL) {
35532176cfdSRui Paulo 			IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
356841ab66cSSepherosa Ziehau 				"%s: unable to attach cipher %s\n",
357841ab66cSSepherosa Ziehau 				__func__, cip->ic_name);
358841ab66cSSepherosa Ziehau 			key->wk_flags = oflags;	/* restore old flags */
35932176cfdSRui Paulo 			vap->iv_stats.is_crypto_attachfail++;
360841ab66cSSepherosa Ziehau 			return 0;
361841ab66cSSepherosa Ziehau 		}
36232176cfdSRui Paulo 		cipher_detach(key);
363841ab66cSSepherosa Ziehau 		key->wk_cipher = cip;		/* XXX refcnt? */
364841ab66cSSepherosa Ziehau 		key->wk_private = keyctx;
365841ab66cSSepherosa Ziehau 	}
366841ab66cSSepherosa Ziehau 
367841ab66cSSepherosa Ziehau 	/*
368841ab66cSSepherosa Ziehau 	 * Ask the driver for a key index if we don't have one.
369841ab66cSSepherosa Ziehau 	 * Note that entries in the global key table always have
370841ab66cSSepherosa Ziehau 	 * an index; this means it's safe to call this routine
371841ab66cSSepherosa Ziehau 	 * for these entries just to setup the reference to the
372841ab66cSSepherosa Ziehau 	 * cipher template.  Note also that when using software
373841ab66cSSepherosa Ziehau 	 * crypto we also call the driver to give us a key index.
374841ab66cSSepherosa Ziehau 	 */
37532176cfdSRui Paulo 	if ((key->wk_flags & IEEE80211_KEY_DEVKEY) == 0) {
37632176cfdSRui Paulo 		if (!dev_key_alloc(vap, key, &keyix, &rxkeyix)) {
377841ab66cSSepherosa Ziehau 			/*
37832176cfdSRui Paulo 			 * Unable to setup driver state.
379841ab66cSSepherosa Ziehau 			 */
38032176cfdSRui Paulo 			vap->iv_stats.is_crypto_keyfail++;
38132176cfdSRui Paulo 			IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
382841ab66cSSepherosa Ziehau 			    "%s: unable to setup cipher %s\n",
383841ab66cSSepherosa Ziehau 			    __func__, cip->ic_name);
384841ab66cSSepherosa Ziehau 			return 0;
385841ab66cSSepherosa Ziehau 		}
38632176cfdSRui Paulo 		if (key->wk_flags != flags) {
38732176cfdSRui Paulo 			/*
38832176cfdSRui Paulo 			 * Driver overrode flags we setup; typically because
38932176cfdSRui Paulo 			 * resources were unavailable to handle _this_ key.
39032176cfdSRui Paulo 			 * Re-attach the cipher context to allow cipher
39132176cfdSRui Paulo 			 * modules to handle differing requirements.
39232176cfdSRui Paulo 			 */
39332176cfdSRui Paulo 			IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
39432176cfdSRui Paulo 			    "%s: driver override for cipher %s, flags "
39532176cfdSRui Paulo 			    "0x%x -> 0x%x\n", __func__, cip->ic_name,
39632176cfdSRui Paulo 			    oflags, key->wk_flags);
39732176cfdSRui Paulo 			keyctx = cip->ic_attach(vap, key);
39832176cfdSRui Paulo 			if (keyctx == NULL) {
39932176cfdSRui Paulo 				IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
40032176cfdSRui Paulo 				    "%s: unable to attach cipher %s with "
40132176cfdSRui Paulo 				    "flags 0x%x\n", __func__, cip->ic_name,
40232176cfdSRui Paulo 				    key->wk_flags);
40332176cfdSRui Paulo 				key->wk_flags = oflags;	/* restore old flags */
40432176cfdSRui Paulo 				vap->iv_stats.is_crypto_attachfail++;
40532176cfdSRui Paulo 				return 0;
40632176cfdSRui Paulo 			}
40732176cfdSRui Paulo 			cipher_detach(key);
40832176cfdSRui Paulo 			key->wk_cipher = cip;		/* XXX refcnt? */
40932176cfdSRui Paulo 			key->wk_private = keyctx;
41032176cfdSRui Paulo 		}
411841ab66cSSepherosa Ziehau 		key->wk_keyix = keyix;
412841ab66cSSepherosa Ziehau 		key->wk_rxkeyix = rxkeyix;
41332176cfdSRui Paulo 		key->wk_flags |= IEEE80211_KEY_DEVKEY;
414841ab66cSSepherosa Ziehau 	}
415841ab66cSSepherosa Ziehau 	return 1;
416841ab66cSSepherosa Ziehau }
417841ab66cSSepherosa Ziehau 
418841ab66cSSepherosa Ziehau /*
419841ab66cSSepherosa Ziehau  * Remove the key (no locking, for internal use).
420841ab66cSSepherosa Ziehau  */
421841ab66cSSepherosa Ziehau static int
_ieee80211_crypto_delkey(struct ieee80211vap * vap,struct ieee80211_key * key)42232176cfdSRui Paulo _ieee80211_crypto_delkey(struct ieee80211vap *vap, struct ieee80211_key *key)
423841ab66cSSepherosa Ziehau {
424841ab66cSSepherosa Ziehau 	KASSERT(key->wk_cipher != NULL, ("No cipher!"));
425841ab66cSSepherosa Ziehau 
42632176cfdSRui Paulo 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
427841ab66cSSepherosa Ziehau 	    "%s: %s keyix %u flags 0x%x rsc %ju tsc %ju len %u\n",
428841ab66cSSepherosa Ziehau 	    __func__, key->wk_cipher->ic_name,
429841ab66cSSepherosa Ziehau 	    key->wk_keyix, key->wk_flags,
43032176cfdSRui Paulo 	    key->wk_keyrsc[IEEE80211_NONQOS_TID], key->wk_keytsc,
43132176cfdSRui Paulo 	    key->wk_keylen);
432841ab66cSSepherosa Ziehau 
43332176cfdSRui Paulo 	if (key->wk_flags & IEEE80211_KEY_DEVKEY) {
434841ab66cSSepherosa Ziehau 		/*
435841ab66cSSepherosa Ziehau 		 * Remove hardware entry.
436841ab66cSSepherosa Ziehau 		 */
437841ab66cSSepherosa Ziehau 		/* XXX key cache */
43832176cfdSRui Paulo 		if (!dev_key_delete(vap, key)) {
43932176cfdSRui Paulo 			IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
440841ab66cSSepherosa Ziehau 			    "%s: driver did not delete key index %u\n",
44132176cfdSRui Paulo 			    __func__, key->wk_keyix);
44232176cfdSRui Paulo 			vap->iv_stats.is_crypto_delkey++;
443841ab66cSSepherosa Ziehau 			/* XXX recovery? */
444841ab66cSSepherosa Ziehau 		}
445841ab66cSSepherosa Ziehau 	}
446841ab66cSSepherosa Ziehau 	cipher_detach(key);
447841ab66cSSepherosa Ziehau 	memset(key, 0, sizeof(*key));
44832176cfdSRui Paulo 	ieee80211_crypto_resetkey(vap, key, IEEE80211_KEYIX_NONE);
449841ab66cSSepherosa Ziehau 	return 1;
450841ab66cSSepherosa Ziehau }
451841ab66cSSepherosa Ziehau 
452841ab66cSSepherosa Ziehau /*
453841ab66cSSepherosa Ziehau  * Remove the specified key.
454841ab66cSSepherosa Ziehau  */
455841ab66cSSepherosa Ziehau int
ieee80211_crypto_delkey(struct ieee80211vap * vap,struct ieee80211_key * key)45632176cfdSRui Paulo ieee80211_crypto_delkey(struct ieee80211vap *vap, struct ieee80211_key *key)
457841ab66cSSepherosa Ziehau {
458841ab66cSSepherosa Ziehau 	int status;
459841ab66cSSepherosa Ziehau 
46032176cfdSRui Paulo 	ieee80211_key_update_begin(vap);
46132176cfdSRui Paulo 	status = _ieee80211_crypto_delkey(vap, key);
46232176cfdSRui Paulo 	ieee80211_key_update_end(vap);
463841ab66cSSepherosa Ziehau 	return status;
464841ab66cSSepherosa Ziehau }
465841ab66cSSepherosa Ziehau 
466841ab66cSSepherosa Ziehau /*
467841ab66cSSepherosa Ziehau  * Clear the global key table.
468841ab66cSSepherosa Ziehau  */
469841ab66cSSepherosa Ziehau void
ieee80211_crypto_delglobalkeys(struct ieee80211vap * vap)47032176cfdSRui Paulo ieee80211_crypto_delglobalkeys(struct ieee80211vap *vap)
471841ab66cSSepherosa Ziehau {
472841ab66cSSepherosa Ziehau 	int i;
473841ab66cSSepherosa Ziehau 
47432176cfdSRui Paulo 	ieee80211_key_update_begin(vap);
475841ab66cSSepherosa Ziehau 	for (i = 0; i < IEEE80211_WEP_NKID; i++)
47632176cfdSRui Paulo 		(void) _ieee80211_crypto_delkey(vap, &vap->iv_nw_keys[i]);
47732176cfdSRui Paulo 	ieee80211_key_update_end(vap);
478841ab66cSSepherosa Ziehau }
479841ab66cSSepherosa Ziehau 
480841ab66cSSepherosa Ziehau /*
481841ab66cSSepherosa Ziehau  * Set the contents of the specified key.
482841ab66cSSepherosa Ziehau  *
483841ab66cSSepherosa Ziehau  * Locking must be handled by the caller using:
48432176cfdSRui Paulo  *	ieee80211_key_update_begin(vap);
48532176cfdSRui Paulo  *	ieee80211_key_update_end(vap);
486841ab66cSSepherosa Ziehau  */
487841ab66cSSepherosa Ziehau int
ieee80211_crypto_setkey(struct ieee80211vap * vap,struct ieee80211_key * key)48832176cfdSRui Paulo ieee80211_crypto_setkey(struct ieee80211vap *vap, struct ieee80211_key *key)
489841ab66cSSepherosa Ziehau {
490841ab66cSSepherosa Ziehau 	const struct ieee80211_cipher *cip = key->wk_cipher;
491841ab66cSSepherosa Ziehau 
492841ab66cSSepherosa Ziehau 	KASSERT(cip != NULL, ("No cipher!"));
493841ab66cSSepherosa Ziehau 
49432176cfdSRui Paulo 	IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
4951e290df3SAntonio Huete Jimenez 	    "%s: %s keyix %u flags 0x%x mac %s rsc %ju tsc %ju len %u\n",
496841ab66cSSepherosa Ziehau 	    __func__, cip->ic_name, key->wk_keyix,
497085ff963SMatthew Dillon 	    key->wk_flags, ether_sprintf(key->wk_macaddr),
49832176cfdSRui Paulo 	    key->wk_keyrsc[IEEE80211_NONQOS_TID], key->wk_keytsc,
49932176cfdSRui Paulo 	    key->wk_keylen);
500841ab66cSSepherosa Ziehau 
50132176cfdSRui Paulo 	if ((key->wk_flags & IEEE80211_KEY_DEVKEY)  == 0) {
50232176cfdSRui Paulo 		/* XXX nothing allocated, should not happen */
50332176cfdSRui Paulo 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
50432176cfdSRui Paulo 		    "%s: no device key setup done; should not happen!\n",
50532176cfdSRui Paulo 		    __func__);
50632176cfdSRui Paulo 		vap->iv_stats.is_crypto_setkey_nokey++;
50732176cfdSRui Paulo 		return 0;
50832176cfdSRui Paulo 	}
509841ab66cSSepherosa Ziehau 	/*
510841ab66cSSepherosa Ziehau 	 * Give cipher a chance to validate key contents.
511841ab66cSSepherosa Ziehau 	 * XXX should happen before modifying state.
512841ab66cSSepherosa Ziehau 	 */
513841ab66cSSepherosa Ziehau 	if (!cip->ic_setkey(key)) {
51432176cfdSRui Paulo 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_CRYPTO,
515841ab66cSSepherosa Ziehau 		    "%s: cipher %s rejected key index %u len %u flags 0x%x\n",
516841ab66cSSepherosa Ziehau 		    __func__, cip->ic_name, key->wk_keyix,
517841ab66cSSepherosa Ziehau 		    key->wk_keylen, key->wk_flags);
51832176cfdSRui Paulo 		vap->iv_stats.is_crypto_setkey_cipher++;
519841ab66cSSepherosa Ziehau 		return 0;
520841ab66cSSepherosa Ziehau 	}
52132176cfdSRui Paulo 	return dev_key_set(vap, key);
522841ab66cSSepherosa Ziehau }
523841ab66cSSepherosa Ziehau 
5244f655ef5SMatthew Dillon uint8_t
ieee80211_crypto_get_keyid(struct ieee80211vap * vap,struct ieee80211_key * k)5254f655ef5SMatthew Dillon ieee80211_crypto_get_keyid(struct ieee80211vap *vap, struct ieee80211_key *k)
5264f655ef5SMatthew Dillon {
5274f655ef5SMatthew Dillon 	if (k >= &vap->iv_nw_keys[0] &&
5284f655ef5SMatthew Dillon 	    k <  &vap->iv_nw_keys[IEEE80211_WEP_NKID])
5294f655ef5SMatthew Dillon 		return (k - vap->iv_nw_keys);
5304f655ef5SMatthew Dillon 	else
5314f655ef5SMatthew Dillon 		return (0);
5324f655ef5SMatthew Dillon }
5334f655ef5SMatthew Dillon 
534841ab66cSSepherosa Ziehau struct ieee80211_key *
ieee80211_crypto_get_txkey(struct ieee80211_node * ni,struct mbuf * m)5354f655ef5SMatthew Dillon ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m)
536841ab66cSSepherosa Ziehau {
53732176cfdSRui Paulo 	struct ieee80211vap *vap = ni->ni_vap;
538841ab66cSSepherosa Ziehau 	struct ieee80211_frame *wh;
539841ab66cSSepherosa Ziehau 
540841ab66cSSepherosa Ziehau 	/*
541841ab66cSSepherosa Ziehau 	 * Multicast traffic always uses the multicast key.
542841ab66cSSepherosa Ziehau 	 * Otherwise if a unicast key is set we use that and
543841ab66cSSepherosa Ziehau 	 * it is always key index 0.  When no unicast key is
544841ab66cSSepherosa Ziehau 	 * set we fall back to the default transmit key.
545841ab66cSSepherosa Ziehau 	 */
546841ab66cSSepherosa Ziehau 	wh = mtod(m, struct ieee80211_frame *);
547841ab66cSSepherosa Ziehau 	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
54832176cfdSRui Paulo 	    IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey)) {
54932176cfdSRui Paulo 		if (vap->iv_def_txkey == IEEE80211_KEYIX_NONE) {
55032176cfdSRui Paulo 			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO,
55132176cfdSRui Paulo 			    wh->i_addr1,
55232176cfdSRui Paulo 			    "no default transmit key (%s) deftxkey %u",
55332176cfdSRui Paulo 			    __func__, vap->iv_def_txkey);
55432176cfdSRui Paulo 			vap->iv_stats.is_tx_nodefkey++;
555841ab66cSSepherosa Ziehau 			return NULL;
556841ab66cSSepherosa Ziehau 		}
5574f655ef5SMatthew Dillon 		return &vap->iv_nw_keys[vap->iv_def_txkey];
558841ab66cSSepherosa Ziehau 	}
5594f655ef5SMatthew Dillon 
5604f655ef5SMatthew Dillon 	return &ni->ni_ucastkey;
5614f655ef5SMatthew Dillon }
5624f655ef5SMatthew Dillon 
5634f655ef5SMatthew Dillon /*
5644f655ef5SMatthew Dillon  * Add privacy headers appropriate for the specified key.
5654f655ef5SMatthew Dillon  */
5664f655ef5SMatthew Dillon struct ieee80211_key *
ieee80211_crypto_encap(struct ieee80211_node * ni,struct mbuf * m)5674f655ef5SMatthew Dillon ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m)
5684f655ef5SMatthew Dillon {
5694f655ef5SMatthew Dillon 	struct ieee80211_key *k;
5704f655ef5SMatthew Dillon 	const struct ieee80211_cipher *cip;
5714f655ef5SMatthew Dillon 
5724f655ef5SMatthew Dillon 	if ((k = ieee80211_crypto_get_txkey(ni, m)) != NULL) {
57332176cfdSRui Paulo 		cip = k->wk_cipher;
5744f655ef5SMatthew Dillon 		return (cip->ic_encap(k, m) ? k : NULL);
5754f655ef5SMatthew Dillon 	}
5764f655ef5SMatthew Dillon 
5774f655ef5SMatthew Dillon 	return NULL;
578841ab66cSSepherosa Ziehau }
579841ab66cSSepherosa Ziehau 
580841ab66cSSepherosa Ziehau /*
581841ab66cSSepherosa Ziehau  * Validate and strip privacy headers (and trailer) for a
582841ab66cSSepherosa Ziehau  * received frame that has the WEP/Privacy bit set.
583841ab66cSSepherosa Ziehau  */
584841ab66cSSepherosa Ziehau struct ieee80211_key *
ieee80211_crypto_decap(struct ieee80211_node * ni,struct mbuf * m,int hdrlen)58532176cfdSRui Paulo ieee80211_crypto_decap(struct ieee80211_node *ni, struct mbuf *m, int hdrlen)
586841ab66cSSepherosa Ziehau {
587841ab66cSSepherosa Ziehau #define	IEEE80211_WEP_HDRLEN	(IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
588841ab66cSSepherosa Ziehau #define	IEEE80211_WEP_MINLEN \
589841ab66cSSepherosa Ziehau 	(sizeof(struct ieee80211_frame) + \
590841ab66cSSepherosa Ziehau 	IEEE80211_WEP_HDRLEN + IEEE80211_WEP_CRCLEN)
59132176cfdSRui Paulo 	struct ieee80211vap *vap = ni->ni_vap;
592841ab66cSSepherosa Ziehau 	struct ieee80211_key *k;
593841ab66cSSepherosa Ziehau 	struct ieee80211_frame *wh;
594841ab66cSSepherosa Ziehau 	const struct ieee80211_cipher *cip;
595841ab66cSSepherosa Ziehau 	uint8_t keyid;
596841ab66cSSepherosa Ziehau 
597841ab66cSSepherosa Ziehau 	/* NB: this minimum size data frame could be bigger */
598841ab66cSSepherosa Ziehau 	if (m->m_pkthdr.len < IEEE80211_WEP_MINLEN) {
59932176cfdSRui Paulo 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY,
600841ab66cSSepherosa Ziehau 			"%s: WEP data frame too short, len %u\n",
601841ab66cSSepherosa Ziehau 			__func__, m->m_pkthdr.len);
60232176cfdSRui Paulo 		vap->iv_stats.is_rx_tooshort++;	/* XXX need unique stat? */
603f186073cSJoerg Sonnenberger 		return NULL;
604f186073cSJoerg Sonnenberger 	}
605f186073cSJoerg Sonnenberger 
606f186073cSJoerg Sonnenberger 	/*
607841ab66cSSepherosa Ziehau 	 * Locate the key. If unicast and there is no unicast
608841ab66cSSepherosa Ziehau 	 * key then we fall back to the key id in the header.
609841ab66cSSepherosa Ziehau 	 * This assumes unicast keys are only configured when
610841ab66cSSepherosa Ziehau 	 * the key id in the header is meaningless (typically 0).
611f186073cSJoerg Sonnenberger 	 */
612841ab66cSSepherosa Ziehau 	wh = mtod(m, struct ieee80211_frame *);
61332176cfdSRui Paulo 	m_copydata(m, hdrlen + IEEE80211_WEP_IVLEN, sizeof(keyid), &keyid);
614841ab66cSSepherosa Ziehau 	if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
61532176cfdSRui Paulo 	    IEEE80211_KEY_UNDEFINED(&ni->ni_ucastkey))
61632176cfdSRui Paulo 		k = &vap->iv_nw_keys[keyid >> 6];
617f186073cSJoerg Sonnenberger 	else
618841ab66cSSepherosa Ziehau 		k = &ni->ni_ucastkey;
619f186073cSJoerg Sonnenberger 
620f186073cSJoerg Sonnenberger 	/*
621841ab66cSSepherosa Ziehau 	 * Insure crypto header is contiguous for all decap work.
622f186073cSJoerg Sonnenberger 	 */
623841ab66cSSepherosa Ziehau 	cip = k->wk_cipher;
624841ab66cSSepherosa Ziehau 	if (m->m_len < hdrlen + cip->ic_header &&
625841ab66cSSepherosa Ziehau 	    (m = m_pullup(m, hdrlen + cip->ic_header)) == NULL) {
62632176cfdSRui Paulo 		IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr2,
62732176cfdSRui Paulo 		    "unable to pullup %s header", cip->ic_name);
62832176cfdSRui Paulo 		vap->iv_stats.is_rx_wepfail++;	/* XXX */
62932176cfdSRui Paulo 		return NULL;
630841ab66cSSepherosa Ziehau 	}
631f186073cSJoerg Sonnenberger 
632841ab66cSSepherosa Ziehau 	return (cip->ic_decap(k, m, hdrlen) ? k : NULL);
633841ab66cSSepherosa Ziehau #undef IEEE80211_WEP_MINLEN
634841ab66cSSepherosa Ziehau #undef IEEE80211_WEP_HDRLEN
635f186073cSJoerg Sonnenberger }
6366bd66811SSepherosa Ziehau 
63732176cfdSRui Paulo static void
load_ucastkey(void * arg,struct ieee80211_node * ni)63832176cfdSRui Paulo load_ucastkey(void *arg, struct ieee80211_node *ni)
6396bd66811SSepherosa Ziehau {
64032176cfdSRui Paulo 	struct ieee80211vap *vap = ni->ni_vap;
6416bd66811SSepherosa Ziehau 	struct ieee80211_key *k;
6426bd66811SSepherosa Ziehau 
64332176cfdSRui Paulo 	if (vap->iv_state != IEEE80211_S_RUN)
64432176cfdSRui Paulo 		return;
6456bd66811SSepherosa Ziehau 	k = &ni->ni_ucastkey;
64632176cfdSRui Paulo 	if (k->wk_flags & IEEE80211_KEY_DEVKEY)
64732176cfdSRui Paulo 		dev_key_set(vap, k);
6486bd66811SSepherosa Ziehau }
64932176cfdSRui Paulo 
65032176cfdSRui Paulo /*
65132176cfdSRui Paulo  * Re-load all keys known to the 802.11 layer that may
65232176cfdSRui Paulo  * have hardware state backing them.  This is used by
65332176cfdSRui Paulo  * drivers on resume to push keys down into the device.
65432176cfdSRui Paulo  */
65532176cfdSRui Paulo void
ieee80211_crypto_reload_keys(struct ieee80211com * ic)65632176cfdSRui Paulo ieee80211_crypto_reload_keys(struct ieee80211com *ic)
65732176cfdSRui Paulo {
65832176cfdSRui Paulo 	struct ieee80211vap *vap;
65932176cfdSRui Paulo 	int i;
66032176cfdSRui Paulo 
66132176cfdSRui Paulo 	/*
66232176cfdSRui Paulo 	 * Keys in the global key table of each vap.
66332176cfdSRui Paulo 	 */
66432176cfdSRui Paulo 	/* NB: used only during resume so don't lock for now */
66532176cfdSRui Paulo 	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
66632176cfdSRui Paulo 		if (vap->iv_state != IEEE80211_S_RUN)
66732176cfdSRui Paulo 			continue;
66832176cfdSRui Paulo 		for (i = 0; i < IEEE80211_WEP_NKID; i++) {
66932176cfdSRui Paulo 			const struct ieee80211_key *k = &vap->iv_nw_keys[i];
67032176cfdSRui Paulo 			if (k->wk_flags & IEEE80211_KEY_DEVKEY)
67132176cfdSRui Paulo 				dev_key_set(vap, k);
67232176cfdSRui Paulo 		}
67332176cfdSRui Paulo 	}
67432176cfdSRui Paulo 	/*
67532176cfdSRui Paulo 	 * Unicast keys.
67632176cfdSRui Paulo 	 */
67732176cfdSRui Paulo 	ieee80211_iterate_nodes(&ic->ic_sta, load_ucastkey, NULL);
6786bd66811SSepherosa Ziehau }
679