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