10ba2cbe9Sxc151355 /* 2*ff3124efSff224033 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 30ba2cbe9Sxc151355 * Use is subject to license terms. 40ba2cbe9Sxc151355 */ 50ba2cbe9Sxc151355 60ba2cbe9Sxc151355 /* 70ba2cbe9Sxc151355 * Copyright (c) 2001 Atsushi Onoe 80ba2cbe9Sxc151355 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 90ba2cbe9Sxc151355 * All rights reserved. 100ba2cbe9Sxc151355 * 110ba2cbe9Sxc151355 * Redistribution and use in source and binary forms, with or without 120ba2cbe9Sxc151355 * modification, are permitted provided that the following conditions 130ba2cbe9Sxc151355 * are met: 140ba2cbe9Sxc151355 * 1. Redistributions of source code must retain the above copyright 150ba2cbe9Sxc151355 * notice, this list of conditions and the following disclaimer. 160ba2cbe9Sxc151355 * 2. Redistributions in binary form must reproduce the above copyright 170ba2cbe9Sxc151355 * notice, this list of conditions and the following disclaimer in the 180ba2cbe9Sxc151355 * documentation and/or other materials provided with the distribution. 190ba2cbe9Sxc151355 * 3. The name of the author may not be used to endorse or promote products 200ba2cbe9Sxc151355 * derived from this software without specific prior written permission. 210ba2cbe9Sxc151355 * 220ba2cbe9Sxc151355 * Alternatively, this software may be distributed under the terms of the 230ba2cbe9Sxc151355 * GNU General Public License ("GPL") version 2 as published by the Free 240ba2cbe9Sxc151355 * Software Foundation. 250ba2cbe9Sxc151355 * 260ba2cbe9Sxc151355 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 270ba2cbe9Sxc151355 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 280ba2cbe9Sxc151355 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 290ba2cbe9Sxc151355 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 300ba2cbe9Sxc151355 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 310ba2cbe9Sxc151355 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 320ba2cbe9Sxc151355 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 330ba2cbe9Sxc151355 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 340ba2cbe9Sxc151355 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 350ba2cbe9Sxc151355 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 360ba2cbe9Sxc151355 */ 370ba2cbe9Sxc151355 380ba2cbe9Sxc151355 #pragma ident "%Z%%M% %I% %E% SMI" 390ba2cbe9Sxc151355 400ba2cbe9Sxc151355 /* 410ba2cbe9Sxc151355 * IEEE 802.11 generic crypto support 420ba2cbe9Sxc151355 */ 430ba2cbe9Sxc151355 #include <sys/types.h> 440ba2cbe9Sxc151355 #include <sys/note.h> 453a1a8936Szf162725 #include <sys/crypto/common.h> 463a1a8936Szf162725 #include <sys/crypto/api.h> 47*ff3124efSff224033 #include <sys/strsun.h> 480ba2cbe9Sxc151355 #include "net80211_impl.h" 490ba2cbe9Sxc151355 500ba2cbe9Sxc151355 extern const struct ieee80211_cipher wep; 51a399b765Szf162725 extern const struct ieee80211_cipher tkip; 52a399b765Szf162725 extern const struct ieee80211_cipher ccmp; 530ba2cbe9Sxc151355 540ba2cbe9Sxc151355 /* 550ba2cbe9Sxc151355 * Table of registered cipher modules. 560ba2cbe9Sxc151355 */ 570ba2cbe9Sxc151355 static const char *cipher_modnames[] = { 580ba2cbe9Sxc151355 "wlan_wep", /* IEEE80211_CIPHER_WEP */ 590ba2cbe9Sxc151355 "wlan_tkip", /* IEEE80211_CIPHER_TKIP */ 600ba2cbe9Sxc151355 "wlan_aes_ocb", /* IEEE80211_CIPHER_AES_OCB */ 610ba2cbe9Sxc151355 "wlan_ccmp", /* IEEE80211_CIPHER_AES_CCM */ 620ba2cbe9Sxc151355 "wlan_ckip", /* IEEE80211_CIPHER_CKIP */ 630ba2cbe9Sxc151355 }; 640ba2cbe9Sxc151355 650ba2cbe9Sxc151355 /* 660ba2cbe9Sxc151355 * Default "null" key management routines. 670ba2cbe9Sxc151355 */ 680ba2cbe9Sxc151355 /* ARGSUSED */ 690ba2cbe9Sxc151355 static int 700ba2cbe9Sxc151355 nulldev_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k, 710ba2cbe9Sxc151355 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 720ba2cbe9Sxc151355 { 730ba2cbe9Sxc151355 *keyix = 0; /* use key index 0 for ucast key */ 740ba2cbe9Sxc151355 *rxkeyix = IEEE80211_KEYIX_NONE; 750ba2cbe9Sxc151355 return (1); 760ba2cbe9Sxc151355 } 770ba2cbe9Sxc151355 780ba2cbe9Sxc151355 /* ARGSUSED */ 790ba2cbe9Sxc151355 static int 800ba2cbe9Sxc151355 nulldev_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k) 810ba2cbe9Sxc151355 { 820ba2cbe9Sxc151355 return (1); 830ba2cbe9Sxc151355 } 840ba2cbe9Sxc151355 850ba2cbe9Sxc151355 /* ARGSUSED */ 860ba2cbe9Sxc151355 static int 870ba2cbe9Sxc151355 nulldev_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 880ba2cbe9Sxc151355 const uint8_t *mac) 890ba2cbe9Sxc151355 { 900ba2cbe9Sxc151355 return (1); 910ba2cbe9Sxc151355 } 920ba2cbe9Sxc151355 930ba2cbe9Sxc151355 /* ARGSUSED */ 940ba2cbe9Sxc151355 static void 950ba2cbe9Sxc151355 nulldev_key_update(ieee80211com_t *ic) 960ba2cbe9Sxc151355 { 970ba2cbe9Sxc151355 /* noop */ 980ba2cbe9Sxc151355 } 990ba2cbe9Sxc151355 1000ba2cbe9Sxc151355 /* 1010ba2cbe9Sxc151355 * Reset key state to an unused state. The crypto 1020ba2cbe9Sxc151355 * key allocation mechanism insures other state (e.g. 1030ba2cbe9Sxc151355 * key data) is properly setup before a key is used. 1040ba2cbe9Sxc151355 */ 1050ba2cbe9Sxc151355 void 1060ba2cbe9Sxc151355 ieee80211_crypto_resetkey(ieee80211com_t *ic, 1070ba2cbe9Sxc151355 struct ieee80211_key *k, ieee80211_keyix ix) 1080ba2cbe9Sxc151355 { 1090ba2cbe9Sxc151355 k->wk_cipher = &ieee80211_cipher_none; 1100ba2cbe9Sxc151355 k->wk_private = k->wk_cipher->ic_attach(ic, k); 1110ba2cbe9Sxc151355 k->wk_keyix = ix; 1120ba2cbe9Sxc151355 k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 1130ba2cbe9Sxc151355 } 1140ba2cbe9Sxc151355 1150ba2cbe9Sxc151355 /* 1160ba2cbe9Sxc151355 * Establish a relationship between the specified key and cipher 1170ba2cbe9Sxc151355 * and, if necessary, allocate a hardware index from the driver. 1180ba2cbe9Sxc151355 * Note that when a fixed key index is required it must be specified 1190ba2cbe9Sxc151355 * and we blindly assign it w/o consulting the driver. 1200ba2cbe9Sxc151355 * 1210ba2cbe9Sxc151355 * This must be the first call applied to a key; all the other key 1220ba2cbe9Sxc151355 * routines assume wk_cipher is setup. 1230ba2cbe9Sxc151355 * 1240ba2cbe9Sxc151355 * Locking must be handled by the caller using: 1250ba2cbe9Sxc151355 * ieee80211_key_update_begin(ic); 1260ba2cbe9Sxc151355 * ieee80211_key_update_end(ic); 1270ba2cbe9Sxc151355 */ 1280ba2cbe9Sxc151355 int 1290ba2cbe9Sxc151355 ieee80211_crypto_newkey(ieee80211com_t *ic, int cipher, int flags, 1300ba2cbe9Sxc151355 struct ieee80211_key *key) 1310ba2cbe9Sxc151355 { 1320ba2cbe9Sxc151355 const struct ieee80211_cipher *cip; 1330ba2cbe9Sxc151355 ieee80211_keyix keyix, rxkeyix; 1340ba2cbe9Sxc151355 void *keyctx; 1350ba2cbe9Sxc151355 uint16_t oflags; 1360ba2cbe9Sxc151355 1370ba2cbe9Sxc151355 /* 1380ba2cbe9Sxc151355 * Validate cipher and set reference to cipher routines. 1390ba2cbe9Sxc151355 */ 1400ba2cbe9Sxc151355 if (cipher >= IEEE80211_CIPHER_MAX) { 1410ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 1420ba2cbe9Sxc151355 "invalid cipher %u\n", cipher); 1430ba2cbe9Sxc151355 return (0); 1440ba2cbe9Sxc151355 } 145239e91abShx147065 cip = ic->ic_ciphers[cipher]; 1460ba2cbe9Sxc151355 /* already load all the ciphers, cip can't be NULL */ 1470ba2cbe9Sxc151355 if (cip == NULL) { 1480ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 1490ba2cbe9Sxc151355 "unable to load cipher %u, module %s\n", 1500ba2cbe9Sxc151355 cipher, cipher < IEEE80211_N(cipher_modnames) ? 1510ba2cbe9Sxc151355 cipher_modnames[cipher] : "<unknown>"); 1520ba2cbe9Sxc151355 return (0); 1530ba2cbe9Sxc151355 } 1540ba2cbe9Sxc151355 1550ba2cbe9Sxc151355 oflags = key->wk_flags; 1560ba2cbe9Sxc151355 flags &= IEEE80211_KEY_COMMON; 1570ba2cbe9Sxc151355 /* 1580ba2cbe9Sxc151355 * If the hardware does not support the cipher then 1590ba2cbe9Sxc151355 * fallback to a host-based implementation. 1600ba2cbe9Sxc151355 */ 1610ba2cbe9Sxc151355 if ((ic->ic_caps & (1<<cipher)) == 0) { 1620ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 1630ba2cbe9Sxc151355 "no h/w support for cipher %s, falling back to s/w\n", 1640ba2cbe9Sxc151355 cip->ic_name); 1650ba2cbe9Sxc151355 flags |= IEEE80211_KEY_SWCRYPT; 1660ba2cbe9Sxc151355 } 167a399b765Szf162725 /* 168a399b765Szf162725 * Hardware TKIP with software MIC is an important 169a399b765Szf162725 * combination; we handle it by flagging each key, 170a399b765Szf162725 * the cipher modules honor it. 171a399b765Szf162725 */ 172a399b765Szf162725 if (cipher == IEEE80211_CIPHER_TKIP && 173a399b765Szf162725 (ic->ic_caps & IEEE80211_C_TKIPMIC) == 0) { 174a399b765Szf162725 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 175a399b765Szf162725 "no h/w support for TKIP MIC, falling back to s/w\n"); 176a399b765Szf162725 flags |= IEEE80211_KEY_SWMIC; 177a399b765Szf162725 } 1780ba2cbe9Sxc151355 1790ba2cbe9Sxc151355 /* 1800ba2cbe9Sxc151355 * Bind cipher to key instance. Note we do this 1810ba2cbe9Sxc151355 * after checking the device capabilities so the 1820ba2cbe9Sxc151355 * cipher module can optimize space usage based on 1830ba2cbe9Sxc151355 * whether or not it needs to do the cipher work. 1840ba2cbe9Sxc151355 */ 1850ba2cbe9Sxc151355 if (key->wk_cipher != cip || key->wk_flags != flags) { 1860ba2cbe9Sxc151355 again: 1870ba2cbe9Sxc151355 /* 1880ba2cbe9Sxc151355 * Fillin the flags so cipher modules can see s/w 1890ba2cbe9Sxc151355 * crypto requirements and potentially allocate 1900ba2cbe9Sxc151355 * different state and/or attach different method 1910ba2cbe9Sxc151355 * pointers. 1920ba2cbe9Sxc151355 */ 1930ba2cbe9Sxc151355 key->wk_flags = (uint16_t)flags; 1940ba2cbe9Sxc151355 keyctx = cip->ic_attach(ic, key); 1950ba2cbe9Sxc151355 if (keyctx == NULL) { 1960ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 1970ba2cbe9Sxc151355 "unable to attach cipher %s\n", cip->ic_name); 1980ba2cbe9Sxc151355 key->wk_flags = oflags; /* restore old flags */ 1990ba2cbe9Sxc151355 return (0); 2000ba2cbe9Sxc151355 } 2010ba2cbe9Sxc151355 CIPHER_DETACH(key); /* Detach old cipher */ 2020ba2cbe9Sxc151355 key->wk_cipher = cip; 2030ba2cbe9Sxc151355 key->wk_private = keyctx; 2040ba2cbe9Sxc151355 } 2050ba2cbe9Sxc151355 /* 2060ba2cbe9Sxc151355 * Commit to requested usage so driver can see the flags. 2070ba2cbe9Sxc151355 */ 2080ba2cbe9Sxc151355 key->wk_flags = (uint16_t)flags; 2090ba2cbe9Sxc151355 2100ba2cbe9Sxc151355 /* 2110ba2cbe9Sxc151355 * Ask the driver for a key index if we don't have one. 2120ba2cbe9Sxc151355 * Note that entries in the global key table always have 2130ba2cbe9Sxc151355 * an index; this means it's safe to call this routine 2140ba2cbe9Sxc151355 * for these entries just to setup the reference to the 2150ba2cbe9Sxc151355 * cipher template. Note also that when using software 2160ba2cbe9Sxc151355 * crypto we also call the driver to give us a key index. 2170ba2cbe9Sxc151355 */ 2180ba2cbe9Sxc151355 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 2190ba2cbe9Sxc151355 if (!DEV_KEY_ALLOC(ic, key, &keyix, &rxkeyix)) { 2200ba2cbe9Sxc151355 /* 2210ba2cbe9Sxc151355 * Driver has no room; fallback to doing crypto 2220ba2cbe9Sxc151355 * in the host. We change the flags and start the 2230ba2cbe9Sxc151355 * procedure over. If we get back here then there's 2240ba2cbe9Sxc151355 * no hope and we bail. Note that this can leave 2250ba2cbe9Sxc151355 * the key in a inconsistent state if the caller 2260ba2cbe9Sxc151355 * continues to use it. 2270ba2cbe9Sxc151355 */ 2280ba2cbe9Sxc151355 if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { 2290ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 2300ba2cbe9Sxc151355 "crypto_setkey: " 2310ba2cbe9Sxc151355 "no h/w resources for cipher %s, " 2320ba2cbe9Sxc151355 "falling back to s/w\n", cip->ic_name); 2330ba2cbe9Sxc151355 oflags = key->wk_flags; 2340ba2cbe9Sxc151355 flags |= IEEE80211_KEY_SWCRYPT; 2350ba2cbe9Sxc151355 if (cipher == IEEE80211_CIPHER_TKIP) 2360ba2cbe9Sxc151355 flags |= IEEE80211_KEY_SWMIC; 2370ba2cbe9Sxc151355 goto again; 2380ba2cbe9Sxc151355 } 2390ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 2400ba2cbe9Sxc151355 "unable to setup cipher %s\n", cip->ic_name); 2410ba2cbe9Sxc151355 return (0); 2420ba2cbe9Sxc151355 } 2430ba2cbe9Sxc151355 key->wk_keyix = keyix; 2440ba2cbe9Sxc151355 key->wk_rxkeyix = rxkeyix; 2450ba2cbe9Sxc151355 } 2460ba2cbe9Sxc151355 return (1); 2470ba2cbe9Sxc151355 } 2480ba2cbe9Sxc151355 2490ba2cbe9Sxc151355 /* 2500ba2cbe9Sxc151355 * Remove the key (no locking, for internal use). 2510ba2cbe9Sxc151355 */ 2520ba2cbe9Sxc151355 static int 2530ba2cbe9Sxc151355 ieee80211_crypto_delkey_locked(ieee80211com_t *ic, struct ieee80211_key *key) 2540ba2cbe9Sxc151355 { 2550ba2cbe9Sxc151355 uint16_t keyix; 2560ba2cbe9Sxc151355 2570ba2cbe9Sxc151355 ASSERT(key->wk_cipher != NULL); 2580ba2cbe9Sxc151355 2590ba2cbe9Sxc151355 keyix = key->wk_keyix; 2600ba2cbe9Sxc151355 if (keyix != IEEE80211_KEYIX_NONE) { 2610ba2cbe9Sxc151355 /* 2620ba2cbe9Sxc151355 * Remove hardware entry. 2630ba2cbe9Sxc151355 */ 2640ba2cbe9Sxc151355 if (!DEV_KEY_DELETE(ic, key)) { 2650ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 2660ba2cbe9Sxc151355 "ieee80211_crypto_delkey_locked: ", 2670ba2cbe9Sxc151355 "driverdeletes key %u failed\n", keyix); 2680ba2cbe9Sxc151355 } 2690ba2cbe9Sxc151355 } 2700ba2cbe9Sxc151355 CIPHER_DETACH(key); 2710ba2cbe9Sxc151355 bzero(key, sizeof (struct ieee80211_key)); 2720ba2cbe9Sxc151355 /* NB: cannot depend on key index to decide this */ 2730ba2cbe9Sxc151355 ieee80211_crypto_resetkey(ic, key, IEEE80211_KEYIX_NONE); 2740ba2cbe9Sxc151355 return (1); 2750ba2cbe9Sxc151355 } 2760ba2cbe9Sxc151355 2770ba2cbe9Sxc151355 /* 2780ba2cbe9Sxc151355 * Remove the specified key. 2790ba2cbe9Sxc151355 */ 2800ba2cbe9Sxc151355 int 2810ba2cbe9Sxc151355 ieee80211_crypto_delkey(ieee80211com_t *ic, struct ieee80211_key *key) 2820ba2cbe9Sxc151355 { 2830ba2cbe9Sxc151355 int status; 2840ba2cbe9Sxc151355 2850ba2cbe9Sxc151355 KEY_UPDATE_BEGIN(ic); 2860ba2cbe9Sxc151355 status = ieee80211_crypto_delkey_locked(ic, key); 2870ba2cbe9Sxc151355 KEY_UPDATE_END(ic); 2880ba2cbe9Sxc151355 return (status); 2890ba2cbe9Sxc151355 } 2900ba2cbe9Sxc151355 2910ba2cbe9Sxc151355 /* 2920ba2cbe9Sxc151355 * Clear the global key table. 2930ba2cbe9Sxc151355 */ 2940ba2cbe9Sxc151355 static void 2950ba2cbe9Sxc151355 ieee80211_crypto_delglobalkeys(ieee80211com_t *ic) 2960ba2cbe9Sxc151355 { 2970ba2cbe9Sxc151355 int i; 2980ba2cbe9Sxc151355 2990ba2cbe9Sxc151355 KEY_UPDATE_BEGIN(ic); 3000ba2cbe9Sxc151355 for (i = 0; i < IEEE80211_WEP_NKID; i++) 3010ba2cbe9Sxc151355 (void) ieee80211_crypto_delkey_locked(ic, &ic->ic_nw_keys[i]); 3020ba2cbe9Sxc151355 KEY_UPDATE_END(ic); 3030ba2cbe9Sxc151355 } 3040ba2cbe9Sxc151355 3050ba2cbe9Sxc151355 /* 3060ba2cbe9Sxc151355 * Set the contents of the specified key. 3070ba2cbe9Sxc151355 * 3080ba2cbe9Sxc151355 * Locking must be handled by the caller using: 3090ba2cbe9Sxc151355 * ieee80211_key_update_begin(ic); 3100ba2cbe9Sxc151355 * ieee80211_key_update_end(ic); 3110ba2cbe9Sxc151355 */ 3120ba2cbe9Sxc151355 int 3130ba2cbe9Sxc151355 ieee80211_crypto_setkey(ieee80211com_t *ic, struct ieee80211_key *key, 3140ba2cbe9Sxc151355 const uint8_t *macaddr) 3150ba2cbe9Sxc151355 { 3160ba2cbe9Sxc151355 const struct ieee80211_cipher *cip = key->wk_cipher; 3170ba2cbe9Sxc151355 3180ba2cbe9Sxc151355 ASSERT(cip != NULL); 3190ba2cbe9Sxc151355 3200ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 3210ba2cbe9Sxc151355 "%s keyix %u flags 0x%x mac %s len %u\n", 3220ba2cbe9Sxc151355 cip->ic_name, key->wk_keyix, key->wk_flags, 3230ba2cbe9Sxc151355 ieee80211_macaddr_sprintf(macaddr), key->wk_keylen); 3240ba2cbe9Sxc151355 3250ba2cbe9Sxc151355 /* 3260ba2cbe9Sxc151355 * Give cipher a chance to validate key contents. 3270ba2cbe9Sxc151355 * should happen before modifying state. 3280ba2cbe9Sxc151355 */ 3290ba2cbe9Sxc151355 if (cip->ic_setkey(key) == 0) { 3300ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 3310ba2cbe9Sxc151355 "cipher %s rejected key index %u len %u flags 0x%x\n", 3320ba2cbe9Sxc151355 cip->ic_name, key->wk_keyix, key->wk_keylen, 3330ba2cbe9Sxc151355 key->wk_flags); 3340ba2cbe9Sxc151355 return (0); 3350ba2cbe9Sxc151355 } 3360ba2cbe9Sxc151355 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 3370ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 3380ba2cbe9Sxc151355 "no key index; should not happen!\n"); 3390ba2cbe9Sxc151355 return (0); 3400ba2cbe9Sxc151355 } 3410ba2cbe9Sxc151355 return (DEV_KEY_SET(ic, key, macaddr)); 3420ba2cbe9Sxc151355 } 3430ba2cbe9Sxc151355 3440ba2cbe9Sxc151355 /* 3450ba2cbe9Sxc151355 * Return the transmit key to use in sending a frame. 3460ba2cbe9Sxc151355 */ 3470ba2cbe9Sxc151355 struct ieee80211_key * 3480ba2cbe9Sxc151355 ieee80211_crypto_getkey(ieee80211com_t *ic) 3490ba2cbe9Sxc151355 { 3500ba2cbe9Sxc151355 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || 3510ba2cbe9Sxc151355 KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) 3520ba2cbe9Sxc151355 return (NULL); 3530ba2cbe9Sxc151355 return (&ic->ic_nw_keys[ic->ic_def_txkey]); 3540ba2cbe9Sxc151355 } 3550ba2cbe9Sxc151355 3560ba2cbe9Sxc151355 uint8_t 3570ba2cbe9Sxc151355 ieee80211_crypto_getciphertype(ieee80211com_t *ic) 3580ba2cbe9Sxc151355 { 3590ba2cbe9Sxc151355 struct ieee80211_key *key; 3600ba2cbe9Sxc151355 uint32_t cipher; 3610ba2cbe9Sxc151355 static const uint8_t ciphermap[] = { 3620ba2cbe9Sxc151355 WIFI_SEC_WEP, /* IEEE80211_CIPHER_WEP */ 363a399b765Szf162725 WIFI_SEC_WPA, /* IEEE80211_CIPHER_TKIP */ 3640ba2cbe9Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_AES_OCB */ 365a399b765Szf162725 WIFI_SEC_WPA, /* IEEE80211_CIPHER_AES_CCM */ 3660ba2cbe9Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_CKIP */ 3670ba2cbe9Sxc151355 WIFI_SEC_NONE, /* IEEE80211_CIPHER_NONE */ 3680ba2cbe9Sxc151355 }; 3690ba2cbe9Sxc151355 3700ba2cbe9Sxc151355 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) 3710ba2cbe9Sxc151355 return (WIFI_SEC_NONE); 3720ba2cbe9Sxc151355 3730ba2cbe9Sxc151355 key = ieee80211_crypto_getkey(ic); 3740ba2cbe9Sxc151355 if (key == NULL) 3750ba2cbe9Sxc151355 return (WIFI_SEC_NONE); 3760ba2cbe9Sxc151355 3770ba2cbe9Sxc151355 cipher = key->wk_cipher->ic_cipher; 3780ba2cbe9Sxc151355 ASSERT(cipher < IEEE80211_N(ciphermap)); 3790ba2cbe9Sxc151355 return (ciphermap[cipher]); 3800ba2cbe9Sxc151355 } 3810ba2cbe9Sxc151355 3820ba2cbe9Sxc151355 /* 3830ba2cbe9Sxc151355 * Add privacy headers appropriate for the specified key. 3840ba2cbe9Sxc151355 */ 3850ba2cbe9Sxc151355 struct ieee80211_key * 3860ba2cbe9Sxc151355 ieee80211_crypto_encap(ieee80211com_t *ic, mblk_t *mp) 3870ba2cbe9Sxc151355 { 3880ba2cbe9Sxc151355 struct ieee80211_key *k; 3890ba2cbe9Sxc151355 const struct ieee80211_cipher *cip; 3900ba2cbe9Sxc151355 uint8_t keyix; 3910ba2cbe9Sxc151355 3920ba2cbe9Sxc151355 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) { 3930ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 3940ba2cbe9Sxc151355 "ieee80211_crypto_encap: %s", 3950ba2cbe9Sxc151355 " No default xmit key for frame\n"); 3960ba2cbe9Sxc151355 return (NULL); 3970ba2cbe9Sxc151355 } 3980ba2cbe9Sxc151355 keyix = ic->ic_def_txkey; 3990ba2cbe9Sxc151355 k = &ic->ic_nw_keys[ic->ic_def_txkey]; 4000ba2cbe9Sxc151355 cip = k->wk_cipher; 4010ba2cbe9Sxc151355 return (cip->ic_encap(k, mp, keyix<<6) ? k : NULL); 4020ba2cbe9Sxc151355 } 4030ba2cbe9Sxc151355 4040ba2cbe9Sxc151355 /* 4050ba2cbe9Sxc151355 * Validate and strip privacy headers (and trailer) for a 4060ba2cbe9Sxc151355 * received frame that has the WEP/Privacy bit set. 4070ba2cbe9Sxc151355 */ 4080ba2cbe9Sxc151355 struct ieee80211_key * 4090ba2cbe9Sxc151355 ieee80211_crypto_decap(ieee80211com_t *ic, mblk_t *mp, int hdrlen) 4100ba2cbe9Sxc151355 { 4110ba2cbe9Sxc151355 struct ieee80211_key *k; 4120ba2cbe9Sxc151355 const struct ieee80211_cipher *cip; 4130ba2cbe9Sxc151355 uint8_t *ivp; 4140ba2cbe9Sxc151355 uint8_t keyid; 4150ba2cbe9Sxc151355 4160ba2cbe9Sxc151355 /* NB: this minimum size data frame could be bigger */ 417*ff3124efSff224033 if (MBLKL(mp) < IEEE80211_WEP_MINLEN) { 4180ba2cbe9Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_decap:" 4190ba2cbe9Sxc151355 " WEP data frame too short, len %u\n", 420*ff3124efSff224033 MBLKL(mp)); 4210ba2cbe9Sxc151355 return (NULL); 4220ba2cbe9Sxc151355 } 4230ba2cbe9Sxc151355 /* 4240ba2cbe9Sxc151355 * Locate the key. If unicast and there is no unicast 4250ba2cbe9Sxc151355 * key then we fall back to the key id in the header. 4260ba2cbe9Sxc151355 * This assumes unicast keys are only configured when 4270ba2cbe9Sxc151355 * the key id in the header is meaningless (typically 0). 4280ba2cbe9Sxc151355 */ 4290ba2cbe9Sxc151355 ivp = mp->b_rptr + hdrlen; 4300ba2cbe9Sxc151355 keyid = ivp[IEEE80211_WEP_IVLEN]; 4310ba2cbe9Sxc151355 k = &ic->ic_nw_keys[keyid >> 6]; 4320ba2cbe9Sxc151355 4330ba2cbe9Sxc151355 /* check to avoid panic when wep is on but key is not set */ 4340ba2cbe9Sxc151355 if (k->wk_cipher == &ieee80211_cipher_none || 4350ba2cbe9Sxc151355 k->wk_cipher == NULL) 4360ba2cbe9Sxc151355 return (NULL); 4370ba2cbe9Sxc151355 4380ba2cbe9Sxc151355 cip = k->wk_cipher; 4390ba2cbe9Sxc151355 return ((cip->ic_decap)(k, mp, hdrlen) ? k : NULL); 4400ba2cbe9Sxc151355 } 4410ba2cbe9Sxc151355 4420ba2cbe9Sxc151355 /* 4430ba2cbe9Sxc151355 * Setup crypto support. 4440ba2cbe9Sxc151355 */ 4450ba2cbe9Sxc151355 void 4460ba2cbe9Sxc151355 ieee80211_crypto_attach(ieee80211com_t *ic) 4470ba2cbe9Sxc151355 { 4480ba2cbe9Sxc151355 struct ieee80211_crypto_state *cs = &ic->ic_crypto; 4490ba2cbe9Sxc151355 int i; 4500ba2cbe9Sxc151355 4513a1a8936Szf162725 (void) crypto_mech2id(SUN_CKM_RC4); /* Load RC4 */ 4523a1a8936Szf162725 (void) crypto_mech2id(SUN_CKM_AES_CBC); /* Load AES-CBC */ 4533a1a8936Szf162725 (void) crypto_mech2id(SUN_CKM_AES_CCM); /* Load AES-CCM */ 4543a1a8936Szf162725 4550ba2cbe9Sxc151355 /* NB: we assume everything is pre-zero'd */ 4560ba2cbe9Sxc151355 cs->cs_def_txkey = IEEE80211_KEYIX_NONE; 4570ba2cbe9Sxc151355 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 4580ba2cbe9Sxc151355 ieee80211_crypto_resetkey(ic, &cs->cs_nw_keys[i], 4590ba2cbe9Sxc151355 IEEE80211_KEYIX_NONE); 4600ba2cbe9Sxc151355 } 4610ba2cbe9Sxc151355 4620ba2cbe9Sxc151355 /* 4630ba2cbe9Sxc151355 * Initialize the driver key support routines to noop entries. 4640ba2cbe9Sxc151355 * This is useful especially for the cipher test modules. 4650ba2cbe9Sxc151355 */ 4660ba2cbe9Sxc151355 cs->cs_key_alloc = nulldev_key_alloc; 4670ba2cbe9Sxc151355 cs->cs_key_set = nulldev_key_set; 4680ba2cbe9Sxc151355 cs->cs_key_delete = nulldev_key_delete; 4690ba2cbe9Sxc151355 cs->cs_key_update_begin = nulldev_key_update; 4700ba2cbe9Sxc151355 cs->cs_key_update_end = nulldev_key_update; 4710ba2cbe9Sxc151355 472239e91abShx147065 ieee80211_crypto_register(ic, &wep); 473239e91abShx147065 ieee80211_crypto_register(ic, &tkip); 474239e91abShx147065 ieee80211_crypto_register(ic, &ccmp); 4750ba2cbe9Sxc151355 } 4760ba2cbe9Sxc151355 4770ba2cbe9Sxc151355 /* 4780ba2cbe9Sxc151355 * Teardown crypto support. 4790ba2cbe9Sxc151355 */ 4800ba2cbe9Sxc151355 void 4810ba2cbe9Sxc151355 ieee80211_crypto_detach(ieee80211com_t *ic) 4820ba2cbe9Sxc151355 { 4830ba2cbe9Sxc151355 ieee80211_crypto_delglobalkeys(ic); 4840ba2cbe9Sxc151355 485239e91abShx147065 ieee80211_crypto_unregister(ic, &wep); 486239e91abShx147065 ieee80211_crypto_unregister(ic, &tkip); 487239e91abShx147065 ieee80211_crypto_unregister(ic, &ccmp); 4880ba2cbe9Sxc151355 } 4890ba2cbe9Sxc151355 4900ba2cbe9Sxc151355 /* 4910ba2cbe9Sxc151355 * Register a crypto cipher module. 4920ba2cbe9Sxc151355 */ 4930ba2cbe9Sxc151355 void 494239e91abShx147065 ieee80211_crypto_register(ieee80211com_t *ic, 495239e91abShx147065 const struct ieee80211_cipher *cip) 4960ba2cbe9Sxc151355 { 4970ba2cbe9Sxc151355 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 4980ba2cbe9Sxc151355 ieee80211_err("ieee80211_crypto_register: " 4990ba2cbe9Sxc151355 "cipher %s has an invalid cipher index %u\n", 5000ba2cbe9Sxc151355 cip->ic_name, cip->ic_cipher); 5010ba2cbe9Sxc151355 return; 5020ba2cbe9Sxc151355 } 503239e91abShx147065 if (ic->ic_ciphers[cip->ic_cipher] != NULL && 504239e91abShx147065 ic->ic_ciphers[cip->ic_cipher] != cip) { 5050ba2cbe9Sxc151355 ieee80211_err("ieee80211_crypto_register: " 5060ba2cbe9Sxc151355 "cipher %s registered with a different template\n", 5070ba2cbe9Sxc151355 cip->ic_name); 5080ba2cbe9Sxc151355 return; 5090ba2cbe9Sxc151355 } 510239e91abShx147065 ic->ic_ciphers[cip->ic_cipher] = cip; 5110ba2cbe9Sxc151355 } 5120ba2cbe9Sxc151355 5130ba2cbe9Sxc151355 /* 5140ba2cbe9Sxc151355 * Unregister a crypto cipher module. 5150ba2cbe9Sxc151355 */ 5160ba2cbe9Sxc151355 void 517239e91abShx147065 ieee80211_crypto_unregister(ieee80211com_t *ic, 518239e91abShx147065 const struct ieee80211_cipher *cip) 5190ba2cbe9Sxc151355 { 5200ba2cbe9Sxc151355 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 5210ba2cbe9Sxc151355 ieee80211_err("ieee80211_crypto_unregister: " 5220ba2cbe9Sxc151355 "cipher %s has an invalid cipher index %u\n", 5230ba2cbe9Sxc151355 cip->ic_name, cip->ic_cipher); 5240ba2cbe9Sxc151355 return; 5250ba2cbe9Sxc151355 } 526239e91abShx147065 if (ic->ic_ciphers[cip->ic_cipher] != NULL && 527239e91abShx147065 ic->ic_ciphers[cip->ic_cipher] != cip) { 5280ba2cbe9Sxc151355 ieee80211_err("ieee80211_crypto_unregister: " 5290ba2cbe9Sxc151355 "cipher %s registered with a different template\n", 5300ba2cbe9Sxc151355 cip->ic_name); 5310ba2cbe9Sxc151355 return; 5320ba2cbe9Sxc151355 } 5330ba2cbe9Sxc151355 /* NB: don't complain about not being registered */ 534239e91abShx147065 ic->ic_ciphers[cip->ic_cipher] = NULL; 5350ba2cbe9Sxc151355 } 536