1*83228edfSmaxv /* $NetBSD: ieee80211_crypto.c,v 1.23 2018/05/08 07:02:07 maxv Exp $ */
2a8560c32Smaxv
3a8560c32Smaxv /*
440e261aaSdyoung * Copyright (c) 2001 Atsushi Onoe
590634029Sdyoung * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
640e261aaSdyoung * All rights reserved.
740e261aaSdyoung *
840e261aaSdyoung * Redistribution and use in source and binary forms, with or without
940e261aaSdyoung * modification, are permitted provided that the following conditions
1040e261aaSdyoung * are met:
1140e261aaSdyoung * 1. Redistributions of source code must retain the above copyright
1240e261aaSdyoung * notice, this list of conditions and the following disclaimer.
1340e261aaSdyoung * 2. Redistributions in binary form must reproduce the above copyright
1440e261aaSdyoung * notice, this list of conditions and the following disclaimer in the
1540e261aaSdyoung * documentation and/or other materials provided with the distribution.
1640e261aaSdyoung * 3. The name of the author may not be used to endorse or promote products
1740e261aaSdyoung * derived from this software without specific prior written permission.
1840e261aaSdyoung *
1940e261aaSdyoung * Alternatively, this software may be distributed under the terms of the
2040e261aaSdyoung * GNU General Public License ("GPL") version 2 as published by the Free
2140e261aaSdyoung * Software Foundation.
2240e261aaSdyoung *
2340e261aaSdyoung * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2440e261aaSdyoung * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2540e261aaSdyoung * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2640e261aaSdyoung * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2740e261aaSdyoung * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2840e261aaSdyoung * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2940e261aaSdyoung * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3040e261aaSdyoung * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3140e261aaSdyoung * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3240e261aaSdyoung * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3340e261aaSdyoung */
3440e261aaSdyoung
3540e261aaSdyoung #include <sys/cdefs.h>
366e8d0b71Sdyoung #ifdef __FreeBSD__
3787515e34Sskrll __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_crypto.c,v 1.12 2005/08/08 18:46:35 sam Exp $");
3890634029Sdyoung #endif
3990634029Sdyoung #ifdef __NetBSD__
40*83228edfSmaxv __KERNEL_RCSID(0, "$NetBSD: ieee80211_crypto.c,v 1.23 2018/05/08 07:02:07 maxv Exp $");
416e8d0b71Sdyoung #endif
4240e261aaSdyoung
43082aeae6Spooka #ifdef _KERNEL_OPT
4440e261aaSdyoung #include "opt_inet.h"
45082aeae6Spooka #endif
4640e261aaSdyoung
4790634029Sdyoung /*
4890634029Sdyoung * IEEE 802.11 generic crypto support.
4990634029Sdyoung */
5040e261aaSdyoung #include <sys/param.h>
5140e261aaSdyoung #include <sys/mbuf.h>
5290634029Sdyoung
5340e261aaSdyoung #include <sys/socket.h>
5440e261aaSdyoung #include <sys/sockio.h>
5540e261aaSdyoung #include <sys/endian.h>
5640e261aaSdyoung #include <sys/errno.h>
5740e261aaSdyoung #include <sys/proc.h>
5840e261aaSdyoung #include <sys/sysctl.h>
5940e261aaSdyoung
6040e261aaSdyoung #include <net/if.h>
6140e261aaSdyoung #include <net/if_media.h>
6240e261aaSdyoung #include <net/if_arp.h>
63847c5ca1Sdyoung #include <net/if_ether.h>
6440e261aaSdyoung #include <net/if_llc.h>
6540e261aaSdyoung
6690634029Sdyoung #include <net80211/ieee80211_netbsd.h>
6740e261aaSdyoung #include <net80211/ieee80211_var.h>
6840e261aaSdyoung
6990634029Sdyoung /*
7090634029Sdyoung * Table of registered cipher modules.
7190634029Sdyoung */
7290634029Sdyoung static const struct ieee80211_cipher *ciphers[IEEE80211_CIPHER_MAX];
7340e261aaSdyoung
7440e261aaSdyoung #ifdef INET
7540e261aaSdyoung #include <netinet/in.h>
76847c5ca1Sdyoung #include <net/if_ether.h>
77847c5ca1Sdyoung #endif
7840e261aaSdyoung
7990634029Sdyoung static int _ieee80211_crypto_delkey(struct ieee80211com *,
8090634029Sdyoung struct ieee80211_key *);
8140e261aaSdyoung
8290634029Sdyoung /*
8390634029Sdyoung * Default "null" key management routines.
8490634029Sdyoung */
8590634029Sdyoung static int
null_key_alloc(struct ieee80211com * ic,const struct ieee80211_key * k,ieee80211_keyix * keyix,ieee80211_keyix * rxkeyix)8687515e34Sskrll null_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *k,
8787515e34Sskrll ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
8840e261aaSdyoung {
89d2ba8780Sdyoung if (!(&ic->ic_nw_keys[0] <= k &&
90d2ba8780Sdyoung k < &ic->ic_nw_keys[IEEE80211_WEP_NKID])) {
91d2ba8780Sdyoung /*
92d2ba8780Sdyoung * Not in the global key table, the driver should handle this
93d2ba8780Sdyoung * by allocating a slot in the h/w key table/cache. In
94d2ba8780Sdyoung * lieu of that return key slot 0 for any unicast key
95d2ba8780Sdyoung * request. We disallow the request if this is a group key.
96d2ba8780Sdyoung * This default policy does the right thing for legacy hardware
97d2ba8780Sdyoung * with a 4 key table. It also handles devices that pass
98d2ba8780Sdyoung * packets through untouched when marked with the WEP bit
99d2ba8780Sdyoung * and key index 0.
100d2ba8780Sdyoung */
10187515e34Sskrll if (k->wk_flags & IEEE80211_KEY_GROUP)
10287515e34Sskrll return 0;
10387515e34Sskrll *keyix = 0; /* NB: use key index 0 for ucast key */
10487515e34Sskrll } else {
10587515e34Sskrll *keyix = k - ic->ic_nw_keys;
10690634029Sdyoung }
10787515e34Sskrll *rxkeyix = IEEE80211_KEYIX_NONE; /* XXX maybe *keyix? */
10887515e34Sskrll return 1;
109d2ba8780Sdyoung }
110a8560c32Smaxv
11190634029Sdyoung static int
null_key_delete(struct ieee80211com * ic,const struct ieee80211_key * k)112a8560c32Smaxv null_key_delete(struct ieee80211com *ic, const struct ieee80211_key *k)
11390634029Sdyoung {
11490634029Sdyoung return 1;
11590634029Sdyoung }
116a8560c32Smaxv
11790634029Sdyoung static int
null_key_set(struct ieee80211com * ic,const struct ieee80211_key * k,const u_int8_t mac[IEEE80211_ADDR_LEN])118a8560c32Smaxv null_key_set(struct ieee80211com *ic, const struct ieee80211_key *k,
119168cd830Schristos const u_int8_t mac[IEEE80211_ADDR_LEN])
12090634029Sdyoung {
12190634029Sdyoung return 1;
12290634029Sdyoung }
123a8560c32Smaxv
124a8560c32Smaxv static void
null_key_update(struct ieee80211com * ic)125a8560c32Smaxv null_key_update(struct ieee80211com *ic)
126a8560c32Smaxv {
127a8560c32Smaxv ;
128a8560c32Smaxv }
12990634029Sdyoung
13090634029Sdyoung /*
13190634029Sdyoung * Write-arounds for common operations.
13290634029Sdyoung */
13390634029Sdyoung static __inline void
cipher_detach(struct ieee80211_key * key)13490634029Sdyoung cipher_detach(struct ieee80211_key *key)
13590634029Sdyoung {
13690634029Sdyoung key->wk_cipher->ic_detach(key);
13790634029Sdyoung }
13890634029Sdyoung
13990634029Sdyoung /*
14090634029Sdyoung * Wrappers for driver key management methods.
14190634029Sdyoung */
14290634029Sdyoung static __inline int
dev_key_alloc(struct ieee80211com * ic,const struct ieee80211_key * key,ieee80211_keyix * keyix,ieee80211_keyix * rxkeyix)143a8560c32Smaxv dev_key_alloc(struct ieee80211com *ic, const struct ieee80211_key *key,
14487515e34Sskrll ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
14590634029Sdyoung {
14687515e34Sskrll return ic->ic_crypto.cs_key_alloc(ic, key, keyix, rxkeyix);
14790634029Sdyoung }
14890634029Sdyoung
14990634029Sdyoung static __inline int
dev_key_delete(struct ieee80211com * ic,const struct ieee80211_key * key)150a8560c32Smaxv dev_key_delete(struct ieee80211com *ic, const struct ieee80211_key *key)
15190634029Sdyoung {
15290634029Sdyoung return ic->ic_crypto.cs_key_delete(ic, key);
15390634029Sdyoung }
15490634029Sdyoung
15590634029Sdyoung static __inline int
dev_key_set(struct ieee80211com * ic,const struct ieee80211_key * key,const u_int8_t mac[IEEE80211_ADDR_LEN])15690634029Sdyoung dev_key_set(struct ieee80211com *ic, const struct ieee80211_key *key,
15790634029Sdyoung const u_int8_t mac[IEEE80211_ADDR_LEN])
15890634029Sdyoung {
15990634029Sdyoung return ic->ic_crypto.cs_key_set(ic, key, mac);
16090634029Sdyoung }
16140e261aaSdyoung
16240e261aaSdyoung /*
16340e261aaSdyoung * Setup crypto support.
16440e261aaSdyoung */
16540e261aaSdyoung void
ieee80211_crypto_attach(struct ieee80211com * ic)16690634029Sdyoung ieee80211_crypto_attach(struct ieee80211com *ic)
16740e261aaSdyoung {
16890634029Sdyoung struct ieee80211_crypto_state *cs = &ic->ic_crypto;
16990634029Sdyoung int i;
17040e261aaSdyoung
17190634029Sdyoung /* NB: we assume everything is pre-zero'd */
17290634029Sdyoung cs->cs_def_txkey = IEEE80211_KEYIX_NONE;
17387515e34Sskrll cs->cs_max_keyix = IEEE80211_WEP_NKID;
17490634029Sdyoung ciphers[IEEE80211_CIPHER_NONE] = &ieee80211_cipher_none;
17590634029Sdyoung for (i = 0; i < IEEE80211_WEP_NKID; i++)
17690634029Sdyoung ieee80211_crypto_resetkey(ic, &cs->cs_nw_keys[i],
17790634029Sdyoung IEEE80211_KEYIX_NONE);
17840e261aaSdyoung /*
17990634029Sdyoung * Initialize the driver key support routines to noop entries.
18090634029Sdyoung * This is useful especially for the cipher test modules.
18140e261aaSdyoung */
18290634029Sdyoung cs->cs_key_alloc = null_key_alloc;
18390634029Sdyoung cs->cs_key_set = null_key_set;
18490634029Sdyoung cs->cs_key_delete = null_key_delete;
18590634029Sdyoung cs->cs_key_update_begin = null_key_update;
18690634029Sdyoung cs->cs_key_update_end = null_key_update;
18740e261aaSdyoung }
18840e261aaSdyoung
18990634029Sdyoung /*
19090634029Sdyoung * Teardown crypto support.
19190634029Sdyoung */
19290634029Sdyoung void
ieee80211_crypto_detach(struct ieee80211com * ic)19390634029Sdyoung ieee80211_crypto_detach(struct ieee80211com *ic)
19490634029Sdyoung {
19590634029Sdyoung ieee80211_crypto_delglobalkeys(ic);
19640e261aaSdyoung }
19740e261aaSdyoung
19890634029Sdyoung /*
19990634029Sdyoung * Register a crypto cipher module.
20090634029Sdyoung */
20190634029Sdyoung void
ieee80211_crypto_register(const struct ieee80211_cipher * cip)20290634029Sdyoung ieee80211_crypto_register(const struct ieee80211_cipher *cip)
20390634029Sdyoung {
20490634029Sdyoung if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) {
20590634029Sdyoung printf("%s: cipher %s has an invalid cipher index %u\n",
20690634029Sdyoung __func__, cip->ic_name, cip->ic_cipher);
20790634029Sdyoung return;
20890634029Sdyoung }
20990634029Sdyoung if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) {
21090634029Sdyoung printf("%s: cipher %s registered with a different template\n",
21190634029Sdyoung __func__, cip->ic_name);
21290634029Sdyoung return;
21390634029Sdyoung }
21490634029Sdyoung ciphers[cip->ic_cipher] = cip;
21590634029Sdyoung }
21690634029Sdyoung
21790634029Sdyoung /*
21890634029Sdyoung * Unregister a crypto cipher module.
21990634029Sdyoung */
22090634029Sdyoung void
ieee80211_crypto_unregister(const struct ieee80211_cipher * cip)22190634029Sdyoung ieee80211_crypto_unregister(const struct ieee80211_cipher *cip)
22290634029Sdyoung {
22390634029Sdyoung if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) {
22490634029Sdyoung printf("%s: cipher %s has an invalid cipher index %u\n",
22590634029Sdyoung __func__, cip->ic_name, cip->ic_cipher);
22690634029Sdyoung return;
22790634029Sdyoung }
22890634029Sdyoung if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) {
22990634029Sdyoung printf("%s: cipher %s registered with a different template\n",
23090634029Sdyoung __func__, cip->ic_name);
23190634029Sdyoung return;
23290634029Sdyoung }
23390634029Sdyoung /* NB: don't complain about not being registered */
23490634029Sdyoung /* XXX disallow if references */
23590634029Sdyoung ciphers[cip->ic_cipher] = NULL;
23690634029Sdyoung }
23790634029Sdyoung
23890634029Sdyoung int
ieee80211_crypto_available(u_int cipher)23990634029Sdyoung ieee80211_crypto_available(u_int cipher)
24090634029Sdyoung {
24190634029Sdyoung return cipher < IEEE80211_CIPHER_MAX && ciphers[cipher] != NULL;
24290634029Sdyoung }
24390634029Sdyoung
24490634029Sdyoung /* XXX well-known names! */
24590634029Sdyoung static const char *cipher_modnames[] = {
24690634029Sdyoung "wlan_wep", /* IEEE80211_CIPHER_WEP */
24790634029Sdyoung "wlan_tkip", /* IEEE80211_CIPHER_TKIP */
24890634029Sdyoung "wlan_aes_ocb", /* IEEE80211_CIPHER_AES_OCB */
24990634029Sdyoung "wlan_ccmp", /* IEEE80211_CIPHER_AES_CCM */
25090634029Sdyoung "wlan_ckip", /* IEEE80211_CIPHER_CKIP */
25190634029Sdyoung };
25290634029Sdyoung
25390634029Sdyoung /*
25490634029Sdyoung * Establish a relationship between the specified key and cipher
25590634029Sdyoung * and, if necessary, allocate a hardware index from the driver.
25690634029Sdyoung * Note that when a fixed key index is required it must be specified
25790634029Sdyoung * and we blindly assign it w/o consulting the driver (XXX).
25890634029Sdyoung *
25990634029Sdyoung * This must be the first call applied to a key; all the other key
26090634029Sdyoung * routines assume wk_cipher is setup.
26190634029Sdyoung *
26290634029Sdyoung * Locking must be handled by the caller using:
26390634029Sdyoung * ieee80211_key_update_begin(ic);
26490634029Sdyoung * ieee80211_key_update_end(ic);
26590634029Sdyoung */
26690634029Sdyoung int
ieee80211_crypto_newkey(struct ieee80211com * ic,int cipher,int flags,struct ieee80211_key * key)267a8560c32Smaxv ieee80211_crypto_newkey(struct ieee80211com *ic, int cipher, int flags,
268a8560c32Smaxv struct ieee80211_key *key)
26990634029Sdyoung {
27090634029Sdyoung #define N(a) (sizeof(a) / sizeof(a[0]))
27190634029Sdyoung const struct ieee80211_cipher *cip;
27287515e34Sskrll ieee80211_keyix keyix, rxkeyix;
27390634029Sdyoung void *keyctx;
27490634029Sdyoung int oflags;
27590634029Sdyoung
27690634029Sdyoung /*
27790634029Sdyoung * Validate cipher and set reference to cipher routines.
27890634029Sdyoung */
27990634029Sdyoung if (cipher >= IEEE80211_CIPHER_MAX) {
28090634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
28190634029Sdyoung "%s: invalid cipher %u\n", __func__, cipher);
28290634029Sdyoung ic->ic_stats.is_crypto_badcipher++;
28390634029Sdyoung return 0;
28490634029Sdyoung }
28590634029Sdyoung cip = ciphers[cipher];
286a8560c32Smaxv
28790634029Sdyoung if (cip == NULL) {
28890634029Sdyoung /*
28990634029Sdyoung * Auto-load cipher module if we have a well-known name
29090634029Sdyoung * for it. It might be better to use string names rather
29190634029Sdyoung * than numbers and craft a module name based on the cipher
29290634029Sdyoung * name; e.g. wlan_cipher_<cipher-name>.
29390634029Sdyoung */
29490634029Sdyoung if (cipher < N(cipher_modnames)) {
29590634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
29690634029Sdyoung "%s: unregistered cipher %u, load module %s\n",
29790634029Sdyoung __func__, cipher, cipher_modnames[cipher]);
29890634029Sdyoung ieee80211_load_module(cipher_modnames[cipher]);
29990634029Sdyoung /*
30090634029Sdyoung * If cipher module loaded it should immediately
30190634029Sdyoung * call ieee80211_crypto_register which will fill
30290634029Sdyoung * in the entry in the ciphers array.
30390634029Sdyoung */
30490634029Sdyoung cip = ciphers[cipher];
30590634029Sdyoung }
30690634029Sdyoung if (cip == NULL) {
30790634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
30890634029Sdyoung "%s: unable to load cipher %u, module %s\n",
30990634029Sdyoung __func__, cipher,
31090634029Sdyoung cipher < N(cipher_modnames) ?
31190634029Sdyoung cipher_modnames[cipher] : "<unknown>");
31290634029Sdyoung ic->ic_stats.is_crypto_nocipher++;
31390634029Sdyoung return 0;
31490634029Sdyoung }
31590634029Sdyoung }
31690634029Sdyoung
31790634029Sdyoung oflags = key->wk_flags;
31890634029Sdyoung flags &= IEEE80211_KEY_COMMON;
319a8560c32Smaxv
32090634029Sdyoung /*
32190634029Sdyoung * If the hardware does not support the cipher then
32290634029Sdyoung * fall back to a host-based implementation.
32390634029Sdyoung */
32490634029Sdyoung if ((ic->ic_caps & (1<<cipher)) == 0) {
32590634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
32690634029Sdyoung "%s: no h/w support for cipher %s, falling back to s/w\n",
32790634029Sdyoung __func__, cip->ic_name);
32890634029Sdyoung flags |= IEEE80211_KEY_SWCRYPT;
32990634029Sdyoung }
330a8560c32Smaxv
33190634029Sdyoung /*
33290634029Sdyoung * Hardware TKIP with software MIC is an important
33390634029Sdyoung * combination; we handle it by flagging each key,
33490634029Sdyoung * the cipher modules honor it.
33590634029Sdyoung */
33690634029Sdyoung if (cipher == IEEE80211_CIPHER_TKIP &&
33790634029Sdyoung (ic->ic_caps & IEEE80211_C_TKIPMIC) == 0) {
33890634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
33990634029Sdyoung "%s: no h/w support for TKIP MIC, falling back to s/w\n",
34090634029Sdyoung __func__);
34190634029Sdyoung flags |= IEEE80211_KEY_SWMIC;
34290634029Sdyoung }
34390634029Sdyoung
34490634029Sdyoung /*
34590634029Sdyoung * Bind cipher to key instance. Note we do this
34690634029Sdyoung * after checking the device capabilities so the
34790634029Sdyoung * cipher module can optimize space usage based on
34890634029Sdyoung * whether or not it needs to do the cipher work.
34990634029Sdyoung */
35090634029Sdyoung if (key->wk_cipher != cip || key->wk_flags != flags) {
35190634029Sdyoung again:
35290634029Sdyoung /*
35390634029Sdyoung * Fillin the flags so cipher modules can see s/w
35490634029Sdyoung * crypto requirements and potentially allocate
35590634029Sdyoung * different state and/or attach different method
35690634029Sdyoung * pointers.
35790634029Sdyoung *
35890634029Sdyoung * XXX this is not right when s/w crypto fallback
35990634029Sdyoung * fails and we try to restore previous state.
36090634029Sdyoung */
36190634029Sdyoung key->wk_flags = flags;
36290634029Sdyoung keyctx = cip->ic_attach(ic, key);
36390634029Sdyoung if (keyctx == NULL) {
36490634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
36590634029Sdyoung "%s: unable to attach cipher %s\n",
36690634029Sdyoung __func__, cip->ic_name);
36790634029Sdyoung key->wk_flags = oflags; /* restore old flags */
36890634029Sdyoung ic->ic_stats.is_crypto_attachfail++;
36990634029Sdyoung return 0;
37090634029Sdyoung }
37190634029Sdyoung cipher_detach(key);
37290634029Sdyoung key->wk_cipher = cip; /* XXX refcnt? */
37390634029Sdyoung key->wk_private = keyctx;
37490634029Sdyoung }
37590634029Sdyoung /*
37690634029Sdyoung * Commit to requested usage so driver can see the flags.
37790634029Sdyoung */
37890634029Sdyoung key->wk_flags = flags;
37990634029Sdyoung
38090634029Sdyoung /*
38190634029Sdyoung * Ask the driver for a key index if we don't have one.
38290634029Sdyoung * Note that entries in the global key table always have
38390634029Sdyoung * an index; this means it's safe to call this routine
38490634029Sdyoung * for these entries just to setup the reference to the
38590634029Sdyoung * cipher template. Note also that when using software
38690634029Sdyoung * crypto we also call the driver to give us a key index.
38790634029Sdyoung */
38890634029Sdyoung if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
38987515e34Sskrll if (!dev_key_alloc(ic, key, &keyix, &rxkeyix)) {
39090634029Sdyoung /*
39190634029Sdyoung * Driver has no room; fallback to doing crypto
39290634029Sdyoung * in the host. We change the flags and start the
39390634029Sdyoung * procedure over. If we get back here then there's
39490634029Sdyoung * no hope and we bail. Note that this can leave
39590634029Sdyoung * the key in a inconsistent state if the caller
39690634029Sdyoung * continues to use it.
39790634029Sdyoung */
39890634029Sdyoung if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) {
39990634029Sdyoung ic->ic_stats.is_crypto_swfallback++;
40090634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
40190634029Sdyoung "%s: no h/w resources for cipher %s, "
40290634029Sdyoung "falling back to s/w\n", __func__,
40390634029Sdyoung cip->ic_name);
40490634029Sdyoung oflags = key->wk_flags;
40590634029Sdyoung flags |= IEEE80211_KEY_SWCRYPT;
40690634029Sdyoung if (cipher == IEEE80211_CIPHER_TKIP)
40790634029Sdyoung flags |= IEEE80211_KEY_SWMIC;
40890634029Sdyoung goto again;
40990634029Sdyoung }
41090634029Sdyoung ic->ic_stats.is_crypto_keyfail++;
41190634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
41290634029Sdyoung "%s: unable to setup cipher %s\n",
41390634029Sdyoung __func__, cip->ic_name);
41490634029Sdyoung return 0;
41590634029Sdyoung }
41687515e34Sskrll key->wk_keyix = keyix;
41787515e34Sskrll key->wk_rxkeyix = rxkeyix;
41890634029Sdyoung }
41990634029Sdyoung return 1;
42090634029Sdyoung #undef N
42190634029Sdyoung }
42290634029Sdyoung
42390634029Sdyoung /*
42490634029Sdyoung * Remove the key (no locking, for internal use).
42590634029Sdyoung */
42690634029Sdyoung static int
_ieee80211_crypto_delkey(struct ieee80211com * ic,struct ieee80211_key * key)42790634029Sdyoung _ieee80211_crypto_delkey(struct ieee80211com *ic, struct ieee80211_key *key)
42890634029Sdyoung {
42987515e34Sskrll ieee80211_keyix keyix;
43090634029Sdyoung
43190634029Sdyoung IASSERT(key->wk_cipher != NULL, ("No cipher!"));
43290634029Sdyoung
43390634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
43490634029Sdyoung "%s: %s keyix %u flags 0x%x rsc %ju tsc %ju len %u\n",
43590634029Sdyoung __func__, key->wk_cipher->ic_name,
43690634029Sdyoung key->wk_keyix, key->wk_flags,
43790634029Sdyoung key->wk_keyrsc, key->wk_keytsc, key->wk_keylen);
43890634029Sdyoung
43990634029Sdyoung keyix = key->wk_keyix;
44090634029Sdyoung if (keyix != IEEE80211_KEYIX_NONE) {
44190634029Sdyoung /*
44290634029Sdyoung * Remove hardware entry.
44390634029Sdyoung */
44490634029Sdyoung /* XXX key cache */
44590634029Sdyoung if (!dev_key_delete(ic, key)) {
44690634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
44790634029Sdyoung "%s: driver did not delete key index %u\n",
44890634029Sdyoung __func__, keyix);
44990634029Sdyoung ic->ic_stats.is_crypto_delkey++;
45090634029Sdyoung /* XXX recovery? */
45190634029Sdyoung }
45290634029Sdyoung }
45390634029Sdyoung cipher_detach(key);
45490634029Sdyoung memset(key, 0, sizeof(*key));
45590634029Sdyoung ieee80211_crypto_resetkey(ic, key, IEEE80211_KEYIX_NONE);
45690634029Sdyoung return 1;
45790634029Sdyoung }
45890634029Sdyoung
45990634029Sdyoung /*
46090634029Sdyoung * Remove the specified key.
46190634029Sdyoung */
46290634029Sdyoung int
ieee80211_crypto_delkey(struct ieee80211com * ic,struct ieee80211_key * key)46390634029Sdyoung ieee80211_crypto_delkey(struct ieee80211com *ic, struct ieee80211_key *key)
46490634029Sdyoung {
46590634029Sdyoung int status;
46690634029Sdyoung
46790634029Sdyoung ieee80211_key_update_begin(ic);
46890634029Sdyoung status = _ieee80211_crypto_delkey(ic, key);
46990634029Sdyoung ieee80211_key_update_end(ic);
47090634029Sdyoung return status;
47190634029Sdyoung }
47290634029Sdyoung
47390634029Sdyoung /*
47490634029Sdyoung * Clear the global key table.
47590634029Sdyoung */
47690634029Sdyoung void
ieee80211_crypto_delglobalkeys(struct ieee80211com * ic)47790634029Sdyoung ieee80211_crypto_delglobalkeys(struct ieee80211com *ic)
47890634029Sdyoung {
47990634029Sdyoung int i;
48090634029Sdyoung
48190634029Sdyoung ieee80211_key_update_begin(ic);
48290634029Sdyoung for (i = 0; i < IEEE80211_WEP_NKID; i++)
48390634029Sdyoung (void)_ieee80211_crypto_delkey(ic, &ic->ic_nw_keys[i]);
48490634029Sdyoung ieee80211_key_update_end(ic);
48590634029Sdyoung }
48690634029Sdyoung
48790634029Sdyoung /*
48890634029Sdyoung * Set the contents of the specified key.
48990634029Sdyoung *
49090634029Sdyoung * Locking must be handled by the caller using:
49190634029Sdyoung * ieee80211_key_update_begin(ic);
49290634029Sdyoung * ieee80211_key_update_end(ic);
49390634029Sdyoung */
49490634029Sdyoung int
ieee80211_crypto_setkey(struct ieee80211com * ic,struct ieee80211_key * key,const u_int8_t macaddr[IEEE80211_ADDR_LEN])49590634029Sdyoung ieee80211_crypto_setkey(struct ieee80211com *ic, struct ieee80211_key *key,
49690634029Sdyoung const u_int8_t macaddr[IEEE80211_ADDR_LEN])
49790634029Sdyoung {
49890634029Sdyoung const struct ieee80211_cipher *cip = key->wk_cipher;
49990634029Sdyoung
50090634029Sdyoung IASSERT(cip != NULL, ("No cipher!"));
50190634029Sdyoung
50290634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
50390634029Sdyoung "%s: %s keyix %u flags 0x%x mac %s rsc %ju tsc %ju len %u\n",
50490634029Sdyoung __func__, cip->ic_name, key->wk_keyix,
50590634029Sdyoung key->wk_flags, ether_sprintf(macaddr),
50690634029Sdyoung key->wk_keyrsc, key->wk_keytsc, key->wk_keylen);
50790634029Sdyoung
50890634029Sdyoung /*
50990634029Sdyoung * Give cipher a chance to validate key contents.
51090634029Sdyoung * XXX should happen before modifying state.
51190634029Sdyoung */
51290634029Sdyoung if (!cip->ic_setkey(key)) {
51390634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
51490634029Sdyoung "%s: cipher %s rejected key index %u len %u flags 0x%x\n",
51590634029Sdyoung __func__, cip->ic_name, key->wk_keyix,
51690634029Sdyoung key->wk_keylen, key->wk_flags);
51790634029Sdyoung ic->ic_stats.is_crypto_setkey_cipher++;
51890634029Sdyoung return 0;
51990634029Sdyoung }
52090634029Sdyoung if (key->wk_keyix == IEEE80211_KEYIX_NONE) {
52190634029Sdyoung /* XXX nothing allocated, should not happen */
52290634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
52390634029Sdyoung "%s: no key index; should not happen!\n", __func__);
52490634029Sdyoung ic->ic_stats.is_crypto_setkey_nokey++;
52590634029Sdyoung return 0;
52690634029Sdyoung }
52790634029Sdyoung return dev_key_set(ic, key, macaddr);
52890634029Sdyoung }
52990634029Sdyoung
53090634029Sdyoung /*
53190634029Sdyoung * Add privacy headers appropriate for the specified key.
532d1b4a5beSmaxv *
533d1b4a5beSmaxv * XXX XXX XXX: Here we modify 'm', and potentially reallocate it. We
534d1b4a5beSmaxv * should pass back to the caller the updated pointer to avoid
535d1b4a5beSmaxv * use-after-frees. This can be done by changing the argument to be **m,
536d1b4a5beSmaxv * but many drivers will have to be changed accordingly.
53790634029Sdyoung */
53890634029Sdyoung struct ieee80211_key *
ieee80211_crypto_encap(struct ieee80211com * ic,struct ieee80211_node * ni,struct mbuf * m)539a8560c32Smaxv ieee80211_crypto_encap(struct ieee80211com *ic, struct ieee80211_node *ni,
540a8560c32Smaxv struct mbuf *m)
54190634029Sdyoung {
54290634029Sdyoung struct ieee80211_key *k;
54390634029Sdyoung struct ieee80211_frame *wh;
54490634029Sdyoung const struct ieee80211_cipher *cip;
545a8560c32Smaxv u_int8_t keyid, *hdr;
546a8560c32Smaxv int hdrlen;
54790634029Sdyoung
54890634029Sdyoung /*
54990634029Sdyoung * Multicast traffic always uses the multicast key.
55090634029Sdyoung * Otherwise if a unicast key is set we use that and
55190634029Sdyoung * it is always key index 0. When no unicast key is
55290634029Sdyoung * set we fall back to the default transmit key.
55390634029Sdyoung */
55490634029Sdyoung wh = mtod(m, struct ieee80211_frame *);
55590634029Sdyoung if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
55690634029Sdyoung ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
55790634029Sdyoung if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) {
55890634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_CRYPTO,
55990634029Sdyoung "[%s] no default transmit key (%s) deftxkey %u\n",
56090634029Sdyoung ether_sprintf(wh->i_addr1), __func__,
56190634029Sdyoung ic->ic_def_txkey);
56290634029Sdyoung ic->ic_stats.is_tx_nodefkey++;
56387515e34Sskrll return NULL;
56490634029Sdyoung }
56590634029Sdyoung keyid = ic->ic_def_txkey;
56690634029Sdyoung k = &ic->ic_nw_keys[ic->ic_def_txkey];
56790634029Sdyoung } else {
56890634029Sdyoung keyid = 0;
56990634029Sdyoung k = &ni->ni_ucastkey;
57090634029Sdyoung }
57190634029Sdyoung cip = k->wk_cipher;
572a8560c32Smaxv
573a8560c32Smaxv /*
574a8560c32Smaxv * The crypto header is added after the IEEE802.11 header. Prepend
575a8560c32Smaxv * the size of the crypto header, and move the IEEE802.11 header back
576a8560c32Smaxv * to the beginning of the mbuf. Ensure everything is contiguous.
577a8560c32Smaxv */
578a8560c32Smaxv hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
579a8560c32Smaxv M_PREPEND(m, cip->ic_header, M_NOWAIT);
580a8560c32Smaxv if (m && m->m_len < hdrlen + cip->ic_header) {
581a8560c32Smaxv m = m_pullup(m, hdrlen + cip->ic_header);
582a8560c32Smaxv }
583a8560c32Smaxv if (m == NULL) {
584a8560c32Smaxv return NULL;
585a8560c32Smaxv }
586a8560c32Smaxv hdr = mtod(m, u_int8_t *);
587a8560c32Smaxv memmove(hdr, hdr + cip->ic_header, hdrlen);
588a8560c32Smaxv
58987515e34Sskrll return (cip->ic_encap(k, m, keyid<<6) ? k : NULL);
59040e261aaSdyoung }
59140e261aaSdyoung
5929af01d3aSmaxv #define IEEE80211_WEP_HDRLEN (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN)
5939af01d3aSmaxv #define IEEE80211_WEP_MINLEN \
5949af01d3aSmaxv (sizeof(struct ieee80211_frame) + \
5959af01d3aSmaxv IEEE80211_WEP_HDRLEN + IEEE80211_WEP_CRCLEN)
5969af01d3aSmaxv
59740e261aaSdyoung /*
59890634029Sdyoung * Validate and strip privacy headers (and trailer) for a
59990634029Sdyoung * received frame that has the WEP/Privacy bit set.
60040e261aaSdyoung */
60190634029Sdyoung struct ieee80211_key *
ieee80211_crypto_decap(struct ieee80211com * ic,struct ieee80211_node * ni,struct mbuf ** mp,int hdrlen)60290634029Sdyoung ieee80211_crypto_decap(struct ieee80211com *ic,
603fa370b63Smaxv struct ieee80211_node *ni, struct mbuf **mp, int hdrlen)
60440e261aaSdyoung {
6059af01d3aSmaxv const struct ieee80211_cipher *cip;
60690634029Sdyoung struct ieee80211_key *k;
60790634029Sdyoung struct ieee80211_frame *wh;
608fa370b63Smaxv struct mbuf *m = *mp;
60990634029Sdyoung u_int8_t keyid;
61040e261aaSdyoung
611671dd6e4Smaxv KASSERT((m->m_flags & M_PKTHDR) != 0);
612671dd6e4Smaxv
613671dd6e4Smaxv /*
614671dd6e4Smaxv * This minimum size data frame could be bigger. It is re-checked
615671dd6e4Smaxv * below.
616671dd6e4Smaxv */
61790634029Sdyoung if (m->m_pkthdr.len < IEEE80211_WEP_MINLEN) {
61890634029Sdyoung IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
61990634029Sdyoung "%s: WEP data frame too short, len %u\n",
62090634029Sdyoung __func__, m->m_pkthdr.len);
6219af01d3aSmaxv ic->ic_stats.is_rx_tooshort++;
62290634029Sdyoung return NULL;
62340e261aaSdyoung }
62440e261aaSdyoung
62540e261aaSdyoung /*
62690634029Sdyoung * Locate the key. If unicast and there is no unicast
62790634029Sdyoung * key then we fall back to the key id in the header.
62890634029Sdyoung * This assumes unicast keys are only configured when
62990634029Sdyoung * the key id in the header is meaningless (typically 0).
63040e261aaSdyoung */
63190634029Sdyoung wh = mtod(m, struct ieee80211_frame *);
632d339db42Sdyoung m_copydata(m, hdrlen + IEEE80211_WEP_IVLEN, sizeof(keyid), &keyid);
63390634029Sdyoung if (IEEE80211_IS_MULTICAST(wh->i_addr1) ||
6349af01d3aSmaxv ni->ni_ucastkey.wk_cipher == &ieee80211_cipher_none) {
63590634029Sdyoung k = &ic->ic_nw_keys[keyid >> 6];
6369af01d3aSmaxv } else {
63790634029Sdyoung k = &ni->ni_ucastkey;
6389af01d3aSmaxv }
63940e261aaSdyoung
64090634029Sdyoung /*
64190634029Sdyoung * Insure crypto header is contiguous for all decap work.
64290634029Sdyoung */
64390634029Sdyoung cip = k->wk_cipher;
6449af01d3aSmaxv if (m->m_len < hdrlen + cip->ic_header) {
6459af01d3aSmaxv m = m_pullup(m, hdrlen + cip->ic_header);
6469af01d3aSmaxv *mp = m;
6479af01d3aSmaxv }
6489af01d3aSmaxv
6499af01d3aSmaxv if (m == NULL) {
650d1b4a5beSmaxv ic->ic_stats.is_rx_tooshort++;
651e16ddd31Sdyoung return NULL;
65290634029Sdyoung }
65340e261aaSdyoung
654671dd6e4Smaxv /*
655671dd6e4Smaxv * Ensure there is a header+trailer included.
656671dd6e4Smaxv */
657671dd6e4Smaxv if (m->m_pkthdr.len < hdrlen + cip->ic_header + cip->ic_trailer) {
658671dd6e4Smaxv IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
659671dd6e4Smaxv "%s: WEP data frame too short, len %u\n",
660671dd6e4Smaxv __func__, m->m_pkthdr.len);
661671dd6e4Smaxv ic->ic_stats.is_rx_tooshort++;
662671dd6e4Smaxv return NULL;
663671dd6e4Smaxv }
664671dd6e4Smaxv
665d2ba8780Sdyoung return (cip->ic_decap(k, m, hdrlen) ? k : NULL);
66640e261aaSdyoung }
667