Annotation of qemu/roms/ipxe/src/net/80211/wpa.c, revision 1.1.1.1

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 );

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.