1 /* 2 * Copyright 2007 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 <sys/crypto/common.h> 46 #include <sys/crypto/api.h> 47 #include "net80211_impl.h" 48 49 extern const struct ieee80211_cipher wep; 50 extern const struct ieee80211_cipher tkip; 51 extern const struct ieee80211_cipher ccmp; 52 53 /* 54 * Table of registered cipher modules. 55 */ 56 static const char *cipher_modnames[] = { 57 "wlan_wep", /* IEEE80211_CIPHER_WEP */ 58 "wlan_tkip", /* IEEE80211_CIPHER_TKIP */ 59 "wlan_aes_ocb", /* IEEE80211_CIPHER_AES_OCB */ 60 "wlan_ccmp", /* IEEE80211_CIPHER_AES_CCM */ 61 "wlan_ckip", /* IEEE80211_CIPHER_CKIP */ 62 }; 63 64 /* 65 * Default "null" key management routines. 66 */ 67 /* ARGSUSED */ 68 static int 69 nulldev_key_alloc(ieee80211com_t *ic, const struct ieee80211_key *k, 70 ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) 71 { 72 *keyix = 0; /* use key index 0 for ucast key */ 73 *rxkeyix = IEEE80211_KEYIX_NONE; 74 return (1); 75 } 76 77 /* ARGSUSED */ 78 static int 79 nulldev_key_delete(ieee80211com_t *ic, const struct ieee80211_key *k) 80 { 81 return (1); 82 } 83 84 /* ARGSUSED */ 85 static int 86 nulldev_key_set(ieee80211com_t *ic, const struct ieee80211_key *k, 87 const uint8_t *mac) 88 { 89 return (1); 90 } 91 92 /* ARGSUSED */ 93 static void 94 nulldev_key_update(ieee80211com_t *ic) 95 { 96 /* noop */ 97 } 98 99 /* 100 * Reset key state to an unused state. The crypto 101 * key allocation mechanism insures other state (e.g. 102 * key data) is properly setup before a key is used. 103 */ 104 void 105 ieee80211_crypto_resetkey(ieee80211com_t *ic, 106 struct ieee80211_key *k, ieee80211_keyix ix) 107 { 108 k->wk_cipher = &ieee80211_cipher_none; 109 k->wk_private = k->wk_cipher->ic_attach(ic, k); 110 k->wk_keyix = ix; 111 k->wk_flags = IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV; 112 } 113 114 /* 115 * Establish a relationship between the specified key and cipher 116 * and, if necessary, allocate a hardware index from the driver. 117 * Note that when a fixed key index is required it must be specified 118 * and we blindly assign it w/o consulting the driver. 119 * 120 * This must be the first call applied to a key; all the other key 121 * routines assume wk_cipher is setup. 122 * 123 * Locking must be handled by the caller using: 124 * ieee80211_key_update_begin(ic); 125 * ieee80211_key_update_end(ic); 126 */ 127 int 128 ieee80211_crypto_newkey(ieee80211com_t *ic, int cipher, int flags, 129 struct ieee80211_key *key) 130 { 131 const struct ieee80211_cipher *cip; 132 ieee80211_keyix keyix, rxkeyix; 133 void *keyctx; 134 uint16_t oflags; 135 136 /* 137 * Validate cipher and set reference to cipher routines. 138 */ 139 if (cipher >= IEEE80211_CIPHER_MAX) { 140 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 141 "invalid cipher %u\n", cipher); 142 return (0); 143 } 144 cip = ic->ic_ciphers[cipher]; 145 /* already load all the ciphers, cip can't be NULL */ 146 if (cip == NULL) { 147 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 148 "unable to load cipher %u, module %s\n", 149 cipher, cipher < IEEE80211_N(cipher_modnames) ? 150 cipher_modnames[cipher] : "<unknown>"); 151 return (0); 152 } 153 154 oflags = key->wk_flags; 155 flags &= IEEE80211_KEY_COMMON; 156 /* 157 * If the hardware does not support the cipher then 158 * fallback to a host-based implementation. 159 */ 160 if ((ic->ic_caps & (1<<cipher)) == 0) { 161 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_newkey: " 162 "no h/w support for cipher %s, falling back to s/w\n", 163 cip->ic_name); 164 flags |= IEEE80211_KEY_SWCRYPT; 165 } 166 /* 167 * Hardware TKIP with software MIC is an important 168 * combination; we handle it by flagging each key, 169 * the cipher modules honor it. 170 */ 171 if (cipher == IEEE80211_CIPHER_TKIP && 172 (ic->ic_caps & IEEE80211_C_TKIPMIC) == 0) { 173 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 174 "no h/w support for TKIP MIC, falling back to s/w\n"); 175 flags |= IEEE80211_KEY_SWMIC; 176 } 177 178 /* 179 * Bind cipher to key instance. Note we do this 180 * after checking the device capabilities so the 181 * cipher module can optimize space usage based on 182 * whether or not it needs to do the cipher work. 183 */ 184 if (key->wk_cipher != cip || key->wk_flags != flags) { 185 again: 186 /* 187 * Fillin the flags so cipher modules can see s/w 188 * crypto requirements and potentially allocate 189 * different state and/or attach different method 190 * pointers. 191 */ 192 key->wk_flags = (uint16_t)flags; 193 keyctx = cip->ic_attach(ic, key); 194 if (keyctx == NULL) { 195 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 196 "unable to attach cipher %s\n", cip->ic_name); 197 key->wk_flags = oflags; /* restore old flags */ 198 return (0); 199 } 200 CIPHER_DETACH(key); /* Detach old cipher */ 201 key->wk_cipher = cip; 202 key->wk_private = keyctx; 203 } 204 /* 205 * Commit to requested usage so driver can see the flags. 206 */ 207 key->wk_flags = (uint16_t)flags; 208 209 /* 210 * Ask the driver for a key index if we don't have one. 211 * Note that entries in the global key table always have 212 * an index; this means it's safe to call this routine 213 * for these entries just to setup the reference to the 214 * cipher template. Note also that when using software 215 * crypto we also call the driver to give us a key index. 216 */ 217 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 218 if (!DEV_KEY_ALLOC(ic, key, &keyix, &rxkeyix)) { 219 /* 220 * Driver has no room; fallback to doing crypto 221 * in the host. We change the flags and start the 222 * procedure over. If we get back here then there's 223 * no hope and we bail. Note that this can leave 224 * the key in a inconsistent state if the caller 225 * continues to use it. 226 */ 227 if ((key->wk_flags & IEEE80211_KEY_SWCRYPT) == 0) { 228 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 229 "crypto_setkey: " 230 "no h/w resources for cipher %s, " 231 "falling back to s/w\n", cip->ic_name); 232 oflags = key->wk_flags; 233 flags |= IEEE80211_KEY_SWCRYPT; 234 if (cipher == IEEE80211_CIPHER_TKIP) 235 flags |= IEEE80211_KEY_SWMIC; 236 goto again; 237 } 238 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "crypto_setkey: " 239 "unable to setup cipher %s\n", cip->ic_name); 240 return (0); 241 } 242 key->wk_keyix = keyix; 243 key->wk_rxkeyix = rxkeyix; 244 } 245 return (1); 246 } 247 248 /* 249 * Remove the key (no locking, for internal use). 250 */ 251 static int 252 ieee80211_crypto_delkey_locked(ieee80211com_t *ic, struct ieee80211_key *key) 253 { 254 uint16_t keyix; 255 256 ASSERT(key->wk_cipher != NULL); 257 258 keyix = key->wk_keyix; 259 if (keyix != IEEE80211_KEYIX_NONE) { 260 /* 261 * Remove hardware entry. 262 */ 263 if (!DEV_KEY_DELETE(ic, key)) { 264 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 265 "ieee80211_crypto_delkey_locked: ", 266 "driverdeletes key %u failed\n", keyix); 267 } 268 } 269 CIPHER_DETACH(key); 270 bzero(key, sizeof (struct ieee80211_key)); 271 /* NB: cannot depend on key index to decide this */ 272 ieee80211_crypto_resetkey(ic, key, IEEE80211_KEYIX_NONE); 273 return (1); 274 } 275 276 /* 277 * Remove the specified key. 278 */ 279 int 280 ieee80211_crypto_delkey(ieee80211com_t *ic, struct ieee80211_key *key) 281 { 282 int status; 283 284 KEY_UPDATE_BEGIN(ic); 285 status = ieee80211_crypto_delkey_locked(ic, key); 286 KEY_UPDATE_END(ic); 287 return (status); 288 } 289 290 /* 291 * Clear the global key table. 292 */ 293 static void 294 ieee80211_crypto_delglobalkeys(ieee80211com_t *ic) 295 { 296 int i; 297 298 KEY_UPDATE_BEGIN(ic); 299 for (i = 0; i < IEEE80211_WEP_NKID; i++) 300 (void) ieee80211_crypto_delkey_locked(ic, &ic->ic_nw_keys[i]); 301 KEY_UPDATE_END(ic); 302 } 303 304 /* 305 * Set the contents of the specified key. 306 * 307 * Locking must be handled by the caller using: 308 * ieee80211_key_update_begin(ic); 309 * ieee80211_key_update_end(ic); 310 */ 311 int 312 ieee80211_crypto_setkey(ieee80211com_t *ic, struct ieee80211_key *key, 313 const uint8_t *macaddr) 314 { 315 const struct ieee80211_cipher *cip = key->wk_cipher; 316 317 ASSERT(cip != NULL); 318 319 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 320 "%s keyix %u flags 0x%x mac %s len %u\n", 321 cip->ic_name, key->wk_keyix, key->wk_flags, 322 ieee80211_macaddr_sprintf(macaddr), key->wk_keylen); 323 324 /* 325 * Give cipher a chance to validate key contents. 326 * should happen before modifying state. 327 */ 328 if (cip->ic_setkey(key) == 0) { 329 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 330 "cipher %s rejected key index %u len %u flags 0x%x\n", 331 cip->ic_name, key->wk_keyix, key->wk_keylen, 332 key->wk_flags); 333 return (0); 334 } 335 if (key->wk_keyix == IEEE80211_KEYIX_NONE) { 336 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_setkey: " 337 "no key index; should not happen!\n"); 338 return (0); 339 } 340 return (DEV_KEY_SET(ic, key, macaddr)); 341 } 342 343 /* 344 * Return the transmit key to use in sending a frame. 345 */ 346 struct ieee80211_key * 347 ieee80211_crypto_getkey(ieee80211com_t *ic) 348 { 349 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE || 350 KEY_UNDEFINED(ic->ic_nw_keys[ic->ic_def_txkey])) 351 return (NULL); 352 return (&ic->ic_nw_keys[ic->ic_def_txkey]); 353 } 354 355 uint8_t 356 ieee80211_crypto_getciphertype(ieee80211com_t *ic) 357 { 358 struct ieee80211_key *key; 359 uint32_t cipher; 360 static const uint8_t ciphermap[] = { 361 WIFI_SEC_WEP, /* IEEE80211_CIPHER_WEP */ 362 WIFI_SEC_WPA, /* IEEE80211_CIPHER_TKIP */ 363 (uint8_t)-1, /* IEEE80211_CIPHER_AES_OCB */ 364 WIFI_SEC_WPA, /* IEEE80211_CIPHER_AES_CCM */ 365 (uint8_t)-1, /* IEEE80211_CIPHER_CKIP */ 366 WIFI_SEC_NONE, /* IEEE80211_CIPHER_NONE */ 367 }; 368 369 if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) 370 return (WIFI_SEC_NONE); 371 372 key = ieee80211_crypto_getkey(ic); 373 if (key == NULL) 374 return (WIFI_SEC_NONE); 375 376 cipher = key->wk_cipher->ic_cipher; 377 ASSERT(cipher < IEEE80211_N(ciphermap)); 378 return (ciphermap[cipher]); 379 } 380 381 /* 382 * Add privacy headers appropriate for the specified key. 383 */ 384 struct ieee80211_key * 385 ieee80211_crypto_encap(ieee80211com_t *ic, mblk_t *mp) 386 { 387 struct ieee80211_key *k; 388 const struct ieee80211_cipher *cip; 389 uint8_t keyix; 390 391 if (ic->ic_def_txkey == IEEE80211_KEYIX_NONE) { 392 ieee80211_dbg(IEEE80211_MSG_CRYPTO, 393 "ieee80211_crypto_encap: %s", 394 " No default xmit key for frame\n"); 395 return (NULL); 396 } 397 keyix = ic->ic_def_txkey; 398 k = &ic->ic_nw_keys[ic->ic_def_txkey]; 399 cip = k->wk_cipher; 400 return (cip->ic_encap(k, mp, keyix<<6) ? k : NULL); 401 } 402 403 /* 404 * Validate and strip privacy headers (and trailer) for a 405 * received frame that has the WEP/Privacy bit set. 406 */ 407 struct ieee80211_key * 408 ieee80211_crypto_decap(ieee80211com_t *ic, mblk_t *mp, int hdrlen) 409 { 410 struct ieee80211_key *k; 411 const struct ieee80211_cipher *cip; 412 uint8_t *ivp; 413 uint8_t keyid; 414 415 /* NB: this minimum size data frame could be bigger */ 416 if ((mp->b_wptr - mp->b_rptr) < IEEE80211_WEP_MINLEN) { 417 ieee80211_dbg(IEEE80211_MSG_CRYPTO, "ieee80211_crypto_decap:" 418 " WEP data frame too short, len %u\n", 419 mp->b_wptr - mp->b_rptr); 420 return (NULL); 421 } 422 /* 423 * Locate the key. If unicast and there is no unicast 424 * key then we fall back to the key id in the header. 425 * This assumes unicast keys are only configured when 426 * the key id in the header is meaningless (typically 0). 427 */ 428 ivp = mp->b_rptr + hdrlen; 429 keyid = ivp[IEEE80211_WEP_IVLEN]; 430 k = &ic->ic_nw_keys[keyid >> 6]; 431 432 /* check to avoid panic when wep is on but key is not set */ 433 if (k->wk_cipher == &ieee80211_cipher_none || 434 k->wk_cipher == NULL) 435 return (NULL); 436 437 cip = k->wk_cipher; 438 return ((cip->ic_decap)(k, mp, hdrlen) ? k : NULL); 439 } 440 441 /* 442 * Setup crypto support. 443 */ 444 void 445 ieee80211_crypto_attach(ieee80211com_t *ic) 446 { 447 struct ieee80211_crypto_state *cs = &ic->ic_crypto; 448 int i; 449 450 (void) crypto_mech2id(SUN_CKM_RC4); /* Load RC4 */ 451 (void) crypto_mech2id(SUN_CKM_AES_CBC); /* Load AES-CBC */ 452 (void) crypto_mech2id(SUN_CKM_AES_CCM); /* Load AES-CCM */ 453 454 /* NB: we assume everything is pre-zero'd */ 455 cs->cs_def_txkey = IEEE80211_KEYIX_NONE; 456 for (i = 0; i < IEEE80211_WEP_NKID; i++) { 457 ieee80211_crypto_resetkey(ic, &cs->cs_nw_keys[i], 458 IEEE80211_KEYIX_NONE); 459 } 460 461 /* 462 * Initialize the driver key support routines to noop entries. 463 * This is useful especially for the cipher test modules. 464 */ 465 cs->cs_key_alloc = nulldev_key_alloc; 466 cs->cs_key_set = nulldev_key_set; 467 cs->cs_key_delete = nulldev_key_delete; 468 cs->cs_key_update_begin = nulldev_key_update; 469 cs->cs_key_update_end = nulldev_key_update; 470 471 ieee80211_crypto_register(ic, &wep); 472 ieee80211_crypto_register(ic, &tkip); 473 ieee80211_crypto_register(ic, &ccmp); 474 } 475 476 /* 477 * Teardown crypto support. 478 */ 479 void 480 ieee80211_crypto_detach(ieee80211com_t *ic) 481 { 482 ieee80211_crypto_delglobalkeys(ic); 483 484 ieee80211_crypto_unregister(ic, &wep); 485 ieee80211_crypto_unregister(ic, &tkip); 486 ieee80211_crypto_unregister(ic, &ccmp); 487 } 488 489 /* 490 * Register a crypto cipher module. 491 */ 492 void 493 ieee80211_crypto_register(ieee80211com_t *ic, 494 const struct ieee80211_cipher *cip) 495 { 496 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 497 ieee80211_err("ieee80211_crypto_register: " 498 "cipher %s has an invalid cipher index %u\n", 499 cip->ic_name, cip->ic_cipher); 500 return; 501 } 502 if (ic->ic_ciphers[cip->ic_cipher] != NULL && 503 ic->ic_ciphers[cip->ic_cipher] != cip) { 504 ieee80211_err("ieee80211_crypto_register: " 505 "cipher %s registered with a different template\n", 506 cip->ic_name); 507 return; 508 } 509 ic->ic_ciphers[cip->ic_cipher] = cip; 510 } 511 512 /* 513 * Unregister a crypto cipher module. 514 */ 515 void 516 ieee80211_crypto_unregister(ieee80211com_t *ic, 517 const struct ieee80211_cipher *cip) 518 { 519 if (cip->ic_cipher >= IEEE80211_CIPHER_MAX) { 520 ieee80211_err("ieee80211_crypto_unregister: " 521 "cipher %s has an invalid cipher index %u\n", 522 cip->ic_name, cip->ic_cipher); 523 return; 524 } 525 if (ic->ic_ciphers[cip->ic_cipher] != NULL && 526 ic->ic_ciphers[cip->ic_cipher] != cip) { 527 ieee80211_err("ieee80211_crypto_unregister: " 528 "cipher %s registered with a different template\n", 529 cip->ic_name); 530 return; 531 } 532 /* NB: don't complain about not being registered */ 533 ic->ic_ciphers[cip->ic_cipher] = NULL; 534 } 535