|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2009 Joshua Oreman <[email protected]>. ! 3: * ! 4: * This program is free software; you can redistribute it and/or ! 5: * modify it under the terms of the GNU General Public License as ! 6: * published by the Free Software Foundation; either version 2 of the ! 7: * License, or any later version. ! 8: * ! 9: * This program is distributed in the hope that it will be useful, but ! 10: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 12: * General Public License for more details. ! 13: * ! 14: * You should have received a copy of the GNU General Public License ! 15: * along with this program; if not, write to the Free Software ! 16: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 17: */ ! 18: ! 19: FILE_LICENCE ( GPL2_OR_LATER ); ! 20: ! 21: #include <ipxe/net80211.h> ! 22: #include <ipxe/sec80211.h> ! 23: #include <ipxe/wpa.h> ! 24: #include <ipxe/eapol.h> ! 25: #include <ipxe/crypto.h> ! 26: #include <ipxe/arc4.h> ! 27: #include <ipxe/crc32.h> ! 28: #include <ipxe/sha1.h> ! 29: #include <ipxe/hmac.h> ! 30: #include <ipxe/list.h> ! 31: #include <ipxe/ethernet.h> ! 32: #include <stdlib.h> ! 33: #include <string.h> ! 34: #include <errno.h> ! 35: ! 36: /** @file ! 37: * ! 38: * Handler for the aspects of WPA handshaking that are independent of ! 39: * 802.1X/PSK or TKIP/CCMP; this mostly involves the 4-Way Handshake. ! 40: */ ! 41: ! 42: /** List of WPA contexts in active use. */ ! 43: struct list_head wpa_contexts = LIST_HEAD_INIT ( wpa_contexts ); ! 44: ! 45: ! 46: /** ! 47: * Return an error code and deauthenticate ! 48: * ! 49: * @v ctx WPA common context ! 50: * @v rc Return status code ! 51: * @ret rc The passed return status code ! 52: */ ! 53: static int wpa_fail ( struct wpa_common_ctx *ctx, int rc ) ! 54: { ! 55: net80211_deauthenticate ( ctx->dev, rc ); ! 56: return rc; ! 57: } ! 58: ! 59: ! 60: /** ! 61: * Find a cryptosystem handler structure from a crypto ID ! 62: * ! 63: * @v crypt Cryptosystem ID ! 64: * @ret crypto Cryptosystem handler structure ! 65: * ! 66: * If support for @a crypt is not compiled in to iPXE, or if @a crypt ! 67: * is NET80211_CRYPT_UNKNOWN, returns @c NULL. ! 68: */ ! 69: static struct net80211_crypto * ! 70: wpa_find_cryptosystem ( enum net80211_crypto_alg crypt ) ! 71: { ! 72: struct net80211_crypto *crypto; ! 73: ! 74: for_each_table_entry ( crypto, NET80211_CRYPTOS ) { ! 75: if ( crypto->algorithm == crypt ) ! 76: return crypto; ! 77: } ! 78: ! 79: return NULL; ! 80: } ! 81: ! 82: ! 83: /** ! 84: * Find WPA key integrity and encryption handler from key version field ! 85: * ! 86: * @v ver Version bits of EAPOL-Key info field ! 87: * @ret kie Key integrity and encryption handler ! 88: */ ! 89: struct wpa_kie * wpa_find_kie ( int version ) ! 90: { ! 91: struct wpa_kie *kie; ! 92: ! 93: for_each_table_entry ( kie, WPA_KIES ) { ! 94: if ( kie->version == version ) ! 95: return kie; ! 96: } ! 97: ! 98: return NULL; ! 99: } ! 100: ! 101: ! 102: /** ! 103: * Construct RSN or WPA information element ! 104: * ! 105: * @v dev 802.11 device ! 106: * @ret ie_ret RSN or WPA information element ! 107: * @ret rc Return status code ! 108: * ! 109: * This function allocates, fills, and returns a RSN or WPA ! 110: * information element suitable for including in an association ! 111: * request frame to the network identified by @c dev->associating. ! 112: * If it is impossible to construct an information element consistent ! 113: * with iPXE's capabilities that is compatible with that network, or ! 114: * if none should be sent because that network's beacon included no ! 115: * security information, returns an error indication and leaves ! 116: * @a ie_ret unchanged. ! 117: * ! 118: * The returned IE will be of the same type (RSN or WPA) as was ! 119: * included in the beacon for the network it is destined for. ! 120: */ ! 121: int wpa_make_rsn_ie ( struct net80211_device *dev, union ieee80211_ie **ie_ret ) ! 122: { ! 123: u8 *rsn, *rsn_end; ! 124: int is_rsn; ! 125: u32 group_cipher; ! 126: enum net80211_crypto_alg gcrypt; ! 127: int ie_len; ! 128: u8 *iep; ! 129: struct ieee80211_ie_rsn *ie; ! 130: struct ieee80211_frame *hdr; ! 131: struct ieee80211_beacon *beacon; ! 132: ! 133: if ( ! dev->associating ) { ! 134: DBG ( "WPA: Can't make RSN IE for a non-associating device\n" ); ! 135: return -EINVAL; ! 136: } ! 137: ! 138: hdr = dev->associating->beacon->data; ! 139: beacon = ( struct ieee80211_beacon * ) hdr->data; ! 140: rsn = sec80211_find_rsn ( beacon->info_element, ! 141: dev->associating->beacon->tail, &is_rsn, ! 142: &rsn_end ); ! 143: if ( ! rsn ) { ! 144: DBG ( "WPA: Can't make RSN IE when we didn't get one\n" ); ! 145: return -EINVAL; ! 146: } ! 147: ! 148: rsn += 2; /* skip version */ ! 149: group_cipher = *( u32 * ) rsn; ! 150: gcrypt = sec80211_rsn_get_net80211_crypt ( group_cipher ); ! 151: ! 152: if ( ! wpa_find_cryptosystem ( gcrypt ) || ! 153: ! wpa_find_cryptosystem ( dev->associating->crypto ) ) { ! 154: DBG ( "WPA: No support for (GC:%d, PC:%d)\n", ! 155: gcrypt, dev->associating->crypto ); ! 156: return -ENOTSUP; ! 157: } ! 158: ! 159: /* Everything looks good - make our IE. */ ! 160: ! 161: /* WPA IEs need 4 more bytes for the OUI+type */ ! 162: ie_len = ieee80211_rsn_size ( 1, 1, 0, is_rsn ) + ( 4 * ! is_rsn ); ! 163: iep = malloc ( ie_len ); ! 164: if ( ! iep ) ! 165: return -ENOMEM; ! 166: ! 167: *ie_ret = ( union ieee80211_ie * ) iep; ! 168: ! 169: /* Store ID and length bytes. */ ! 170: *iep++ = ( is_rsn ? IEEE80211_IE_RSN : IEEE80211_IE_VENDOR ); ! 171: *iep++ = ie_len - 2; ! 172: ! 173: /* Store OUI+type for WPA IEs. */ ! 174: if ( ! is_rsn ) { ! 175: *( u32 * ) iep = IEEE80211_WPA_OUI_VEN; ! 176: iep += 4; ! 177: } ! 178: ! 179: /* If this is a WPA IE, the id and len bytes in the ! 180: ieee80211_ie_rsn structure will not be valid, but by doing ! 181: the cast we can fill all the other fields much more ! 182: readily. */ ! 183: ! 184: ie = ( struct ieee80211_ie_rsn * ) ( iep - 2 ); ! 185: ie->version = IEEE80211_RSN_VERSION; ! 186: ie->group_cipher = group_cipher; ! 187: ie->pairwise_count = 1; ! 188: ie->pairwise_cipher[0] = ! 189: sec80211_rsn_get_crypto_desc ( dev->associating->crypto, ! 190: is_rsn ); ! 191: ie->akm_count = 1; ! 192: ie->akm_list[0] = ! 193: sec80211_rsn_get_akm_desc ( dev->associating->handshaking, ! 194: is_rsn ); ! 195: if ( is_rsn ) { ! 196: ie->rsn_capab = 0; ! 197: ie->pmkid_count = 0; ! 198: } ! 199: ! 200: return 0; ! 201: } ! 202: ! 203: ! 204: /** ! 205: * Set up generic WPA support to handle 4-Way Handshake ! 206: * ! 207: * @v dev 802.11 device ! 208: * @v ctx WPA common context ! 209: * @v pmk Pairwise Master Key to use for session ! 210: * @v pmk_len Length of PMK, almost always 32 ! 211: * @ret rc Return status code ! 212: */ ! 213: int wpa_start ( struct net80211_device *dev, struct wpa_common_ctx *ctx, ! 214: const void *pmk, size_t pmk_len ) ! 215: { ! 216: struct io_buffer *iob; ! 217: struct ieee80211_frame *hdr; ! 218: struct ieee80211_beacon *beacon; ! 219: u8 *ap_rsn_ie = NULL, *ap_rsn_ie_end; ! 220: ! 221: if ( ! dev->rsn_ie || ! dev->associating ) ! 222: return -EINVAL; ! 223: ! 224: ctx->dev = dev; ! 225: memcpy ( ctx->pmk, pmk, ctx->pmk_len = pmk_len ); ! 226: ctx->state = WPA_READY; ! 227: ctx->replay = ~0ULL; ! 228: ! 229: iob = dev->associating->beacon; ! 230: hdr = iob->data; ! 231: beacon = ( struct ieee80211_beacon * ) hdr->data; ! 232: ap_rsn_ie = sec80211_find_rsn ( beacon->info_element, iob->tail, ! 233: &ctx->ap_rsn_is_rsn, &ap_rsn_ie_end ); ! 234: if ( ap_rsn_ie ) { ! 235: ctx->ap_rsn_ie = malloc ( ap_rsn_ie_end - ap_rsn_ie ); ! 236: if ( ! ctx->ap_rsn_ie ) ! 237: return -ENOMEM; ! 238: memcpy ( ctx->ap_rsn_ie, ap_rsn_ie, ap_rsn_ie_end - ap_rsn_ie ); ! 239: ctx->ap_rsn_ie_len = ap_rsn_ie_end - ap_rsn_ie; ! 240: } else { ! 241: return -ENOENT; ! 242: } ! 243: ! 244: ctx->crypt = dev->associating->crypto; ! 245: ctx->gcrypt = NET80211_CRYPT_UNKNOWN; ! 246: ! 247: list_add_tail ( &ctx->list, &wpa_contexts ); ! 248: return 0; ! 249: } ! 250: ! 251: ! 252: /** ! 253: * Disable handling of received WPA handshake frames ! 254: * ! 255: * @v dev 802.11 device ! 256: */ ! 257: void wpa_stop ( struct net80211_device *dev ) ! 258: { ! 259: struct wpa_common_ctx *ctx, *tmp; ! 260: ! 261: list_for_each_entry_safe ( ctx, tmp, &wpa_contexts, list ) { ! 262: if ( ctx->dev == dev ) { ! 263: free ( ctx->ap_rsn_ie ); ! 264: ctx->ap_rsn_ie = NULL; ! 265: list_del ( &ctx->list ); ! 266: } ! 267: } ! 268: } ! 269: ! 270: ! 271: /** ! 272: * Derive pairwise transient key ! 273: * ! 274: * @v ctx WPA common context ! 275: */ ! 276: static void wpa_derive_ptk ( struct wpa_common_ctx *ctx ) ! 277: { ! 278: struct { ! 279: u8 mac1[ETH_ALEN]; ! 280: u8 mac2[ETH_ALEN]; ! 281: u8 nonce1[WPA_NONCE_LEN]; ! 282: u8 nonce2[WPA_NONCE_LEN]; ! 283: } __attribute__ (( packed )) ptk_data; ! 284: ! 285: /* The addresses and nonces are stored in numerical order (!) */ ! 286: ! 287: if ( memcmp ( ctx->dev->netdev->ll_addr, ctx->dev->bssid, ! 288: ETH_ALEN ) < 0 ) { ! 289: memcpy ( ptk_data.mac1, ctx->dev->netdev->ll_addr, ETH_ALEN ); ! 290: memcpy ( ptk_data.mac2, ctx->dev->bssid, ETH_ALEN ); ! 291: } else { ! 292: memcpy ( ptk_data.mac1, ctx->dev->bssid, ETH_ALEN ); ! 293: memcpy ( ptk_data.mac2, ctx->dev->netdev->ll_addr, ETH_ALEN ); ! 294: } ! 295: ! 296: if ( memcmp ( ctx->Anonce, ctx->Snonce, WPA_NONCE_LEN ) < 0 ) { ! 297: memcpy ( ptk_data.nonce1, ctx->Anonce, WPA_NONCE_LEN ); ! 298: memcpy ( ptk_data.nonce2, ctx->Snonce, WPA_NONCE_LEN ); ! 299: } else { ! 300: memcpy ( ptk_data.nonce1, ctx->Snonce, WPA_NONCE_LEN ); ! 301: memcpy ( ptk_data.nonce2, ctx->Anonce, WPA_NONCE_LEN ); ! 302: } ! 303: ! 304: DBGC2 ( ctx, "WPA %p A1 %s, A2 %s\n", ctx, eth_ntoa ( ptk_data.mac1 ), ! 305: eth_ntoa ( ptk_data.mac2 ) ); ! 306: DBGC2 ( ctx, "WPA %p Nonce1, Nonce2:\n", ctx ); ! 307: DBGC2_HD ( ctx, ptk_data.nonce1, WPA_NONCE_LEN ); ! 308: DBGC2_HD ( ctx, ptk_data.nonce2, WPA_NONCE_LEN ); ! 309: ! 310: prf_sha1 ( ctx->pmk, ctx->pmk_len, ! 311: "Pairwise key expansion", ! 312: &ptk_data, sizeof ( ptk_data ), ! 313: &ctx->ptk, sizeof ( ctx->ptk ) ); ! 314: ! 315: DBGC2 ( ctx, "WPA %p PTK:\n", ctx ); ! 316: DBGC2_HD ( ctx, &ctx->ptk, sizeof ( ctx->ptk ) ); ! 317: } ! 318: ! 319: ! 320: /** ! 321: * Install pairwise transient key ! 322: * ! 323: * @v ctx WPA common context ! 324: * @v len Key length (16 for CCMP, 32 for TKIP) ! 325: * @ret rc Return status code ! 326: */ ! 327: static inline int wpa_install_ptk ( struct wpa_common_ctx *ctx, int len ) ! 328: { ! 329: DBGC ( ctx, "WPA %p: installing %d-byte pairwise transient key\n", ! 330: ctx, len ); ! 331: DBGC2_HD ( ctx, &ctx->ptk.tk, len ); ! 332: ! 333: return sec80211_install ( &ctx->dev->crypto, ctx->crypt, ! 334: &ctx->ptk.tk, len, NULL ); ! 335: } ! 336: ! 337: /** ! 338: * Install group transient key ! 339: * ! 340: * @v ctx WPA common context ! 341: * @v len Key length (16 for CCMP, 32 for TKIP) ! 342: * @v rsc Receive sequence counter field in EAPOL-Key packet ! 343: * @ret rc Return status code ! 344: */ ! 345: static inline int wpa_install_gtk ( struct wpa_common_ctx *ctx, int len, ! 346: const void *rsc ) ! 347: { ! 348: DBGC ( ctx, "WPA %p: installing %d-byte group transient key\n", ! 349: ctx, len ); ! 350: DBGC2_HD ( ctx, &ctx->gtk.tk, len ); ! 351: ! 352: return sec80211_install ( &ctx->dev->gcrypto, ctx->gcrypt, ! 353: &ctx->gtk.tk, len, rsc ); ! 354: } ! 355: ! 356: /** ! 357: * Search for group transient key, and install it if found ! 358: * ! 359: * @v ctx WPA common context ! 360: * @v ie Pointer to first IE in key data field ! 361: * @v ie_end Pointer to first byte not in key data field ! 362: * @v rsc Receive sequence counter field in EAPOL-Key packet ! 363: * @ret rc Return status code ! 364: */ ! 365: static int wpa_maybe_install_gtk ( struct wpa_common_ctx *ctx, ! 366: union ieee80211_ie *ie, void *ie_end, ! 367: const void *rsc ) ! 368: { ! 369: struct wpa_kde *kde; ! 370: ! 371: if ( ! ieee80211_ie_bound ( ie, ie_end ) ) ! 372: return -ENOENT; ! 373: ! 374: while ( ie ) { ! 375: if ( ie->id == IEEE80211_IE_VENDOR && ! 376: ie->vendor.oui == WPA_KDE_GTK ) ! 377: break; ! 378: ! 379: ie = ieee80211_next_ie ( ie, ie_end ); ! 380: } ! 381: ! 382: if ( ! ie ) ! 383: return -ENOENT; ! 384: ! 385: if ( ie->len - 6u > sizeof ( ctx->gtk.tk ) ) { ! 386: DBGC ( ctx, "WPA %p: GTK KDE is too long (%d bytes, max %zd)\n", ! 387: ctx, ie->len - 4, sizeof ( ctx->gtk.tk ) ); ! 388: return -EINVAL; ! 389: } ! 390: ! 391: /* XXX We ignore key ID for now. */ ! 392: kde = ( struct wpa_kde * ) ie; ! 393: memcpy ( &ctx->gtk.tk, &kde->gtk_encap.gtk, kde->len - 6 ); ! 394: ! 395: return wpa_install_gtk ( ctx, kde->len - 6, rsc ); ! 396: } ! 397: ! 398: ! 399: /** ! 400: * Allocate I/O buffer for construction of outgoing EAPOL-Key frame ! 401: * ! 402: * @v kdlen Maximum number of bytes in the Key Data field ! 403: * @ret iob Newly allocated I/O buffer ! 404: * ! 405: * The returned buffer will have space reserved for the link-layer and ! 406: * EAPOL headers, and will have @c iob->tail pointing to the start of ! 407: * the Key Data field. Thus, it is necessary to use iob_put() in ! 408: * filling the Key Data. ! 409: */ ! 410: static struct io_buffer * wpa_alloc_frame ( int kdlen ) ! 411: { ! 412: struct io_buffer *ret = alloc_iob ( sizeof ( struct eapol_key_pkt ) + ! 413: kdlen + EAPOL_HDR_LEN + ! 414: MAX_LL_HEADER_LEN ); ! 415: if ( ! ret ) ! 416: return NULL; ! 417: ! 418: iob_reserve ( ret, MAX_LL_HEADER_LEN + EAPOL_HDR_LEN ); ! 419: memset ( iob_put ( ret, sizeof ( struct eapol_key_pkt ) ), 0, ! 420: sizeof ( struct eapol_key_pkt ) ); ! 421: ! 422: return ret; ! 423: } ! 424: ! 425: ! 426: /** ! 427: * Send EAPOL-Key packet ! 428: * ! 429: * @v iob I/O buffer, with sufficient headroom for headers ! 430: * @v dev 802.11 device ! 431: * @v kie Key integrity and encryption handler ! 432: * @v is_rsn If TRUE, handshake uses new RSN format ! 433: * @ret rc Return status code ! 434: * ! 435: * If a KIE is specified, the MIC will be filled in before transmission. ! 436: */ ! 437: static int wpa_send_eapol ( struct io_buffer *iob, struct wpa_common_ctx *ctx, ! 438: struct wpa_kie *kie ) ! 439: { ! 440: struct eapol_key_pkt *pkt = iob->data; ! 441: struct eapol_frame *eapol = iob_push ( iob, EAPOL_HDR_LEN ); ! 442: ! 443: pkt->info = htons ( pkt->info ); ! 444: pkt->keysize = htons ( pkt->keysize ); ! 445: pkt->datalen = htons ( pkt->datalen ); ! 446: pkt->replay = cpu_to_be64 ( pkt->replay ); ! 447: eapol->version = EAPOL_THIS_VERSION; ! 448: eapol->type = EAPOL_TYPE_KEY; ! 449: eapol->length = htons ( iob->tail - iob->data - sizeof ( *eapol ) ); ! 450: ! 451: memset ( pkt->mic, 0, sizeof ( pkt->mic ) ); ! 452: if ( kie ) ! 453: kie->mic ( &ctx->ptk.kck, eapol, EAPOL_HDR_LEN + ! 454: sizeof ( *pkt ) + ntohs ( pkt->datalen ), ! 455: pkt->mic ); ! 456: ! 457: return net_tx ( iob, ctx->dev->netdev, &eapol_protocol, ! 458: ctx->dev->bssid, ctx->dev->netdev->ll_addr ); ! 459: } ! 460: ! 461: ! 462: /** ! 463: * Send second frame in 4-Way Handshake ! 464: * ! 465: * @v ctx WPA common context ! 466: * @v pkt First frame, to which this is a reply ! 467: * @v is_rsn If TRUE, handshake uses new RSN format ! 468: * @v kie Key integrity and encryption handler ! 469: * @ret rc Return status code ! 470: */ ! 471: static int wpa_send_2_of_4 ( struct wpa_common_ctx *ctx, ! 472: struct eapol_key_pkt *pkt, int is_rsn, ! 473: struct wpa_kie *kie ) ! 474: { ! 475: struct io_buffer *iob = wpa_alloc_frame ( ctx->dev->rsn_ie->len + 2 ); ! 476: struct eapol_key_pkt *npkt; ! 477: ! 478: if ( ! iob ) ! 479: return -ENOMEM; ! 480: ! 481: npkt = iob->data; ! 482: memcpy ( npkt, pkt, sizeof ( *pkt ) ); ! 483: npkt->info &= ~EAPOL_KEY_INFO_KEY_ACK; ! 484: npkt->info |= EAPOL_KEY_INFO_KEY_MIC; ! 485: if ( is_rsn ) ! 486: npkt->keysize = 0; ! 487: memcpy ( npkt->nonce, ctx->Snonce, sizeof ( npkt->nonce ) ); ! 488: npkt->datalen = ctx->dev->rsn_ie->len + 2; ! 489: memcpy ( iob_put ( iob, npkt->datalen ), ctx->dev->rsn_ie, ! 490: npkt->datalen ); ! 491: ! 492: DBGC ( ctx, "WPA %p: sending 2/4\n", ctx ); ! 493: ! 494: return wpa_send_eapol ( iob, ctx, kie ); ! 495: } ! 496: ! 497: ! 498: /** ! 499: * Handle receipt of first frame in 4-Way Handshake ! 500: * ! 501: * @v ctx WPA common context ! 502: * @v pkt EAPOL-Key packet ! 503: * @v is_rsn If TRUE, frame uses new RSN format ! 504: * @v kie Key integrity and encryption handler ! 505: * @ret rc Return status code ! 506: */ ! 507: static int wpa_handle_1_of_4 ( struct wpa_common_ctx *ctx, ! 508: struct eapol_key_pkt *pkt, int is_rsn, ! 509: struct wpa_kie *kie ) ! 510: { ! 511: if ( ctx->state == WPA_WAITING ) ! 512: return -EINVAL; ! 513: ! 514: ctx->state = WPA_WORKING; ! 515: memcpy ( ctx->Anonce, pkt->nonce, sizeof ( ctx->Anonce ) ); ! 516: if ( ! ctx->have_Snonce ) { ! 517: get_random_bytes ( ctx->Snonce, sizeof ( ctx->Snonce ) ); ! 518: ctx->have_Snonce = 1; ! 519: } ! 520: ! 521: DBGC ( ctx, "WPA %p: received 1/4, looks OK\n", ctx ); ! 522: ! 523: wpa_derive_ptk ( ctx ); ! 524: ! 525: return wpa_send_2_of_4 ( ctx, pkt, is_rsn, kie ); ! 526: } ! 527: ! 528: ! 529: /** ! 530: * Send fourth frame in 4-Way Handshake, or second in Group Key Handshake ! 531: * ! 532: * @v ctx WPA common context ! 533: * @v pkt EAPOL-Key packet for frame to which we're replying ! 534: * @v is_rsn If TRUE, frame uses new RSN format ! 535: * @v kie Key integrity and encryption handler ! 536: * @ret rc Return status code ! 537: */ ! 538: static int wpa_send_final ( struct wpa_common_ctx *ctx, ! 539: struct eapol_key_pkt *pkt, int is_rsn, ! 540: struct wpa_kie *kie ) ! 541: { ! 542: struct io_buffer *iob = wpa_alloc_frame ( 0 ); ! 543: struct eapol_key_pkt *npkt; ! 544: ! 545: if ( ! iob ) ! 546: return -ENOMEM; ! 547: ! 548: npkt = iob->data; ! 549: memcpy ( npkt, pkt, sizeof ( *pkt ) ); ! 550: npkt->info &= ~( EAPOL_KEY_INFO_KEY_ACK | EAPOL_KEY_INFO_INSTALL | ! 551: EAPOL_KEY_INFO_KEY_ENC ); ! 552: if ( is_rsn ) ! 553: npkt->keysize = 0; ! 554: memset ( npkt->nonce, 0, sizeof ( npkt->nonce ) ); ! 555: memset ( npkt->iv, 0, sizeof ( npkt->iv ) ); ! 556: npkt->datalen = 0; ! 557: ! 558: if ( npkt->info & EAPOL_KEY_INFO_TYPE ) ! 559: DBGC ( ctx, "WPA %p: sending 4/4\n", ctx ); ! 560: else ! 561: DBGC ( ctx, "WPA %p: sending 2/2\n", ctx ); ! 562: ! 563: return wpa_send_eapol ( iob, ctx, kie ); ! 564: ! 565: } ! 566: ! 567: ! 568: /** ! 569: * Handle receipt of third frame in 4-Way Handshake ! 570: * ! 571: * @v ctx WPA common context ! 572: * @v pkt EAPOL-Key packet ! 573: * @v is_rsn If TRUE, frame uses new RSN format ! 574: * @v kie Key integrity and encryption handler ! 575: * @ret rc Return status code ! 576: */ ! 577: static int wpa_handle_3_of_4 ( struct wpa_common_ctx *ctx, ! 578: struct eapol_key_pkt *pkt, int is_rsn, ! 579: struct wpa_kie *kie ) ! 580: { ! 581: int rc; ! 582: u8 *this_rsn, *this_rsn_end; ! 583: u8 *new_rsn, *new_rsn_end; ! 584: int this_is_rsn, new_is_rsn; ! 585: ! 586: if ( ctx->state == WPA_WAITING ) ! 587: return -EINVAL; ! 588: ! 589: ctx->state = WPA_WORKING; ! 590: ! 591: /* Check nonce */ ! 592: if ( memcmp ( ctx->Anonce, pkt->nonce, WPA_NONCE_LEN ) != 0 ) { ! 593: DBGC ( ctx, "WPA %p ALERT: nonce mismatch in 3/4\n", ctx ); ! 594: return wpa_fail ( ctx, -EACCES ); ! 595: } ! 596: ! 597: /* Check RSN IE */ ! 598: this_rsn = sec80211_find_rsn ( ( union ieee80211_ie * ) pkt->data, ! 599: pkt->data + pkt->datalen, ! 600: &this_is_rsn, &this_rsn_end ); ! 601: if ( this_rsn ) ! 602: new_rsn = sec80211_find_rsn ( ( union ieee80211_ie * ) ! 603: this_rsn_end, ! 604: pkt->data + pkt->datalen, ! 605: &new_is_rsn, &new_rsn_end ); ! 606: else ! 607: new_rsn = NULL; ! 608: ! 609: if ( ! ctx->ap_rsn_ie || ! this_rsn || ! 610: ctx->ap_rsn_ie_len != ( this_rsn_end - this_rsn ) || ! 611: ctx->ap_rsn_is_rsn != this_is_rsn || ! 612: memcmp ( ctx->ap_rsn_ie, this_rsn, ctx->ap_rsn_ie_len ) != 0 ) { ! 613: DBGC ( ctx, "WPA %p ALERT: RSN mismatch in 3/4\n", ctx ); ! 614: DBGC2 ( ctx, "WPA %p RSNs (in 3/4, in beacon):\n", ctx ); ! 615: DBGC2_HD ( ctx, this_rsn, this_rsn_end - this_rsn ); ! 616: DBGC2_HD ( ctx, ctx->ap_rsn_ie, ctx->ap_rsn_ie_len ); ! 617: return wpa_fail ( ctx, -EACCES ); ! 618: } ! 619: ! 620: /* Don't switch if they just supplied both styles of IE ! 621: simultaneously; we need two RSN IEs or two WPA IEs to ! 622: switch ciphers. They'll be immediately consecutive because ! 623: of ordering guarantees. */ ! 624: if ( new_rsn && this_is_rsn == new_is_rsn ) { ! 625: struct net80211_wlan *assoc = ctx->dev->associating; ! 626: DBGC ( ctx, "WPA %p: accommodating bait-and-switch tactics\n", ! 627: ctx ); ! 628: DBGC2 ( ctx, "WPA %p RSNs (in 3/4+beacon, new in 3/4):\n", ! 629: ctx ); ! 630: DBGC2_HD ( ctx, this_rsn, this_rsn_end - this_rsn ); ! 631: DBGC2_HD ( ctx, new_rsn, new_rsn_end - new_rsn ); ! 632: ! 633: if ( ( rc = sec80211_detect_ie ( new_is_rsn, new_rsn, ! 634: new_rsn_end, ! 635: &assoc->handshaking, ! 636: &assoc->crypto ) ) != 0 ) ! 637: DBGC ( ctx, "WPA %p: bait-and-switch invalid, staying " ! 638: "with original request\n", ctx ); ! 639: } else { ! 640: new_rsn = this_rsn; ! 641: new_is_rsn = this_is_rsn; ! 642: new_rsn_end = this_rsn_end; ! 643: } ! 644: ! 645: /* Grab group cryptosystem ID */ ! 646: ctx->gcrypt = sec80211_rsn_get_net80211_crypt ( *( u32 * ) ! 647: ( new_rsn + 2 ) ); ! 648: ! 649: /* Check for a GTK, if info field is encrypted */ ! 650: if ( pkt->info & EAPOL_KEY_INFO_KEY_ENC ) { ! 651: rc = wpa_maybe_install_gtk ( ctx, ! 652: ( union ieee80211_ie * ) pkt->data, ! 653: pkt->data + pkt->datalen, ! 654: pkt->rsc ); ! 655: if ( rc < 0 ) { ! 656: DBGC ( ctx, "WPA %p did not install GTK in 3/4: %s\n", ! 657: ctx, strerror ( rc ) ); ! 658: if ( rc != -ENOENT ) ! 659: return wpa_fail ( ctx, rc ); ! 660: } ! 661: } ! 662: ! 663: DBGC ( ctx, "WPA %p: received 3/4, looks OK\n", ctx ); ! 664: ! 665: /* Send final message */ ! 666: rc = wpa_send_final ( ctx, pkt, is_rsn, kie ); ! 667: if ( rc < 0 ) ! 668: return wpa_fail ( ctx, rc ); ! 669: ! 670: /* Install PTK */ ! 671: rc = wpa_install_ptk ( ctx, pkt->keysize ); ! 672: if ( rc < 0 ) { ! 673: DBGC ( ctx, "WPA %p failed to install PTK: %s\n", ctx, ! 674: strerror ( rc ) ); ! 675: return wpa_fail ( ctx, rc ); ! 676: } ! 677: ! 678: /* Mark us as needing a new Snonce if we rekey */ ! 679: ctx->have_Snonce = 0; ! 680: ! 681: /* Done! */ ! 682: ctx->state = WPA_SUCCESS; ! 683: return 0; ! 684: } ! 685: ! 686: ! 687: /** ! 688: * Handle receipt of first frame in Group Key Handshake ! 689: * ! 690: * @v ctx WPA common context ! 691: * @v pkt EAPOL-Key packet ! 692: * @v is_rsn If TRUE, frame uses new RSN format ! 693: * @v kie Key integrity and encryption handler ! 694: * @ret rc Return status code ! 695: */ ! 696: static int wpa_handle_1_of_2 ( struct wpa_common_ctx *ctx, ! 697: struct eapol_key_pkt *pkt, int is_rsn, ! 698: struct wpa_kie *kie ) ! 699: { ! 700: int rc; ! 701: ! 702: /* ! 703: * WPA and RSN do this completely differently. ! 704: * ! 705: * The idea of encoding the GTK (or PMKID, or various other ! 706: * things) into a KDE that looks like an information element ! 707: * is an RSN innovation; old WPA code never encapsulates ! 708: * things like that. If it looks like an info element, it ! 709: * really is (for the WPA IE check in frames 2/4 and 3/4). The ! 710: * "key data encrypted" bit in the info field is also specific ! 711: * to RSN. ! 712: * ! 713: * So from an old WPA host, 3/4 does not contain an ! 714: * encapsulated GTK. The first frame of the GK handshake ! 715: * contains it, encrypted, but without a KDE wrapper, and with ! 716: * the key ID field (which iPXE doesn't use) shoved away in ! 717: * the reserved bits in the info field, and the TxRx bit ! 718: * stealing the Install bit's spot. ! 719: */ ! 720: ! 721: if ( is_rsn && ( pkt->info & EAPOL_KEY_INFO_KEY_ENC ) ) { ! 722: rc = wpa_maybe_install_gtk ( ctx, ! 723: ( union ieee80211_ie * ) pkt->data, ! 724: pkt->data + pkt->datalen, ! 725: pkt->rsc ); ! 726: if ( rc < 0 ) { ! 727: DBGC ( ctx, "WPA %p: failed to install GTK in 1/2: " ! 728: "%s\n", ctx, strerror ( rc ) ); ! 729: return wpa_fail ( ctx, rc ); ! 730: } ! 731: } else { ! 732: rc = kie->decrypt ( &ctx->ptk.kek, pkt->iv, pkt->data, ! 733: &pkt->datalen ); ! 734: if ( rc < 0 ) { ! 735: DBGC ( ctx, "WPA %p: failed to decrypt GTK: %s\n", ! 736: ctx, strerror ( rc ) ); ! 737: return rc; /* non-fatal */ ! 738: } ! 739: if ( pkt->datalen > sizeof ( ctx->gtk.tk ) ) { ! 740: DBGC ( ctx, "WPA %p: too much GTK data (%d > %zd)\n", ! 741: ctx, pkt->datalen, sizeof ( ctx->gtk.tk ) ); ! 742: return wpa_fail ( ctx, -EINVAL ); ! 743: } ! 744: ! 745: memcpy ( &ctx->gtk.tk, pkt->data, pkt->datalen ); ! 746: wpa_install_gtk ( ctx, pkt->datalen, pkt->rsc ); ! 747: } ! 748: ! 749: DBGC ( ctx, "WPA %p: received 1/2, looks OK\n", ctx ); ! 750: ! 751: return wpa_send_final ( ctx, pkt, is_rsn, kie ); ! 752: } ! 753: ! 754: ! 755: /** ! 756: * Handle receipt of EAPOL-Key frame for WPA ! 757: * ! 758: * @v iob I/O buffer ! 759: * @v netdev Network device ! 760: * @v ll_dest Link-layer destination address ! 761: * @v ll_source Source link-layer address ! 762: */ ! 763: static int eapol_key_rx ( struct io_buffer *iob, struct net_device *netdev, ! 764: const void *ll_dest __unused, ! 765: const void *ll_source ) ! 766: { ! 767: struct net80211_device *dev = net80211_get ( netdev ); ! 768: struct eapol_key_pkt *pkt = iob->data; ! 769: int is_rsn, found_ctx; ! 770: struct wpa_common_ctx *ctx; ! 771: int rc = 0; ! 772: struct wpa_kie *kie; ! 773: u8 their_mic[16], our_mic[16]; ! 774: ! 775: if ( pkt->type != EAPOL_KEY_TYPE_WPA && ! 776: pkt->type != EAPOL_KEY_TYPE_RSN ) { ! 777: DBG ( "EAPOL-Key: packet not of 802.11 type\n" ); ! 778: rc = -EINVAL; ! 779: goto drop; ! 780: } ! 781: ! 782: is_rsn = ( pkt->type == EAPOL_KEY_TYPE_RSN ); ! 783: ! 784: if ( ! dev ) { ! 785: DBG ( "EAPOL-Key: packet not from 802.11\n" ); ! 786: rc = -EINVAL; ! 787: goto drop; ! 788: } ! 789: ! 790: if ( memcmp ( dev->bssid, ll_source, ETH_ALEN ) != 0 ) { ! 791: DBG ( "EAPOL-Key: packet not from associated AP\n" ); ! 792: rc = -EINVAL; ! 793: goto drop; ! 794: } ! 795: ! 796: if ( ! ( ntohs ( pkt->info ) & EAPOL_KEY_INFO_KEY_ACK ) ) { ! 797: DBG ( "EAPOL-Key: packet sent in wrong direction\n" ); ! 798: rc = -EINVAL; ! 799: goto drop; ! 800: } ! 801: ! 802: found_ctx = 0; ! 803: list_for_each_entry ( ctx, &wpa_contexts, list ) { ! 804: if ( ctx->dev == dev ) { ! 805: found_ctx = 1; ! 806: break; ! 807: } ! 808: } ! 809: ! 810: if ( ! found_ctx ) { ! 811: DBG ( "EAPOL-Key: no WPA context to handle packet for %p\n", ! 812: dev ); ! 813: rc = -ENOENT; ! 814: goto drop; ! 815: } ! 816: ! 817: if ( ( void * ) ( pkt + 1 ) + ntohs ( pkt->datalen ) > iob->tail ) { ! 818: DBGC ( ctx, "WPA %p: packet truncated (has %zd extra bytes, " ! 819: "states %d)\n", ctx, iob->tail - ( void * ) ( pkt + 1 ), ! 820: ntohs ( pkt->datalen ) ); ! 821: rc = -EINVAL; ! 822: goto drop; ! 823: } ! 824: ! 825: /* Get a handle on key integrity/encryption handler */ ! 826: kie = wpa_find_kie ( ntohs ( pkt->info ) & EAPOL_KEY_INFO_VERSION ); ! 827: if ( ! kie ) { ! 828: DBGC ( ctx, "WPA %p: no support for packet version %d\n", ctx, ! 829: ntohs ( pkt->info ) & EAPOL_KEY_INFO_VERSION ); ! 830: rc = wpa_fail ( ctx, -ENOTSUP ); ! 831: goto drop; ! 832: } ! 833: ! 834: /* Check MIC */ ! 835: if ( ntohs ( pkt->info ) & EAPOL_KEY_INFO_KEY_MIC ) { ! 836: memcpy ( their_mic, pkt->mic, sizeof ( pkt->mic ) ); ! 837: memset ( pkt->mic, 0, sizeof ( pkt->mic ) ); ! 838: kie->mic ( &ctx->ptk.kck, ( void * ) pkt - EAPOL_HDR_LEN, ! 839: EAPOL_HDR_LEN + sizeof ( *pkt ) + ! 840: ntohs ( pkt->datalen ), our_mic ); ! 841: DBGC2 ( ctx, "WPA %p MIC comparison (theirs, ours):\n", ctx ); ! 842: DBGC2_HD ( ctx, their_mic, 16 ); ! 843: DBGC2_HD ( ctx, our_mic, 16 ); ! 844: if ( memcmp ( their_mic, our_mic, sizeof ( pkt->mic ) ) != 0 ) { ! 845: DBGC ( ctx, "WPA %p: EAPOL MIC failure\n", ctx ); ! 846: goto drop; ! 847: } ! 848: } ! 849: ! 850: /* Fix byte order to local */ ! 851: pkt->info = ntohs ( pkt->info ); ! 852: pkt->keysize = ntohs ( pkt->keysize ); ! 853: pkt->datalen = ntohs ( pkt->datalen ); ! 854: pkt->replay = be64_to_cpu ( pkt->replay ); ! 855: ! 856: /* Check replay counter */ ! 857: if ( ctx->replay != ~0ULL && ctx->replay >= pkt->replay ) { ! 858: DBGC ( ctx, "WPA %p ALERT: Replay detected! " ! 859: "(%08x:%08x >= %08x:%08x)\n", ctx, ! 860: ( u32 ) ( ctx->replay >> 32 ), ( u32 ) ctx->replay, ! 861: ( u32 ) ( pkt->replay >> 32 ), ( u32 ) pkt->replay ); ! 862: rc = 0; /* ignore without error */ ! 863: goto drop; ! 864: } ! 865: ctx->replay = pkt->replay; ! 866: ! 867: /* Decrypt key data */ ! 868: if ( pkt->info & EAPOL_KEY_INFO_KEY_ENC ) { ! 869: rc = kie->decrypt ( &ctx->ptk.kek, pkt->iv, pkt->data, ! 870: &pkt->datalen ); ! 871: if ( rc < 0 ) { ! 872: DBGC ( ctx, "WPA %p: failed to decrypt packet: %s\n", ! 873: ctx, strerror ( rc ) ); ! 874: goto drop; ! 875: } ! 876: } ! 877: ! 878: /* Hand it off to appropriate handler */ ! 879: switch ( pkt->info & ( EAPOL_KEY_INFO_TYPE | ! 880: EAPOL_KEY_INFO_KEY_MIC ) ) { ! 881: case EAPOL_KEY_TYPE_PTK: ! 882: rc = wpa_handle_1_of_4 ( ctx, pkt, is_rsn, kie ); ! 883: break; ! 884: ! 885: case EAPOL_KEY_TYPE_PTK | EAPOL_KEY_INFO_KEY_MIC: ! 886: rc = wpa_handle_3_of_4 ( ctx, pkt, is_rsn, kie ); ! 887: break; ! 888: ! 889: case EAPOL_KEY_TYPE_GTK | EAPOL_KEY_INFO_KEY_MIC: ! 890: rc = wpa_handle_1_of_2 ( ctx, pkt, is_rsn, kie ); ! 891: break; ! 892: ! 893: default: ! 894: DBGC ( ctx, "WPA %p: Invalid combination of key flags %04x\n", ! 895: ctx, pkt->info ); ! 896: rc = -EINVAL; ! 897: break; ! 898: } ! 899: ! 900: drop: ! 901: free_iob ( iob ); ! 902: return rc; ! 903: } ! 904: ! 905: struct eapol_handler eapol_key_handler __eapol_handler = { ! 906: .type = EAPOL_TYPE_KEY, ! 907: .rx = eapol_key_rx, ! 908: }; ! 909: ! 910: /* WPA always needs EAPOL in order to be useful */ ! 911: REQUIRE_OBJECT ( eapol );
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.