13147Sxc151355 /* 24126Szf162725 * 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> 45*5296Szf162725 #include <sys/crypto/common.h> 46*5296Szf162725 #include <sys/crypto/api.h> 473147Sxc151355 #include "net80211_impl.h" 483147Sxc151355 493147Sxc151355 extern const struct ieee80211_cipher wep; 504126Szf162725 extern const struct ieee80211_cipher tkip; 514126Szf162725 extern const struct ieee80211_cipher ccmp; 523147Sxc151355 533147Sxc151355 /* 543147Sxc151355 * Table of registered cipher modules. 553147Sxc151355 */ 563147Sxc151355 static const char *cipher_modnames[] = { 573147Sxc151355 "wlan_wep", /* IEEE80211_CIPHER_WEP */ 583147Sxc151355 "wlan_tkip", /* IEEE80211_CIPHER_TKIP */ 593147Sxc151355 "wlan_aes_ocb", /* IEEE80211_CIPHER_AES_OCB */ 603147Sxc151355 "wlan_ccmp", /* IEEE80211_CIPHER_AES_CCM */ 613147Sxc151355 "wlan_ckip", /* IEEE80211_CIPHER_CKIP */ 623147Sxc151355 }; 633147Sxc151355 643147Sxc151355 /* 653147Sxc151355 * Default "null" key management routines. 663147Sxc151355 */ 673147Sxc151355 /* ARGSUSED */ 683147Sxc151355 static int 693147Sxc151355 nulldev_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k, 703147Sxc151355 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 713147Sxc151355 { 723147Sxc151355 *keyix = 0; /* use key index 0 for ucast key */ 733147Sxc151355 *rxkeyix = IEEE80211_KEYIX_NONE; 743147Sxc151355 return (1); 753147Sxc151355 } 763147Sxc151355 773147Sxc151355 /* ARGSUSED */ 783147Sxc151355 static int 793147Sxc151355 nulldev_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k) 803147Sxc151355 { 813147Sxc151355 return (1); 823147Sxc151355 } 833147Sxc151355 843147Sxc151355 /* ARGSUSED */ 853147Sxc151355 static int 863147Sxc151355 nulldev_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 873147Sxc151355 const uint8_t *mac) 883147Sxc151355 { 893147Sxc151355 return (1); 903147Sxc151355 } 913147Sxc151355 923147Sxc151355 /* ARGSUSED */ 933147Sxc151355 static void 943147Sxc151355 nulldev_key_update(ieee80211com_t *ic) 953147Sxc151355 { 963147Sxc151355 /* noop */ 973147Sxc151355 } 983147Sxc151355 993147Sxc151355 /* 1003147Sxc151355 * Reset key state to an unused state. The crypto 1013147Sxc151355 * key allocation mechanism insures other state (e.g. 1023147Sxc151355 * key data) is properly setup before a key is used. 1033147Sxc151355 */ 1043147Sxc151355 void 1053147Sxc151355 ieee80211_crypto_resetkey(ieee80211com_t *ic, 1064499Shx147065 struct ieee80211_key *k, ieee80211_keyix ix) 1073147Sxc151355 { 1083147Sxc151355 k->wk_cipher = &ieee80211_cipher_none; 1093147Sxc151355 k->wk_private = k->wk_cipher->ic_attach(ic, k); 1103147Sxc151355 k->wk_keyix = ix; 1113147Sxc151355 k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 1123147Sxc151355 } 1133147Sxc151355 1143147Sxc151355 /* 1153147Sxc151355 * Establish a relationship between the specified key and cipher 1163147Sxc151355 * and, if necessary, allocate a hardware index from the driver. 1173147Sxc151355 * Note that when a fixed key index is required it must be specified 1183147Sxc151355 * and we blindly assign it w/o consulting the driver. 1193147Sxc151355 * 1203147Sxc151355 * This must be the first call applied to a key; all the other key 1213147Sxc151355 * routines assume wk_cipher is setup. 1223147Sxc151355 * 1233147Sxc151355 * Locking must be handled by the caller using: 1243147Sxc151355 * ieee80211_key_update_begin(ic); 1253147Sxc151355 * ieee80211_key_update_end(ic); 1263147Sxc151355 */ 1273147Sxc151355 int 1283147Sxc151355 ieee80211_crypto_newkey(ieee80211com_t *ic, int cipher, int flags, 1293147Sxc151355 struct ieee80211_key *key) 1303147Sxc151355 { 1313147Sxc151355 const struct ieee80211_cipher *cip; 1323147Sxc151355 ieee80211_keyix keyix, rxkeyix; 1333147Sxc151355 void *keyctx; 1343147Sxc151355 uint16_t oflags; 1353147Sxc151355 1363147Sxc151355 /* 1373147Sxc151355 * Validate cipher and set reference to cipher routines. 1383147Sxc151355 */ 1393147Sxc151355 if (cipher >= IEEE80211_CIPHER_MAX) { 1403147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 1414499Shx147065 "invalid cipher %u\n", cipher); 1423147Sxc151355 return (0); 1433147Sxc151355 } 1444499Shx147065 cip = ic->ic_ciphers[cipher]; 1453147Sxc151355 /* already load all the ciphers, cip can't be NULL */ 1463147Sxc151355 if (cip == NULL) { 1473147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 1484499Shx147065 "unable to load cipher %u, module %s\n", 1494499Shx147065 cipher, cipher < IEEE80211_N(cipher_modnames) ? 1504499Shx147065 cipher_modnames[cipher] : "<unknown>"); 1513147Sxc151355 return (0); 1523147Sxc151355 } 1533147Sxc151355 1543147Sxc151355 oflags = key->wk_flags; 1553147Sxc151355 flags &= IEEE80211_KEY_COMMON; 1563147Sxc151355 /* 1573147Sxc151355 * If the hardware does not support the cipher then 1583147Sxc151355 * fallback to a host-based implementation. 1593147Sxc151355 */ 1603147Sxc151355 if ((ic->ic_caps & (1<<cipher)) == 0) { 1613147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 1624499Shx147065 "no h/w support for cipher %s, falling back to s/w\n", 1634499Shx147065 cip->ic_name); 1643147Sxc151355 flags |= IEEE80211_KEY_SWCRYPT; 1653147Sxc151355 } 1664126Szf162725 /* 1674126Szf162725 * Hardware TKIP with software MIC is an important 1684126Szf162725 * combination; we handle it by flagging each key, 1694126Szf162725 * the cipher modules honor it. 1704126Szf162725 */ 1714126Szf162725 if (cipher == IEEE80211_CIPHER_TKIP && 1724126Szf162725 (ic->ic_caps & IEEE80211_C_TKIPMIC) == 0) { 1734126Szf162725 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 1744126Szf162725 "no h/w support for TKIP MIC, falling back to s/w\n"); 1754126Szf162725 flags |= IEEE80211_KEY_SWMIC; 1764126Szf162725 } 1773147Sxc151355 1783147Sxc151355 /* 1793147Sxc151355 * Bind cipher to key instance. Note we do this 1803147Sxc151355 * after checking the device capabilities so the 1813147Sxc151355 * cipher module can optimize space usage based on 1823147Sxc151355 * whether or not it needs to do the cipher work. 1833147Sxc151355 */ 1843147Sxc151355 if (key->wk_cipher != cip || key->wk_flags != flags) { 1853147Sxc151355 again: 1863147Sxc151355 /* 1873147Sxc151355 * Fillin the flags so cipher modules can see s/w 1883147Sxc151355 * crypto requirements and potentially allocate 1893147Sxc151355 * different state and/or attach different method 1903147Sxc151355 * pointers. 1913147Sxc151355 */ 1923147Sxc151355 key->wk_flags = (uint16_t)flags; 1933147Sxc151355 keyctx = cip->ic_attach(ic, key); 1943147Sxc151355 if (keyctx == NULL) { 1953147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 1964499Shx147065 "unable to attach cipher %s\n", cip->ic_name); 1973147Sxc151355 key->wk_flags = oflags; /* restore old flags */ 1983147Sxc151355 return (0); 1993147Sxc151355 } 2003147Sxc151355 CIPHER_DETACH(key); /* Detach old cipher */ 2013147Sxc151355 key->wk_cipher = cip; 2023147Sxc151355 key->wk_private = keyctx; 2033147Sxc151355 } 2043147Sxc151355 /* 2053147Sxc151355 * Commit to requested usage so driver can see the flags. 2063147Sxc151355 */ 2073147Sxc151355 key->wk_flags = (uint16_t)flags; 2083147Sxc151355 2093147Sxc151355 /* 2103147Sxc151355 * Ask the driver for a key index if we don't have one. 2113147Sxc151355 * Note that entries in the global key table always have 2123147Sxc151355 * an index; this means it's safe to call this routine 2133147Sxc151355 * for these entries just to setup the reference to the 2143147Sxc151355 * cipher template. Note also that when using software 2153147Sxc151355 * crypto we also call the driver to give us a key index. 2163147Sxc151355 */ 2173147Sxc151355 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 2183147Sxc151355 if (!DEV_KEY_ALLOC(ic, key, &keyix, &rxkeyix)) { 2193147Sxc151355 /* 2203147Sxc151355 * Driver has no room; fallback to doing crypto 2213147Sxc151355 * in the host. We change the flags and start the 2223147Sxc151355 * procedure over. If we get back here then there's 2233147Sxc151355 * no hope and we bail. Note that this can leave 2243147Sxc151355 * the key in a inconsistent state if the caller 2253147Sxc151355 * continues to use it. 2263147Sxc151355 */ 2273147Sxc151355 if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { 2283147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 2294499Shx147065 "crypto_setkey: " 2304499Shx147065 "no h/w resources for cipher %s, " 2314499Shx147065 "falling back to s/w\n", cip->ic_name); 2323147Sxc151355 oflags = key->wk_flags; 2333147Sxc151355 flags |= IEEE80211_KEY_SWCRYPT; 2343147Sxc151355 if (cipher == IEEE80211_CIPHER_TKIP) 2353147Sxc151355 flags |= IEEE80211_KEY_SWMIC; 2363147Sxc151355 goto again; 2373147Sxc151355 } 2383147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 2394499Shx147065 "unable to setup cipher %s\n", cip->ic_name); 2403147Sxc151355 return (0); 2413147Sxc151355 } 2423147Sxc151355 key->wk_keyix = keyix; 2433147Sxc151355 key->wk_rxkeyix = rxkeyix; 2443147Sxc151355 } 2453147Sxc151355 return (1); 2463147Sxc151355 } 2473147Sxc151355 2483147Sxc151355 /* 2493147Sxc151355 * Remove the key (no locking, for internal use). 2503147Sxc151355 */ 2513147Sxc151355 static int 2523147Sxc151355 ieee80211_crypto_delkey_locked(ieee80211com_t *ic, struct ieee80211_key *key) 2533147Sxc151355 { 2543147Sxc151355 uint16_t keyix; 2553147Sxc151355 2563147Sxc151355 ASSERT(key->wk_cipher != NULL); 2573147Sxc151355 2583147Sxc151355 keyix = key->wk_keyix; 2593147Sxc151355 if (keyix != IEEE80211_KEYIX_NONE) { 2603147Sxc151355 /* 2613147Sxc151355 * Remove hardware entry. 2623147Sxc151355 */ 2633147Sxc151355 if (!DEV_KEY_DELETE(ic, key)) { 2643147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 2654499Shx147065 "ieee80211_crypto_delkey_locked: ", 2664499Shx147065 "driverdeletes key %u failed\n", keyix); 2673147Sxc151355 } 2683147Sxc151355 } 2693147Sxc151355 CIPHER_DETACH(key); 2703147Sxc151355 bzero(key, sizeof (struct ieee80211_key)); 2713147Sxc151355 /* NB: cannot depend on key index to decide this */ 2723147Sxc151355 ieee80211_crypto_resetkey(ic, key, IEEE80211_KEYIX_NONE); 2733147Sxc151355 return (1); 2743147Sxc151355 } 2753147Sxc151355 2763147Sxc151355 /* 2773147Sxc151355 * Remove the specified key. 2783147Sxc151355 */ 2793147Sxc151355 int 2803147Sxc151355 ieee80211_crypto_delkey(ieee80211com_t *ic, struct ieee80211_key *key) 2813147Sxc151355 { 2823147Sxc151355 int status; 2833147Sxc151355 2843147Sxc151355 KEY_UPDATE_BEGIN(ic); 2853147Sxc151355 status = ieee80211_crypto_delkey_locked(ic, key); 2863147Sxc151355 KEY_UPDATE_END(ic); 2873147Sxc151355 return (status); 2883147Sxc151355 } 2893147Sxc151355 2903147Sxc151355 /* 2913147Sxc151355 * Clear the global key table. 2923147Sxc151355 */ 2933147Sxc151355 static void 2943147Sxc151355 ieee80211_crypto_delglobalkeys(ieee80211com_t *ic) 2953147Sxc151355 { 2963147Sxc151355 int i; 2973147Sxc151355 2983147Sxc151355 KEY_UPDATE_BEGIN(ic); 2993147Sxc151355 for (i = 0; i < IEEE80211_WEP_NKID; i++) 3003147Sxc151355 (void) ieee80211_crypto_delkey_locked(ic, &ic->ic_nw_keys[i]); 3013147Sxc151355 KEY_UPDATE_END(ic); 3023147Sxc151355 } 3033147Sxc151355 3043147Sxc151355 /* 3053147Sxc151355 * Set the contents of the specified key. 3063147Sxc151355 * 3073147Sxc151355 * Locking must be handled by the caller using: 3083147Sxc151355 * ieee80211_key_update_begin(ic); 3093147Sxc151355 * ieee80211_key_update_end(ic); 3103147Sxc151355 */ 3113147Sxc151355 int 3123147Sxc151355 ieee80211_crypto_setkey(ieee80211com_t *ic, struct ieee80211_key *key, 3133147Sxc151355 const uint8_t *macaddr) 3143147Sxc151355 { 3153147Sxc151355 const struct ieee80211_cipher *cip = key->wk_cipher; 3163147Sxc151355 3173147Sxc151355 ASSERT(cip != NULL); 3183147Sxc151355 3193147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 3204499Shx147065 "%s keyix %u flags 0x%x mac %s len %u\n", 3214499Shx147065 cip->ic_name, key->wk_keyix, key->wk_flags, 3224499Shx147065 ieee80211_macaddr_sprintf(macaddr), key->wk_keylen); 3233147Sxc151355 3243147Sxc151355 /* 3253147Sxc151355 * Give cipher a chance to validate key contents. 3263147Sxc151355 * should happen before modifying state. 3273147Sxc151355 */ 3283147Sxc151355 if (cip->ic_setkey(key) == 0) { 3293147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 3304499Shx147065 "cipher %s rejected key index %u len %u flags 0x%x\n", 3314499Shx147065 cip->ic_name, key->wk_keyix, key->wk_keylen, 3324499Shx147065 key->wk_flags); 3333147Sxc151355 return (0); 3343147Sxc151355 } 3353147Sxc151355 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 3363147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 3374499Shx147065 "no key index; should not happen!\n"); 3383147Sxc151355 return (0); 3393147Sxc151355 } 3403147Sxc151355 return (DEV_KEY_SET(ic, key, macaddr)); 3413147Sxc151355 } 3423147Sxc151355 3433147Sxc151355 /* 3443147Sxc151355 * Return the transmit key to use in sending a frame. 3453147Sxc151355 */ 3463147Sxc151355 struct ieee80211_key * 3473147Sxc151355 ieee80211_crypto_getkey(ieee80211com_t *ic) 3483147Sxc151355 { 3493147Sxc151355 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || 3503147Sxc151355 KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) 3513147Sxc151355 return (NULL); 3523147Sxc151355 return (&ic->ic_nw_keys[ic->ic_def_txkey]); 3533147Sxc151355 } 3543147Sxc151355 3553147Sxc151355 uint8_t 3563147Sxc151355 ieee80211_crypto_getciphertype(ieee80211com_t *ic) 3573147Sxc151355 { 3583147Sxc151355 struct ieee80211_key *key; 3593147Sxc151355 uint32_t cipher; 3603147Sxc151355 static const uint8_t ciphermap[] = { 3613147Sxc151355 WIFI_SEC_WEP, /* IEEE80211_CIPHER_WEP */ 3624126Szf162725 WIFI_SEC_WPA, /* IEEE80211_CIPHER_TKIP */ 3633147Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_AES_OCB */ 3644126Szf162725 WIFI_SEC_WPA, /* IEEE80211_CIPHER_AES_CCM */ 3653147Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_CKIP */ 3663147Sxc151355 WIFI_SEC_NONE, /* IEEE80211_CIPHER_NONE */ 3673147Sxc151355 }; 3683147Sxc151355 3693147Sxc151355 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) 3703147Sxc151355 return (WIFI_SEC_NONE); 3713147Sxc151355 3723147Sxc151355 key = ieee80211_crypto_getkey(ic); 3733147Sxc151355 if (key == NULL) 3743147Sxc151355 return (WIFI_SEC_NONE); 3753147Sxc151355 3763147Sxc151355 cipher = key->wk_cipher->ic_cipher; 3773147Sxc151355 ASSERT(cipher < IEEE80211_N(ciphermap)); 3783147Sxc151355 return (ciphermap[cipher]); 3793147Sxc151355 } 3803147Sxc151355 3813147Sxc151355 /* 3823147Sxc151355 * Add privacy headers appropriate for the specified key. 3833147Sxc151355 */ 3843147Sxc151355 struct ieee80211_key * 3853147Sxc151355 ieee80211_crypto_encap(ieee80211com_t *ic, mblk_t *mp) 3863147Sxc151355 { 3873147Sxc151355 struct ieee80211_key *k; 3883147Sxc151355 const struct ieee80211_cipher *cip; 3893147Sxc151355 uint8_t keyix; 3903147Sxc151355 3913147Sxc151355 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) { 3923147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 3934499Shx147065 "ieee80211_crypto_encap: %s", 3944499Shx147065 " No default xmit key for frame\n"); 3953147Sxc151355 return (NULL); 3963147Sxc151355 } 3973147Sxc151355 keyix = ic->ic_def_txkey; 3983147Sxc151355 k = &ic->ic_nw_keys[ic->ic_def_txkey]; 3993147Sxc151355 cip = k->wk_cipher; 4003147Sxc151355 return (cip->ic_encap(k, mp, keyix<<6) ? k : NULL); 4013147Sxc151355 } 4023147Sxc151355 4033147Sxc151355 /* 4043147Sxc151355 * Validate and strip privacy headers (and trailer) for a 4053147Sxc151355 * received frame that has the WEP/Privacy bit set. 4063147Sxc151355 */ 4073147Sxc151355 struct ieee80211_key * 4083147Sxc151355 ieee80211_crypto_decap(ieee80211com_t *ic, mblk_t *mp, int hdrlen) 4093147Sxc151355 { 4103147Sxc151355 struct ieee80211_key *k; 4113147Sxc151355 const struct ieee80211_cipher *cip; 4123147Sxc151355 uint8_t *ivp; 4133147Sxc151355 uint8_t keyid; 4143147Sxc151355 4153147Sxc151355 /* NB: this minimum size data frame could be bigger */ 4163147Sxc151355 if ((mp->b_wptr - mp->b_rptr) < IEEE80211_WEP_MINLEN) { 4173147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_decap:" 4184499Shx147065 " WEP data frame too short, len %u\n", 4194499Shx147065 mp->b_wptr - mp->b_rptr); 4203147Sxc151355 return (NULL); 4213147Sxc151355 } 4223147Sxc151355 /* 4233147Sxc151355 * Locate the key. If unicast and there is no unicast 4243147Sxc151355 * key then we fall back to the key id in the header. 4253147Sxc151355 * This assumes unicast keys are only configured when 4263147Sxc151355 * the key id in the header is meaningless (typically 0). 4273147Sxc151355 */ 4283147Sxc151355 ivp = mp->b_rptr + hdrlen; 4293147Sxc151355 keyid = ivp[IEEE80211_WEP_IVLEN]; 4303147Sxc151355 k = &ic->ic_nw_keys[keyid >> 6]; 4313147Sxc151355 4323147Sxc151355 /* check to avoid panic when wep is on but key is not set */ 4333147Sxc151355 if (k->wk_cipher == &ieee80211_cipher_none || 4343147Sxc151355 k->wk_cipher == NULL) 4353147Sxc151355 return (NULL); 4363147Sxc151355 4373147Sxc151355 cip = k->wk_cipher; 4383147Sxc151355 return ((cip->ic_decap)(k, mp, hdrlen) ? k : NULL); 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 450*5296Szf162725 (void) crypto_mech2id(SUN_CKM_RC4); /* Load RC4 */ 451*5296Szf162725 (void) crypto_mech2id(SUN_CKM_AES_CBC); /* Load AES-CBC */ 452*5296Szf162725 (void) crypto_mech2id(SUN_CKM_AES_CCM); /* Load AES-CCM */ 453*5296Szf162725 4543147Sxc151355 /* NB: we assume everything is pre-zero'd */ 4553147Sxc151355 cs->cs_def_txkey = IEEE80211_KEYIX_NONE; 4563147Sxc151355 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 4573147Sxc151355 ieee80211_crypto_resetkey(ic, &cs->cs_nw_keys[i], 4584499Shx147065 IEEE80211_KEYIX_NONE); 4593147Sxc151355 } 4603147Sxc151355 4613147Sxc151355 /* 4623147Sxc151355 * Initialize the driver key support routines to noop entries. 4633147Sxc151355 * This is useful especially for the cipher test modules. 4643147Sxc151355 */ 4653147Sxc151355 cs->cs_key_alloc = nulldev_key_alloc; 4663147Sxc151355 cs->cs_key_set = nulldev_key_set; 4673147Sxc151355 cs->cs_key_delete = nulldev_key_delete; 4683147Sxc151355 cs->cs_key_update_begin = nulldev_key_update; 4693147Sxc151355 cs->cs_key_update_end = nulldev_key_update; 4703147Sxc151355 4714499Shx147065 ieee80211_crypto_register(ic, &wep); 4724499Shx147065 ieee80211_crypto_register(ic, &tkip); 4734499Shx147065 ieee80211_crypto_register(ic, &ccmp); 4743147Sxc151355 } 4753147Sxc151355 4763147Sxc151355 /* 4773147Sxc151355 * Teardown crypto support. 4783147Sxc151355 */ 4793147Sxc151355 void 4803147Sxc151355 ieee80211_crypto_detach(ieee80211com_t *ic) 4813147Sxc151355 { 4823147Sxc151355 ieee80211_crypto_delglobalkeys(ic); 4833147Sxc151355 4844499Shx147065 ieee80211_crypto_unregister(ic, &wep); 4854499Shx147065 ieee80211_crypto_unregister(ic, &tkip); 4864499Shx147065 ieee80211_crypto_unregister(ic, &ccmp); 4873147Sxc151355 } 4883147Sxc151355 4893147Sxc151355 /* 4903147Sxc151355 * Register a crypto cipher module. 4913147Sxc151355 */ 4923147Sxc151355 void 4934499Shx147065 ieee80211_crypto_register(ieee80211com_t *ic, 4944499Shx147065 const struct ieee80211_cipher *cip) 4953147Sxc151355 { 4963147Sxc151355 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 4973147Sxc151355 ieee80211_err("ieee80211_crypto_register: " 4984499Shx147065 "cipher %s has an invalid cipher index %u\n", 4994499Shx147065 cip->ic_name, cip->ic_cipher); 5003147Sxc151355 return; 5013147Sxc151355 } 5024499Shx147065 if (ic->ic_ciphers[cip->ic_cipher] != NULL && 5034499Shx147065 ic->ic_ciphers[cip->ic_cipher] != cip) { 5043147Sxc151355 ieee80211_err("ieee80211_crypto_register: " 5054499Shx147065 "cipher %s registered with a different template\n", 5064499Shx147065 cip->ic_name); 5073147Sxc151355 return; 5083147Sxc151355 } 5094499Shx147065 ic->ic_ciphers[cip->ic_cipher] = cip; 5103147Sxc151355 } 5113147Sxc151355 5123147Sxc151355 /* 5133147Sxc151355 * Unregister a crypto cipher module. 5143147Sxc151355 */ 5153147Sxc151355 void 5164499Shx147065 ieee80211_crypto_unregister(ieee80211com_t *ic, 5174499Shx147065 const struct ieee80211_cipher *cip) 5183147Sxc151355 { 5193147Sxc151355 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 5203147Sxc151355 ieee80211_err("ieee80211_crypto_unregister: " 5214499Shx147065 "cipher %s has an invalid cipher index %u\n", 5224499Shx147065 cip->ic_name, cip->ic_cipher); 5233147Sxc151355 return; 5243147Sxc151355 } 5254499Shx147065 if (ic->ic_ciphers[cip->ic_cipher] != NULL && 5264499Shx147065 ic->ic_ciphers[cip->ic_cipher] != cip) { 5273147Sxc151355 ieee80211_err("ieee80211_crypto_unregister: " 5284499Shx147065 "cipher %s registered with a different template\n", 5294499Shx147065 cip->ic_name); 5303147Sxc151355 return; 5313147Sxc151355 } 5323147Sxc151355 /* NB: don't complain about not being registered */ 5334499Shx147065 ic->ic_ciphers[cip->ic_cipher] = NULL; 5343147Sxc151355 } 535