13147Sxc151355 /* 2*4126Szf162725 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 33147Sxc151355 * Use is subject to license terms. 43147Sxc151355 */ 53147Sxc151355 63147Sxc151355 /* 73147Sxc151355 * Copyright (c) 2001 Atsushi Onoe 83147Sxc151355 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 93147Sxc151355 * All rights reserved. 103147Sxc151355 * 113147Sxc151355 * Redistribution and use in source and binary forms, with or without 123147Sxc151355 * modification, are permitted provided that the following conditions 133147Sxc151355 * are met: 143147Sxc151355 * 1. Redistributions of source code must retain the above copyright 153147Sxc151355 * notice, this list of conditions and the following disclaimer. 163147Sxc151355 * 2. Redistributions in binary form must reproduce the above copyright 173147Sxc151355 * notice, this list of conditions and the following disclaimer in the 183147Sxc151355 * documentation and/or other materials provided with the distribution. 193147Sxc151355 * 3. The name of the author may not be used to endorse or promote products 203147Sxc151355 * derived from this software without specific prior written permission. 213147Sxc151355 * 223147Sxc151355 * Alternatively, this software may be distributed under the terms of the 233147Sxc151355 * GNU General Public License ("GPL") version 2 as published by the Free 243147Sxc151355 * Software Foundation. 253147Sxc151355 * 263147Sxc151355 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 273147Sxc151355 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 283147Sxc151355 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 293147Sxc151355 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 303147Sxc151355 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 313147Sxc151355 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 323147Sxc151355 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 333147Sxc151355 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 343147Sxc151355 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 353147Sxc151355 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 363147Sxc151355 */ 373147Sxc151355 383147Sxc151355 #pragma ident "%Z%%M% %I% %E% SMI" 393147Sxc151355 403147Sxc151355 /* 413147Sxc151355 * IEEE 802.11 generic crypto support 423147Sxc151355 */ 433147Sxc151355 #include <sys/types.h> 443147Sxc151355 #include <sys/note.h> 453147Sxc151355 #include "net80211_impl.h" 463147Sxc151355 473147Sxc151355 extern const struct ieee80211_cipher wep; 48*4126Szf162725 extern const struct ieee80211_cipher tkip; 49*4126Szf162725 extern const struct ieee80211_cipher ccmp; 503147Sxc151355 513147Sxc151355 /* 523147Sxc151355 * Table of registered cipher modules. 533147Sxc151355 */ 543147Sxc151355 static const struct ieee80211_cipher *ciphers[IEEE80211_CIPHER_MAX]; 553147Sxc151355 static const char *cipher_modnames[] = { 563147Sxc151355 "wlan_wep", /* IEEE80211_CIPHER_WEP */ 573147Sxc151355 "wlan_tkip", /* IEEE80211_CIPHER_TKIP */ 583147Sxc151355 "wlan_aes_ocb", /* IEEE80211_CIPHER_AES_OCB */ 593147Sxc151355 "wlan_ccmp", /* IEEE80211_CIPHER_AES_CCM */ 603147Sxc151355 "wlan_ckip", /* IEEE80211_CIPHER_CKIP */ 613147Sxc151355 }; 623147Sxc151355 633147Sxc151355 /* 643147Sxc151355 * Default "null" key management routines. 653147Sxc151355 */ 663147Sxc151355 /* ARGSUSED */ 673147Sxc151355 static int 683147Sxc151355 nulldev_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k, 693147Sxc151355 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 703147Sxc151355 { 713147Sxc151355 *keyix = 0; /* use key index 0 for ucast key */ 723147Sxc151355 *rxkeyix = IEEE80211_KEYIX_NONE; 733147Sxc151355 return (1); 743147Sxc151355 } 753147Sxc151355 763147Sxc151355 /* ARGSUSED */ 773147Sxc151355 static int 783147Sxc151355 nulldev_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k) 793147Sxc151355 { 803147Sxc151355 return (1); 813147Sxc151355 } 823147Sxc151355 833147Sxc151355 /* ARGSUSED */ 843147Sxc151355 static int 853147Sxc151355 nulldev_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 863147Sxc151355 const uint8_t *mac) 873147Sxc151355 { 883147Sxc151355 return (1); 893147Sxc151355 } 903147Sxc151355 913147Sxc151355 /* ARGSUSED */ 923147Sxc151355 static void 933147Sxc151355 nulldev_key_update(ieee80211com_t *ic) 943147Sxc151355 { 953147Sxc151355 /* noop */ 963147Sxc151355 } 973147Sxc151355 983147Sxc151355 /* 993147Sxc151355 * Reset key state to an unused state. The crypto 1003147Sxc151355 * key allocation mechanism insures other state (e.g. 1013147Sxc151355 * key data) is properly setup before a key is used. 1023147Sxc151355 */ 1033147Sxc151355 void 1043147Sxc151355 ieee80211_crypto_resetkey(ieee80211com_t *ic, 1053147Sxc151355 struct ieee80211_key *k, ieee80211_keyix ix) 1063147Sxc151355 { 1073147Sxc151355 k->wk_cipher = &ieee80211_cipher_none; 1083147Sxc151355 k->wk_private = k->wk_cipher->ic_attach(ic, k); 1093147Sxc151355 k->wk_keyix = ix; 1103147Sxc151355 k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 1113147Sxc151355 } 1123147Sxc151355 1133147Sxc151355 /* 1143147Sxc151355 * Establish a relationship between the specified key and cipher 1153147Sxc151355 * and, if necessary, allocate a hardware index from the driver. 1163147Sxc151355 * Note that when a fixed key index is required it must be specified 1173147Sxc151355 * and we blindly assign it w/o consulting the driver. 1183147Sxc151355 * 1193147Sxc151355 * This must be the first call applied to a key; all the other key 1203147Sxc151355 * routines assume wk_cipher is setup. 1213147Sxc151355 * 1223147Sxc151355 * Locking must be handled by the caller using: 1233147Sxc151355 * ieee80211_key_update_begin(ic); 1243147Sxc151355 * ieee80211_key_update_end(ic); 1253147Sxc151355 */ 1263147Sxc151355 int 1273147Sxc151355 ieee80211_crypto_newkey(ieee80211com_t *ic, int cipher, int flags, 1283147Sxc151355 struct ieee80211_key *key) 1293147Sxc151355 { 1303147Sxc151355 const struct ieee80211_cipher *cip; 1313147Sxc151355 ieee80211_keyix keyix, rxkeyix; 1323147Sxc151355 void *keyctx; 1333147Sxc151355 uint16_t oflags; 1343147Sxc151355 1353147Sxc151355 /* 1363147Sxc151355 * Validate cipher and set reference to cipher routines. 1373147Sxc151355 */ 1383147Sxc151355 if (cipher >= IEEE80211_CIPHER_MAX) { 1393147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 1403147Sxc151355 "invalid cipher %u\n", cipher); 1413147Sxc151355 return (0); 1423147Sxc151355 } 1433147Sxc151355 cip = ciphers[cipher]; 1443147Sxc151355 /* already load all the ciphers, cip can't be NULL */ 1453147Sxc151355 if (cip == NULL) { 1463147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 1473147Sxc151355 "unable to load cipher %u, module %s\n", 1483147Sxc151355 cipher, cipher < IEEE80211_N(cipher_modnames) ? 1493147Sxc151355 cipher_modnames[cipher] : "<unknown>"); 1503147Sxc151355 return (0); 1513147Sxc151355 } 1523147Sxc151355 1533147Sxc151355 oflags = key->wk_flags; 1543147Sxc151355 flags &= IEEE80211_KEY_COMMON; 1553147Sxc151355 /* 1563147Sxc151355 * If the hardware does not support the cipher then 1573147Sxc151355 * fallback to a host-based implementation. 1583147Sxc151355 */ 1593147Sxc151355 if ((ic->ic_caps & (1<<cipher)) == 0) { 1603147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 1613147Sxc151355 "no h/w support for cipher %s, falling back to s/w\n", 1623147Sxc151355 cip->ic_name); 1633147Sxc151355 flags |= IEEE80211_KEY_SWCRYPT; 1643147Sxc151355 } 165*4126Szf162725 /* 166*4126Szf162725 * Hardware TKIP with software MIC is an important 167*4126Szf162725 * combination; we handle it by flagging each key, 168*4126Szf162725 * the cipher modules honor it. 169*4126Szf162725 */ 170*4126Szf162725 if (cipher == IEEE80211_CIPHER_TKIP && 171*4126Szf162725 (ic->ic_caps & IEEE80211_C_TKIPMIC) == 0) { 172*4126Szf162725 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 173*4126Szf162725 "no h/w support for TKIP MIC, falling back to s/w\n"); 174*4126Szf162725 flags |= IEEE80211_KEY_SWMIC; 175*4126Szf162725 } 1763147Sxc151355 1773147Sxc151355 /* 1783147Sxc151355 * Bind cipher to key instance. Note we do this 1793147Sxc151355 * after checking the device capabilities so the 1803147Sxc151355 * cipher module can optimize space usage based on 1813147Sxc151355 * whether or not it needs to do the cipher work. 1823147Sxc151355 */ 1833147Sxc151355 if (key->wk_cipher != cip || key->wk_flags != flags) { 1843147Sxc151355 again: 1853147Sxc151355 /* 1863147Sxc151355 * Fillin the flags so cipher modules can see s/w 1873147Sxc151355 * crypto requirements and potentially allocate 1883147Sxc151355 * different state and/or attach different method 1893147Sxc151355 * pointers. 1903147Sxc151355 */ 1913147Sxc151355 key->wk_flags = (uint16_t)flags; 1923147Sxc151355 keyctx = cip->ic_attach(ic, key); 1933147Sxc151355 if (keyctx == NULL) { 1943147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 1953147Sxc151355 "unable to attach cipher %s\n", cip->ic_name); 1963147Sxc151355 key->wk_flags = oflags; /* restore old flags */ 1973147Sxc151355 return (0); 1983147Sxc151355 } 1993147Sxc151355 CIPHER_DETACH(key); /* Detach old cipher */ 2003147Sxc151355 key->wk_cipher = cip; 2013147Sxc151355 key->wk_private = keyctx; 2023147Sxc151355 } 2033147Sxc151355 /* 2043147Sxc151355 * Commit to requested usage so driver can see the flags. 2053147Sxc151355 */ 2063147Sxc151355 key->wk_flags = (uint16_t)flags; 2073147Sxc151355 2083147Sxc151355 /* 2093147Sxc151355 * Ask the driver for a key index if we don't have one. 2103147Sxc151355 * Note that entries in the global key table always have 2113147Sxc151355 * an index; this means it's safe to call this routine 2123147Sxc151355 * for these entries just to setup the reference to the 2133147Sxc151355 * cipher template. Note also that when using software 2143147Sxc151355 * crypto we also call the driver to give us a key index. 2153147Sxc151355 */ 2163147Sxc151355 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 2173147Sxc151355 if (!DEV_KEY_ALLOC(ic, key, &keyix, &rxkeyix)) { 2183147Sxc151355 /* 2193147Sxc151355 * Driver has no room; fallback to doing crypto 2203147Sxc151355 * in the host. We change the flags and start the 2213147Sxc151355 * procedure over. If we get back here then there's 2223147Sxc151355 * no hope and we bail. Note that this can leave 2233147Sxc151355 * the key in a inconsistent state if the caller 2243147Sxc151355 * continues to use it. 2253147Sxc151355 */ 2263147Sxc151355 if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { 2273147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 2283147Sxc151355 "crypto_setkey: " 2293147Sxc151355 "no h/w resources for cipher %s, " 2303147Sxc151355 "falling back to s/w\n", cip->ic_name); 2313147Sxc151355 oflags = key->wk_flags; 2323147Sxc151355 flags |= IEEE80211_KEY_SWCRYPT; 2333147Sxc151355 if (cipher == IEEE80211_CIPHER_TKIP) 2343147Sxc151355 flags |= IEEE80211_KEY_SWMIC; 2353147Sxc151355 goto again; 2363147Sxc151355 } 2373147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 2383147Sxc151355 "unable to setup cipher %s\n", cip->ic_name); 2393147Sxc151355 return (0); 2403147Sxc151355 } 2413147Sxc151355 key->wk_keyix = keyix; 2423147Sxc151355 key->wk_rxkeyix = rxkeyix; 2433147Sxc151355 } 2443147Sxc151355 return (1); 2453147Sxc151355 } 2463147Sxc151355 2473147Sxc151355 /* 2483147Sxc151355 * Remove the key (no locking, for internal use). 2493147Sxc151355 */ 2503147Sxc151355 static int 2513147Sxc151355 ieee80211_crypto_delkey_locked(ieee80211com_t *ic, struct ieee80211_key *key) 2523147Sxc151355 { 2533147Sxc151355 uint16_t keyix; 2543147Sxc151355 2553147Sxc151355 ASSERT(key->wk_cipher != NULL); 2563147Sxc151355 2573147Sxc151355 keyix = key->wk_keyix; 2583147Sxc151355 if (keyix != IEEE80211_KEYIX_NONE) { 2593147Sxc151355 /* 2603147Sxc151355 * Remove hardware entry. 2613147Sxc151355 */ 2623147Sxc151355 if (!DEV_KEY_DELETE(ic, key)) { 2633147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 2643147Sxc151355 "ieee80211_crypto_delkey_locked: ", 2653147Sxc151355 "driverdeletes key %u failed\n", keyix); 2663147Sxc151355 } 2673147Sxc151355 } 2683147Sxc151355 CIPHER_DETACH(key); 2693147Sxc151355 bzero(key, sizeof (struct ieee80211_key)); 2703147Sxc151355 /* NB: cannot depend on key index to decide this */ 2713147Sxc151355 ieee80211_crypto_resetkey(ic, key, IEEE80211_KEYIX_NONE); 2723147Sxc151355 return (1); 2733147Sxc151355 } 2743147Sxc151355 2753147Sxc151355 /* 2763147Sxc151355 * Remove the specified key. 2773147Sxc151355 */ 2783147Sxc151355 int 2793147Sxc151355 ieee80211_crypto_delkey(ieee80211com_t *ic, struct ieee80211_key *key) 2803147Sxc151355 { 2813147Sxc151355 int status; 2823147Sxc151355 2833147Sxc151355 KEY_UPDATE_BEGIN(ic); 2843147Sxc151355 status = ieee80211_crypto_delkey_locked(ic, key); 2853147Sxc151355 KEY_UPDATE_END(ic); 2863147Sxc151355 return (status); 2873147Sxc151355 } 2883147Sxc151355 2893147Sxc151355 /* 2903147Sxc151355 * Clear the global key table. 2913147Sxc151355 */ 2923147Sxc151355 static void 2933147Sxc151355 ieee80211_crypto_delglobalkeys(ieee80211com_t *ic) 2943147Sxc151355 { 2953147Sxc151355 int i; 2963147Sxc151355 2973147Sxc151355 KEY_UPDATE_BEGIN(ic); 2983147Sxc151355 for (i = 0; i < IEEE80211_WEP_NKID; i++) 2993147Sxc151355 (void) ieee80211_crypto_delkey_locked(ic, &ic->ic_nw_keys[i]); 3003147Sxc151355 KEY_UPDATE_END(ic); 3013147Sxc151355 } 3023147Sxc151355 3033147Sxc151355 /* 3043147Sxc151355 * Set the contents of the specified key. 3053147Sxc151355 * 3063147Sxc151355 * Locking must be handled by the caller using: 3073147Sxc151355 * ieee80211_key_update_begin(ic); 3083147Sxc151355 * ieee80211_key_update_end(ic); 3093147Sxc151355 */ 3103147Sxc151355 int 3113147Sxc151355 ieee80211_crypto_setkey(ieee80211com_t *ic, struct ieee80211_key *key, 3123147Sxc151355 const uint8_t *macaddr) 3133147Sxc151355 { 3143147Sxc151355 const struct ieee80211_cipher *cip = key->wk_cipher; 3153147Sxc151355 3163147Sxc151355 ASSERT(cip != NULL); 3173147Sxc151355 3183147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 3193147Sxc151355 "%s keyix %u flags 0x%x mac %s len %u\n", 3203147Sxc151355 cip->ic_name, key->wk_keyix, key->wk_flags, 3213147Sxc151355 ieee80211_macaddr_sprintf(macaddr), key->wk_keylen); 3223147Sxc151355 3233147Sxc151355 /* 3243147Sxc151355 * Give cipher a chance to validate key contents. 3253147Sxc151355 * should happen before modifying state. 3263147Sxc151355 */ 3273147Sxc151355 if (cip->ic_setkey(key) == 0) { 3283147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 3293147Sxc151355 "cipher %s rejected key index %u len %u flags 0x%x\n", 3303147Sxc151355 cip->ic_name, key->wk_keyix, key->wk_keylen, 3313147Sxc151355 key->wk_flags); 3323147Sxc151355 return (0); 3333147Sxc151355 } 3343147Sxc151355 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 3353147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 3363147Sxc151355 "no key index; should not happen!\n"); 3373147Sxc151355 return (0); 3383147Sxc151355 } 3393147Sxc151355 return (DEV_KEY_SET(ic, key, macaddr)); 3403147Sxc151355 } 3413147Sxc151355 3423147Sxc151355 /* 3433147Sxc151355 * Return the transmit key to use in sending a frame. 3443147Sxc151355 */ 3453147Sxc151355 struct ieee80211_key * 3463147Sxc151355 ieee80211_crypto_getkey(ieee80211com_t *ic) 3473147Sxc151355 { 3483147Sxc151355 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || 3493147Sxc151355 KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) 3503147Sxc151355 return (NULL); 3513147Sxc151355 return (&ic->ic_nw_keys[ic->ic_def_txkey]); 3523147Sxc151355 } 3533147Sxc151355 3543147Sxc151355 uint8_t 3553147Sxc151355 ieee80211_crypto_getciphertype(ieee80211com_t *ic) 3563147Sxc151355 { 3573147Sxc151355 struct ieee80211_key *key; 3583147Sxc151355 uint32_t cipher; 3593147Sxc151355 static const uint8_t ciphermap[] = { 3603147Sxc151355 WIFI_SEC_WEP, /* IEEE80211_CIPHER_WEP */ 361*4126Szf162725 WIFI_SEC_WPA, /* IEEE80211_CIPHER_TKIP */ 3623147Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_AES_OCB */ 363*4126Szf162725 WIFI_SEC_WPA, /* IEEE80211_CIPHER_AES_CCM */ 3643147Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_CKIP */ 3653147Sxc151355 WIFI_SEC_NONE, /* IEEE80211_CIPHER_NONE */ 3663147Sxc151355 }; 3673147Sxc151355 3683147Sxc151355 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) 3693147Sxc151355 return (WIFI_SEC_NONE); 3703147Sxc151355 3713147Sxc151355 key = ieee80211_crypto_getkey(ic); 3723147Sxc151355 if (key == NULL) 3733147Sxc151355 return (WIFI_SEC_NONE); 3743147Sxc151355 3753147Sxc151355 cipher = key->wk_cipher->ic_cipher; 3763147Sxc151355 ASSERT(cipher < IEEE80211_N(ciphermap)); 3773147Sxc151355 return (ciphermap[cipher]); 3783147Sxc151355 } 3793147Sxc151355 3803147Sxc151355 /* 3813147Sxc151355 * Add privacy headers appropriate for the specified key. 3823147Sxc151355 */ 3833147Sxc151355 struct ieee80211_key * 3843147Sxc151355 ieee80211_crypto_encap(ieee80211com_t *ic, mblk_t *mp) 3853147Sxc151355 { 3863147Sxc151355 struct ieee80211_key *k; 3873147Sxc151355 const struct ieee80211_cipher *cip; 3883147Sxc151355 uint8_t keyix; 3893147Sxc151355 3903147Sxc151355 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) { 3913147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 3923147Sxc151355 "ieee80211_crypto_encap: %s", 3933147Sxc151355 " No default xmit key for frame\n"); 3943147Sxc151355 return (NULL); 3953147Sxc151355 } 3963147Sxc151355 keyix = ic->ic_def_txkey; 3973147Sxc151355 k = &ic->ic_nw_keys[ic->ic_def_txkey]; 3983147Sxc151355 cip = k->wk_cipher; 3993147Sxc151355 return (cip->ic_encap(k, mp, keyix<<6) ? k : NULL); 4003147Sxc151355 } 4013147Sxc151355 4023147Sxc151355 /* 4033147Sxc151355 * Validate and strip privacy headers (and trailer) for a 4043147Sxc151355 * received frame that has the WEP/Privacy bit set. 4053147Sxc151355 */ 4063147Sxc151355 struct ieee80211_key * 4073147Sxc151355 ieee80211_crypto_decap(ieee80211com_t *ic, mblk_t *mp, int hdrlen) 4083147Sxc151355 { 4093147Sxc151355 struct ieee80211_key *k; 4103147Sxc151355 const struct ieee80211_cipher *cip; 4113147Sxc151355 uint8_t *ivp; 4123147Sxc151355 uint8_t keyid; 4133147Sxc151355 4143147Sxc151355 /* NB: this minimum size data frame could be bigger */ 4153147Sxc151355 if ((mp->b_wptr - mp->b_rptr) < IEEE80211_WEP_MINLEN) { 4163147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_decap:" 4173147Sxc151355 " WEP data frame too short, len %u\n", 4183147Sxc151355 mp->b_wptr - mp->b_rptr); 4193147Sxc151355 return (NULL); 4203147Sxc151355 } 4213147Sxc151355 /* 4223147Sxc151355 * Locate the key. If unicast and there is no unicast 4233147Sxc151355 * key then we fall back to the key id in the header. 4243147Sxc151355 * This assumes unicast keys are only configured when 4253147Sxc151355 * the key id in the header is meaningless (typically 0). 4263147Sxc151355 */ 4273147Sxc151355 ivp = mp->b_rptr + hdrlen; 4283147Sxc151355 keyid = ivp[IEEE80211_WEP_IVLEN]; 4293147Sxc151355 k = &ic->ic_nw_keys[keyid >> 6]; 4303147Sxc151355 4313147Sxc151355 /* check to avoid panic when wep is on but key is not set */ 4323147Sxc151355 if (k->wk_cipher == &ieee80211_cipher_none || 4333147Sxc151355 k->wk_cipher == NULL) 4343147Sxc151355 return (NULL); 4353147Sxc151355 4363147Sxc151355 cip = k->wk_cipher; 4373147Sxc151355 return ((cip->ic_decap)(k, mp, hdrlen) ? k : NULL); 4383147Sxc151355 } 4393147Sxc151355 4403147Sxc151355 4413147Sxc151355 /* 4423147Sxc151355 * Setup crypto support. 4433147Sxc151355 */ 4443147Sxc151355 void 4453147Sxc151355 ieee80211_crypto_attach(ieee80211com_t *ic) 4463147Sxc151355 { 4473147Sxc151355 struct ieee80211_crypto_state *cs = &ic->ic_crypto; 4483147Sxc151355 int i; 4493147Sxc151355 4503147Sxc151355 /* NB: we assume everything is pre-zero'd */ 4513147Sxc151355 cs->cs_def_txkey = IEEE80211_KEYIX_NONE; 4523147Sxc151355 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 4533147Sxc151355 ieee80211_crypto_resetkey(ic, &cs->cs_nw_keys[i], 4543147Sxc151355 IEEE80211_KEYIX_NONE); 4553147Sxc151355 } 4563147Sxc151355 4573147Sxc151355 /* 4583147Sxc151355 * Initialize the driver key support routines to noop entries. 4593147Sxc151355 * This is useful especially for the cipher test modules. 4603147Sxc151355 */ 4613147Sxc151355 cs->cs_key_alloc = nulldev_key_alloc; 4623147Sxc151355 cs->cs_key_set = nulldev_key_set; 4633147Sxc151355 cs->cs_key_delete = nulldev_key_delete; 4643147Sxc151355 cs->cs_key_update_begin = nulldev_key_update; 4653147Sxc151355 cs->cs_key_update_end = nulldev_key_update; 4663147Sxc151355 4673147Sxc151355 ieee80211_crypto_register(&wep); 468*4126Szf162725 ieee80211_crypto_register(&tkip); 469*4126Szf162725 ieee80211_crypto_register(&ccmp); 4703147Sxc151355 } 4713147Sxc151355 4723147Sxc151355 /* 4733147Sxc151355 * Teardown crypto support. 4743147Sxc151355 */ 4753147Sxc151355 void 4763147Sxc151355 ieee80211_crypto_detach(ieee80211com_t *ic) 4773147Sxc151355 { 4783147Sxc151355 ieee80211_crypto_delglobalkeys(ic); 4793147Sxc151355 4803147Sxc151355 ieee80211_crypto_unregister(&wep); 481*4126Szf162725 ieee80211_crypto_unregister(&tkip); 482*4126Szf162725 ieee80211_crypto_unregister(&ccmp); 4833147Sxc151355 } 4843147Sxc151355 4853147Sxc151355 /* 4863147Sxc151355 * Register a crypto cipher module. 4873147Sxc151355 */ 4883147Sxc151355 void 4893147Sxc151355 ieee80211_crypto_register(const struct ieee80211_cipher *cip) 4903147Sxc151355 { 4913147Sxc151355 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 4923147Sxc151355 ieee80211_err("ieee80211_crypto_register: " 4933147Sxc151355 "cipher %s has an invalid cipher index %u\n", 4943147Sxc151355 cip->ic_name, cip->ic_cipher); 4953147Sxc151355 return; 4963147Sxc151355 } 4973147Sxc151355 if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) { 4983147Sxc151355 ieee80211_err("ieee80211_crypto_register: " 4993147Sxc151355 "cipher %s registered with a different template\n", 5003147Sxc151355 cip->ic_name); 5013147Sxc151355 return; 5023147Sxc151355 } 5033147Sxc151355 ciphers[cip->ic_cipher] = cip; 5043147Sxc151355 } 5053147Sxc151355 5063147Sxc151355 /* 5073147Sxc151355 * Unregister a crypto cipher module. 5083147Sxc151355 */ 5093147Sxc151355 void 5103147Sxc151355 ieee80211_crypto_unregister(const struct ieee80211_cipher *cip) 5113147Sxc151355 { 5123147Sxc151355 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 5133147Sxc151355 ieee80211_err("ieee80211_crypto_unregister: " 5143147Sxc151355 "cipher %s has an invalid cipher index %u\n", 5153147Sxc151355 cip->ic_name, cip->ic_cipher); 5163147Sxc151355 return; 5173147Sxc151355 } 5183147Sxc151355 if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) { 5193147Sxc151355 ieee80211_err("ieee80211_crypto_unregister: " 5203147Sxc151355 "cipher %s registered with a different template\n", 5213147Sxc151355 cip->ic_name); 5223147Sxc151355 return; 5233147Sxc151355 } 5243147Sxc151355 /* NB: don't complain about not being registered */ 5253147Sxc151355 ciphers[cip->ic_cipher] = NULL; 5263147Sxc151355 } 527