1*3147Sxc151355 /* 2*3147Sxc151355 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3*3147Sxc151355 * Use is subject to license terms. 4*3147Sxc151355 */ 5*3147Sxc151355 6*3147Sxc151355 /* 7*3147Sxc151355 * Copyright (c) 2001 Atsushi Onoe 8*3147Sxc151355 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting 9*3147Sxc151355 * All rights reserved. 10*3147Sxc151355 * 11*3147Sxc151355 * Redistribution and use in source and binary forms, with or without 12*3147Sxc151355 * modification, are permitted provided that the following conditions 13*3147Sxc151355 * are met: 14*3147Sxc151355 * 1. Redistributions of source code must retain the above copyright 15*3147Sxc151355 * notice, this list of conditions and the following disclaimer. 16*3147Sxc151355 * 2. Redistributions in binary form must reproduce the above copyright 17*3147Sxc151355 * notice, this list of conditions and the following disclaimer in the 18*3147Sxc151355 * documentation and/or other materials provided with the distribution. 19*3147Sxc151355 * 3. The name of the author may not be used to endorse or promote products 20*3147Sxc151355 * derived from this software without specific prior written permission. 21*3147Sxc151355 * 22*3147Sxc151355 * Alternatively, this software may be distributed under the terms of the 23*3147Sxc151355 * GNU General Public License ("GPL") version 2 as published by the Free 24*3147Sxc151355 * Software Foundation. 25*3147Sxc151355 * 26*3147Sxc151355 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27*3147Sxc151355 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28*3147Sxc151355 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29*3147Sxc151355 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30*3147Sxc151355 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31*3147Sxc151355 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32*3147Sxc151355 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33*3147Sxc151355 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34*3147Sxc151355 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35*3147Sxc151355 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36*3147Sxc151355 */ 37*3147Sxc151355 38*3147Sxc151355 #pragma ident "%Z%%M% %I% %E% SMI" 39*3147Sxc151355 40*3147Sxc151355 /* 41*3147Sxc151355 * IEEE 802.11 generic crypto support 42*3147Sxc151355 */ 43*3147Sxc151355 #include <sys/types.h> 44*3147Sxc151355 #include <sys/note.h> 45*3147Sxc151355 #include "net80211_impl.h" 46*3147Sxc151355 47*3147Sxc151355 extern const struct ieee80211_cipher wep; 48*3147Sxc151355 49*3147Sxc151355 /* 50*3147Sxc151355 * Table of registered cipher modules. 51*3147Sxc151355 */ 52*3147Sxc151355 static const struct ieee80211_cipher *ciphers[IEEE80211_CIPHER_MAX]; 53*3147Sxc151355 static const char *cipher_modnames[] = { 54*3147Sxc151355 "wlan_wep", /* IEEE80211_CIPHER_WEP */ 55*3147Sxc151355 "wlan_tkip", /* IEEE80211_CIPHER_TKIP */ 56*3147Sxc151355 "wlan_aes_ocb", /* IEEE80211_CIPHER_AES_OCB */ 57*3147Sxc151355 "wlan_ccmp", /* IEEE80211_CIPHER_AES_CCM */ 58*3147Sxc151355 "wlan_ckip", /* IEEE80211_CIPHER_CKIP */ 59*3147Sxc151355 }; 60*3147Sxc151355 61*3147Sxc151355 /* 62*3147Sxc151355 * Default "null" key management routines. 63*3147Sxc151355 */ 64*3147Sxc151355 /* ARGSUSED */ 65*3147Sxc151355 static int 66*3147Sxc151355 nulldev_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k, 67*3147Sxc151355 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 68*3147Sxc151355 { 69*3147Sxc151355 *keyix = 0; /* use key index 0 for ucast key */ 70*3147Sxc151355 *rxkeyix = IEEE80211_KEYIX_NONE; 71*3147Sxc151355 return (1); 72*3147Sxc151355 } 73*3147Sxc151355 74*3147Sxc151355 /* ARGSUSED */ 75*3147Sxc151355 static int 76*3147Sxc151355 nulldev_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k) 77*3147Sxc151355 { 78*3147Sxc151355 return (1); 79*3147Sxc151355 } 80*3147Sxc151355 81*3147Sxc151355 /* ARGSUSED */ 82*3147Sxc151355 static int 83*3147Sxc151355 nulldev_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 84*3147Sxc151355 const uint8_t *mac) 85*3147Sxc151355 { 86*3147Sxc151355 return (1); 87*3147Sxc151355 } 88*3147Sxc151355 89*3147Sxc151355 /* ARGSUSED */ 90*3147Sxc151355 static void 91*3147Sxc151355 nulldev_key_update(ieee80211com_t *ic) 92*3147Sxc151355 { 93*3147Sxc151355 /* noop */ 94*3147Sxc151355 } 95*3147Sxc151355 96*3147Sxc151355 /* 97*3147Sxc151355 * Reset key state to an unused state. The crypto 98*3147Sxc151355 * key allocation mechanism insures other state (e.g. 99*3147Sxc151355 * key data) is properly setup before a key is used. 100*3147Sxc151355 */ 101*3147Sxc151355 void 102*3147Sxc151355 ieee80211_crypto_resetkey(ieee80211com_t *ic, 103*3147Sxc151355 struct ieee80211_key *k, ieee80211_keyix ix) 104*3147Sxc151355 { 105*3147Sxc151355 k->wk_cipher = &ieee80211_cipher_none; 106*3147Sxc151355 k->wk_private = k->wk_cipher->ic_attach(ic, k); 107*3147Sxc151355 k->wk_keyix = ix; 108*3147Sxc151355 k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 109*3147Sxc151355 } 110*3147Sxc151355 111*3147Sxc151355 /* 112*3147Sxc151355 * Establish a relationship between the specified key and cipher 113*3147Sxc151355 * and, if necessary, allocate a hardware index from the driver. 114*3147Sxc151355 * Note that when a fixed key index is required it must be specified 115*3147Sxc151355 * and we blindly assign it w/o consulting the driver. 116*3147Sxc151355 * 117*3147Sxc151355 * This must be the first call applied to a key; all the other key 118*3147Sxc151355 * routines assume wk_cipher is setup. 119*3147Sxc151355 * 120*3147Sxc151355 * Locking must be handled by the caller using: 121*3147Sxc151355 * ieee80211_key_update_begin(ic); 122*3147Sxc151355 * ieee80211_key_update_end(ic); 123*3147Sxc151355 */ 124*3147Sxc151355 int 125*3147Sxc151355 ieee80211_crypto_newkey(ieee80211com_t *ic, int cipher, int flags, 126*3147Sxc151355 struct ieee80211_key *key) 127*3147Sxc151355 { 128*3147Sxc151355 const struct ieee80211_cipher *cip; 129*3147Sxc151355 ieee80211_keyix keyix, rxkeyix; 130*3147Sxc151355 void *keyctx; 131*3147Sxc151355 uint16_t oflags; 132*3147Sxc151355 133*3147Sxc151355 /* 134*3147Sxc151355 * Validate cipher and set reference to cipher routines. 135*3147Sxc151355 */ 136*3147Sxc151355 if (cipher >= IEEE80211_CIPHER_MAX) { 137*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 138*3147Sxc151355 "invalid cipher %u\n", cipher); 139*3147Sxc151355 return (0); 140*3147Sxc151355 } 141*3147Sxc151355 cip = ciphers[cipher]; 142*3147Sxc151355 /* already load all the ciphers, cip can't be NULL */ 143*3147Sxc151355 if (cip == NULL) { 144*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 145*3147Sxc151355 "unable to load cipher %u, module %s\n", 146*3147Sxc151355 cipher, cipher < IEEE80211_N(cipher_modnames) ? 147*3147Sxc151355 cipher_modnames[cipher] : "<unknown>"); 148*3147Sxc151355 return (0); 149*3147Sxc151355 } 150*3147Sxc151355 151*3147Sxc151355 oflags = key->wk_flags; 152*3147Sxc151355 flags &= IEEE80211_KEY_COMMON; 153*3147Sxc151355 /* 154*3147Sxc151355 * If the hardware does not support the cipher then 155*3147Sxc151355 * fallback to a host-based implementation. 156*3147Sxc151355 */ 157*3147Sxc151355 if ((ic->ic_caps & (1<<cipher)) == 0) { 158*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 159*3147Sxc151355 "no h/w support for cipher %s, falling back to s/w\n", 160*3147Sxc151355 cip->ic_name); 161*3147Sxc151355 flags |= IEEE80211_KEY_SWCRYPT; 162*3147Sxc151355 } 163*3147Sxc151355 164*3147Sxc151355 /* 165*3147Sxc151355 * Bind cipher to key instance. Note we do this 166*3147Sxc151355 * after checking the device capabilities so the 167*3147Sxc151355 * cipher module can optimize space usage based on 168*3147Sxc151355 * whether or not it needs to do the cipher work. 169*3147Sxc151355 */ 170*3147Sxc151355 if (key->wk_cipher != cip || key->wk_flags != flags) { 171*3147Sxc151355 again: 172*3147Sxc151355 /* 173*3147Sxc151355 * Fillin the flags so cipher modules can see s/w 174*3147Sxc151355 * crypto requirements and potentially allocate 175*3147Sxc151355 * different state and/or attach different method 176*3147Sxc151355 * pointers. 177*3147Sxc151355 */ 178*3147Sxc151355 key->wk_flags = (uint16_t)flags; 179*3147Sxc151355 keyctx = cip->ic_attach(ic, key); 180*3147Sxc151355 if (keyctx == NULL) { 181*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 182*3147Sxc151355 "unable to attach cipher %s\n", cip->ic_name); 183*3147Sxc151355 key->wk_flags = oflags; /* restore old flags */ 184*3147Sxc151355 return (0); 185*3147Sxc151355 } 186*3147Sxc151355 CIPHER_DETACH(key); /* Detach old cipher */ 187*3147Sxc151355 key->wk_cipher = cip; 188*3147Sxc151355 key->wk_private = keyctx; 189*3147Sxc151355 } 190*3147Sxc151355 /* 191*3147Sxc151355 * Commit to requested usage so driver can see the flags. 192*3147Sxc151355 */ 193*3147Sxc151355 key->wk_flags = (uint16_t)flags; 194*3147Sxc151355 195*3147Sxc151355 /* 196*3147Sxc151355 * Ask the driver for a key index if we don't have one. 197*3147Sxc151355 * Note that entries in the global key table always have 198*3147Sxc151355 * an index; this means it's safe to call this routine 199*3147Sxc151355 * for these entries just to setup the reference to the 200*3147Sxc151355 * cipher template. Note also that when using software 201*3147Sxc151355 * crypto we also call the driver to give us a key index. 202*3147Sxc151355 */ 203*3147Sxc151355 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 204*3147Sxc151355 if (!DEV_KEY_ALLOC(ic, key, &keyix, &rxkeyix)) { 205*3147Sxc151355 /* 206*3147Sxc151355 * Driver has no room; fallback to doing crypto 207*3147Sxc151355 * in the host. We change the flags and start the 208*3147Sxc151355 * procedure over. If we get back here then there's 209*3147Sxc151355 * no hope and we bail. Note that this can leave 210*3147Sxc151355 * the key in a inconsistent state if the caller 211*3147Sxc151355 * continues to use it. 212*3147Sxc151355 */ 213*3147Sxc151355 if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { 214*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 215*3147Sxc151355 "crypto_setkey: " 216*3147Sxc151355 "no h/w resources for cipher %s, " 217*3147Sxc151355 "falling back to s/w\n", cip->ic_name); 218*3147Sxc151355 oflags = key->wk_flags; 219*3147Sxc151355 flags |= IEEE80211_KEY_SWCRYPT; 220*3147Sxc151355 if (cipher == IEEE80211_CIPHER_TKIP) 221*3147Sxc151355 flags |= IEEE80211_KEY_SWMIC; 222*3147Sxc151355 goto again; 223*3147Sxc151355 } 224*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 225*3147Sxc151355 "unable to setup cipher %s\n", cip->ic_name); 226*3147Sxc151355 return (0); 227*3147Sxc151355 } 228*3147Sxc151355 key->wk_keyix = keyix; 229*3147Sxc151355 key->wk_rxkeyix = rxkeyix; 230*3147Sxc151355 } 231*3147Sxc151355 return (1); 232*3147Sxc151355 } 233*3147Sxc151355 234*3147Sxc151355 /* 235*3147Sxc151355 * Remove the key (no locking, for internal use). 236*3147Sxc151355 */ 237*3147Sxc151355 static int 238*3147Sxc151355 ieee80211_crypto_delkey_locked(ieee80211com_t *ic, struct ieee80211_key *key) 239*3147Sxc151355 { 240*3147Sxc151355 uint16_t keyix; 241*3147Sxc151355 242*3147Sxc151355 ASSERT(key->wk_cipher != NULL); 243*3147Sxc151355 244*3147Sxc151355 keyix = key->wk_keyix; 245*3147Sxc151355 if (keyix != IEEE80211_KEYIX_NONE) { 246*3147Sxc151355 /* 247*3147Sxc151355 * Remove hardware entry. 248*3147Sxc151355 */ 249*3147Sxc151355 if (!DEV_KEY_DELETE(ic, key)) { 250*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 251*3147Sxc151355 "ieee80211_crypto_delkey_locked: ", 252*3147Sxc151355 "driverdeletes key %u failed\n", keyix); 253*3147Sxc151355 } 254*3147Sxc151355 } 255*3147Sxc151355 CIPHER_DETACH(key); 256*3147Sxc151355 bzero(key, sizeof (struct ieee80211_key)); 257*3147Sxc151355 /* NB: cannot depend on key index to decide this */ 258*3147Sxc151355 ieee80211_crypto_resetkey(ic, key, IEEE80211_KEYIX_NONE); 259*3147Sxc151355 return (1); 260*3147Sxc151355 } 261*3147Sxc151355 262*3147Sxc151355 /* 263*3147Sxc151355 * Remove the specified key. 264*3147Sxc151355 */ 265*3147Sxc151355 int 266*3147Sxc151355 ieee80211_crypto_delkey(ieee80211com_t *ic, struct ieee80211_key *key) 267*3147Sxc151355 { 268*3147Sxc151355 int status; 269*3147Sxc151355 270*3147Sxc151355 KEY_UPDATE_BEGIN(ic); 271*3147Sxc151355 status = ieee80211_crypto_delkey_locked(ic, key); 272*3147Sxc151355 KEY_UPDATE_END(ic); 273*3147Sxc151355 return (status); 274*3147Sxc151355 } 275*3147Sxc151355 276*3147Sxc151355 /* 277*3147Sxc151355 * Clear the global key table. 278*3147Sxc151355 */ 279*3147Sxc151355 static void 280*3147Sxc151355 ieee80211_crypto_delglobalkeys(ieee80211com_t *ic) 281*3147Sxc151355 { 282*3147Sxc151355 int i; 283*3147Sxc151355 284*3147Sxc151355 KEY_UPDATE_BEGIN(ic); 285*3147Sxc151355 for (i = 0; i < IEEE80211_WEP_NKID; i++) 286*3147Sxc151355 (void) ieee80211_crypto_delkey_locked(ic, &ic->ic_nw_keys[i]); 287*3147Sxc151355 KEY_UPDATE_END(ic); 288*3147Sxc151355 } 289*3147Sxc151355 290*3147Sxc151355 /* 291*3147Sxc151355 * Set the contents of the specified key. 292*3147Sxc151355 * 293*3147Sxc151355 * Locking must be handled by the caller using: 294*3147Sxc151355 * ieee80211_key_update_begin(ic); 295*3147Sxc151355 * ieee80211_key_update_end(ic); 296*3147Sxc151355 */ 297*3147Sxc151355 int 298*3147Sxc151355 ieee80211_crypto_setkey(ieee80211com_t *ic, struct ieee80211_key *key, 299*3147Sxc151355 const uint8_t *macaddr) 300*3147Sxc151355 { 301*3147Sxc151355 const struct ieee80211_cipher *cip = key->wk_cipher; 302*3147Sxc151355 303*3147Sxc151355 ASSERT(cip != NULL); 304*3147Sxc151355 305*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 306*3147Sxc151355 "%s keyix %u flags 0x%x mac %s len %u\n", 307*3147Sxc151355 cip->ic_name, key->wk_keyix, key->wk_flags, 308*3147Sxc151355 ieee80211_macaddr_sprintf(macaddr), key->wk_keylen); 309*3147Sxc151355 310*3147Sxc151355 /* 311*3147Sxc151355 * Give cipher a chance to validate key contents. 312*3147Sxc151355 * should happen before modifying state. 313*3147Sxc151355 */ 314*3147Sxc151355 if (cip->ic_setkey(key) == 0) { 315*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 316*3147Sxc151355 "cipher %s rejected key index %u len %u flags 0x%x\n", 317*3147Sxc151355 cip->ic_name, key->wk_keyix, key->wk_keylen, 318*3147Sxc151355 key->wk_flags); 319*3147Sxc151355 return (0); 320*3147Sxc151355 } 321*3147Sxc151355 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 322*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 323*3147Sxc151355 "no key index; should not happen!\n"); 324*3147Sxc151355 return (0); 325*3147Sxc151355 } 326*3147Sxc151355 return (DEV_KEY_SET(ic, key, macaddr)); 327*3147Sxc151355 } 328*3147Sxc151355 329*3147Sxc151355 /* 330*3147Sxc151355 * Return the transmit key to use in sending a frame. 331*3147Sxc151355 */ 332*3147Sxc151355 struct ieee80211_key * 333*3147Sxc151355 ieee80211_crypto_getkey(ieee80211com_t *ic) 334*3147Sxc151355 { 335*3147Sxc151355 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || 336*3147Sxc151355 KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) 337*3147Sxc151355 return (NULL); 338*3147Sxc151355 return (&ic->ic_nw_keys[ic->ic_def_txkey]); 339*3147Sxc151355 } 340*3147Sxc151355 341*3147Sxc151355 uint8_t 342*3147Sxc151355 ieee80211_crypto_getciphertype(ieee80211com_t *ic) 343*3147Sxc151355 { 344*3147Sxc151355 struct ieee80211_key *key; 345*3147Sxc151355 uint32_t cipher; 346*3147Sxc151355 static const uint8_t ciphermap[] = { 347*3147Sxc151355 WIFI_SEC_WEP, /* IEEE80211_CIPHER_WEP */ 348*3147Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_TKIP */ 349*3147Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_AES_OCB */ 350*3147Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_AES_CCM */ 351*3147Sxc151355 (uint8_t)-1, /* 4 is not allocated */ 352*3147Sxc151355 (uint8_t)-1, /* IEEE80211_CIPHER_CKIP */ 353*3147Sxc151355 WIFI_SEC_NONE, /* IEEE80211_CIPHER_NONE */ 354*3147Sxc151355 }; 355*3147Sxc151355 356*3147Sxc151355 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) 357*3147Sxc151355 return (WIFI_SEC_NONE); 358*3147Sxc151355 359*3147Sxc151355 key = ieee80211_crypto_getkey(ic); 360*3147Sxc151355 if (key == NULL) 361*3147Sxc151355 return (WIFI_SEC_NONE); 362*3147Sxc151355 363*3147Sxc151355 cipher = key->wk_cipher->ic_cipher; 364*3147Sxc151355 ASSERT(cipher < IEEE80211_N(ciphermap)); 365*3147Sxc151355 return (ciphermap[cipher]); 366*3147Sxc151355 } 367*3147Sxc151355 368*3147Sxc151355 /* 369*3147Sxc151355 * Add privacy headers appropriate for the specified key. 370*3147Sxc151355 */ 371*3147Sxc151355 struct ieee80211_key * 372*3147Sxc151355 ieee80211_crypto_encap(ieee80211com_t *ic, mblk_t *mp) 373*3147Sxc151355 { 374*3147Sxc151355 struct ieee80211_key *k; 375*3147Sxc151355 const struct ieee80211_cipher *cip; 376*3147Sxc151355 uint8_t keyix; 377*3147Sxc151355 378*3147Sxc151355 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) { 379*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 380*3147Sxc151355 "ieee80211_crypto_encap: %s", 381*3147Sxc151355 " No default xmit key for frame\n"); 382*3147Sxc151355 return (NULL); 383*3147Sxc151355 } 384*3147Sxc151355 keyix = ic->ic_def_txkey; 385*3147Sxc151355 k = &ic->ic_nw_keys[ic->ic_def_txkey]; 386*3147Sxc151355 cip = k->wk_cipher; 387*3147Sxc151355 return (cip->ic_encap(k, mp, keyix<<6) ? k : NULL); 388*3147Sxc151355 } 389*3147Sxc151355 390*3147Sxc151355 /* 391*3147Sxc151355 * Validate and strip privacy headers (and trailer) for a 392*3147Sxc151355 * received frame that has the WEP/Privacy bit set. 393*3147Sxc151355 */ 394*3147Sxc151355 struct ieee80211_key * 395*3147Sxc151355 ieee80211_crypto_decap(ieee80211com_t *ic, mblk_t *mp, int hdrlen) 396*3147Sxc151355 { 397*3147Sxc151355 struct ieee80211_key *k; 398*3147Sxc151355 const struct ieee80211_cipher *cip; 399*3147Sxc151355 uint8_t *ivp; 400*3147Sxc151355 uint8_t keyid; 401*3147Sxc151355 402*3147Sxc151355 /* NB: this minimum size data frame could be bigger */ 403*3147Sxc151355 if ((mp->b_wptr - mp->b_rptr) < IEEE80211_WEP_MINLEN) { 404*3147Sxc151355 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_decap:" 405*3147Sxc151355 " WEP data frame too short, len %u\n", 406*3147Sxc151355 mp->b_wptr - mp->b_rptr); 407*3147Sxc151355 return (NULL); 408*3147Sxc151355 } 409*3147Sxc151355 /* 410*3147Sxc151355 * Locate the key. If unicast and there is no unicast 411*3147Sxc151355 * key then we fall back to the key id in the header. 412*3147Sxc151355 * This assumes unicast keys are only configured when 413*3147Sxc151355 * the key id in the header is meaningless (typically 0). 414*3147Sxc151355 */ 415*3147Sxc151355 ivp = mp->b_rptr + hdrlen; 416*3147Sxc151355 keyid = ivp[IEEE80211_WEP_IVLEN]; 417*3147Sxc151355 k = &ic->ic_nw_keys[keyid >> 6]; 418*3147Sxc151355 419*3147Sxc151355 /* check to avoid panic when wep is on but key is not set */ 420*3147Sxc151355 if (k->wk_cipher == &ieee80211_cipher_none || 421*3147Sxc151355 k->wk_cipher == NULL) 422*3147Sxc151355 return (NULL); 423*3147Sxc151355 424*3147Sxc151355 cip = k->wk_cipher; 425*3147Sxc151355 return ((cip->ic_decap)(k, mp, hdrlen) ? k : NULL); 426*3147Sxc151355 } 427*3147Sxc151355 428*3147Sxc151355 429*3147Sxc151355 /* 430*3147Sxc151355 * Setup crypto support. 431*3147Sxc151355 */ 432*3147Sxc151355 void 433*3147Sxc151355 ieee80211_crypto_attach(ieee80211com_t *ic) 434*3147Sxc151355 { 435*3147Sxc151355 struct ieee80211_crypto_state *cs = &ic->ic_crypto; 436*3147Sxc151355 int i; 437*3147Sxc151355 438*3147Sxc151355 /* NB: we assume everything is pre-zero'd */ 439*3147Sxc151355 cs->cs_def_txkey = IEEE80211_KEYIX_NONE; 440*3147Sxc151355 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 441*3147Sxc151355 ieee80211_crypto_resetkey(ic, &cs->cs_nw_keys[i], 442*3147Sxc151355 IEEE80211_KEYIX_NONE); 443*3147Sxc151355 } 444*3147Sxc151355 445*3147Sxc151355 /* 446*3147Sxc151355 * Initialize the driver key support routines to noop entries. 447*3147Sxc151355 * This is useful especially for the cipher test modules. 448*3147Sxc151355 */ 449*3147Sxc151355 cs->cs_key_alloc = nulldev_key_alloc; 450*3147Sxc151355 cs->cs_key_set = nulldev_key_set; 451*3147Sxc151355 cs->cs_key_delete = nulldev_key_delete; 452*3147Sxc151355 cs->cs_key_update_begin = nulldev_key_update; 453*3147Sxc151355 cs->cs_key_update_end = nulldev_key_update; 454*3147Sxc151355 455*3147Sxc151355 ieee80211_crypto_register(&wep); 456*3147Sxc151355 } 457*3147Sxc151355 458*3147Sxc151355 /* 459*3147Sxc151355 * Teardown crypto support. 460*3147Sxc151355 */ 461*3147Sxc151355 void 462*3147Sxc151355 ieee80211_crypto_detach(ieee80211com_t *ic) 463*3147Sxc151355 { 464*3147Sxc151355 ieee80211_crypto_delglobalkeys(ic); 465*3147Sxc151355 466*3147Sxc151355 ieee80211_crypto_unregister(&wep); 467*3147Sxc151355 } 468*3147Sxc151355 469*3147Sxc151355 /* 470*3147Sxc151355 * Register a crypto cipher module. 471*3147Sxc151355 */ 472*3147Sxc151355 void 473*3147Sxc151355 ieee80211_crypto_register(const struct ieee80211_cipher *cip) 474*3147Sxc151355 { 475*3147Sxc151355 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 476*3147Sxc151355 ieee80211_err("ieee80211_crypto_register: " 477*3147Sxc151355 "cipher %s has an invalid cipher index %u\n", 478*3147Sxc151355 cip->ic_name, cip->ic_cipher); 479*3147Sxc151355 return; 480*3147Sxc151355 } 481*3147Sxc151355 if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) { 482*3147Sxc151355 ieee80211_err("ieee80211_crypto_register: " 483*3147Sxc151355 "cipher %s registered with a different template\n", 484*3147Sxc151355 cip->ic_name); 485*3147Sxc151355 return; 486*3147Sxc151355 } 487*3147Sxc151355 ciphers[cip->ic_cipher] = cip; 488*3147Sxc151355 } 489*3147Sxc151355 490*3147Sxc151355 /* 491*3147Sxc151355 * Unregister a crypto cipher module. 492*3147Sxc151355 */ 493*3147Sxc151355 void 494*3147Sxc151355 ieee80211_crypto_unregister(const struct ieee80211_cipher *cip) 495*3147Sxc151355 { 496*3147Sxc151355 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 497*3147Sxc151355 ieee80211_err("ieee80211_crypto_unregister: " 498*3147Sxc151355 "cipher %s has an invalid cipher index %u\n", 499*3147Sxc151355 cip->ic_name, cip->ic_cipher); 500*3147Sxc151355 return; 501*3147Sxc151355 } 502*3147Sxc151355 if (ciphers[cip->ic_cipher] != NULL && ciphers[cip->ic_cipher] != cip) { 503*3147Sxc151355 ieee80211_err("ieee80211_crypto_unregister: " 504*3147Sxc151355 "cipher %s registered with a different template\n", 505*3147Sxc151355 cip->ic_name); 506*3147Sxc151355 return; 507*3147Sxc151355 } 508*3147Sxc151355 /* NB: don't complain about not being registered */ 509*3147Sxc151355 ciphers[cip->ic_cipher] = NULL; 510*3147Sxc151355 } 511