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