2 * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA
20 FILE_LICENCE ( GPL2_OR_LATER
);
22 #include <ipxe/net80211.h>
23 #include <ipxe/sec80211.h>
25 #include <ipxe/eapol.h>
26 #include <ipxe/crypto.h>
27 #include <ipxe/arc4.h>
28 #include <ipxe/crc32.h>
29 #include <ipxe/sha1.h>
30 #include <ipxe/hmac.h>
31 #include <ipxe/list.h>
32 #include <ipxe/ethernet.h>
41 * Handler for the aspects of WPA handshaking that are independent of
42 * 802.1X/PSK or TKIP/CCMP; this mostly involves the 4-Way Handshake.
45 /** List of WPA contexts in active use. */
46 struct list_head wpa_contexts
= LIST_HEAD_INIT ( wpa_contexts
);
50 * Return an error code and deauthenticate
52 * @v ctx WPA common context
53 * @v rc Return status code
54 * @ret rc The passed return status code
56 static int wpa_fail ( struct wpa_common_ctx
*ctx
, int rc
)
58 net80211_deauthenticate ( ctx
->dev
, rc
);
64 * Find a cryptosystem handler structure from a crypto ID
66 * @v crypt Cryptosystem ID
67 * @ret crypto Cryptosystem handler structure
69 * If support for @a crypt is not compiled in to iPXE, or if @a crypt
70 * is NET80211_CRYPT_UNKNOWN, returns @c NULL.
72 static struct net80211_crypto
*
73 wpa_find_cryptosystem ( enum net80211_crypto_alg crypt
)
75 struct net80211_crypto
*crypto
;
77 for_each_table_entry ( crypto
, NET80211_CRYPTOS
) {
78 if ( crypto
->algorithm
== crypt
)
87 * Find WPA key integrity and encryption handler from key version field
89 * @v ver Version bits of EAPOL-Key info field
90 * @ret kie Key integrity and encryption handler
92 struct wpa_kie
* wpa_find_kie ( int version
)
96 for_each_table_entry ( kie
, WPA_KIES
) {
97 if ( kie
->version
== version
)
106 * Construct RSN or WPA information element
108 * @v dev 802.11 device
109 * @ret ie_ret RSN or WPA information element
110 * @ret rc Return status code
112 * This function allocates, fills, and returns a RSN or WPA
113 * information element suitable for including in an association
114 * request frame to the network identified by @c dev->associating.
115 * If it is impossible to construct an information element consistent
116 * with iPXE's capabilities that is compatible with that network, or
117 * if none should be sent because that network's beacon included no
118 * security information, returns an error indication and leaves
119 * @a ie_ret unchanged.
121 * The returned IE will be of the same type (RSN or WPA) as was
122 * included in the beacon for the network it is destined for.
124 int wpa_make_rsn_ie ( struct net80211_device
*dev
, union ieee80211_ie
**ie_ret
)
129 enum net80211_crypto_alg gcrypt
;
132 struct ieee80211_ie_rsn
*ie
;
133 struct ieee80211_frame
*hdr
;
134 struct ieee80211_beacon
*beacon
;
136 if ( ! dev
->associating
) {
137 DBG ( "WPA: Can't make RSN IE for a non-associating device\n" );
141 hdr
= dev
->associating
->beacon
->data
;
142 beacon
= ( struct ieee80211_beacon
* ) hdr
->data
;
143 rsn
= sec80211_find_rsn ( beacon
->info_element
,
144 dev
->associating
->beacon
->tail
, &is_rsn
,
147 DBG ( "WPA: Can't make RSN IE when we didn't get one\n" );
151 rsn
+= 2; /* skip version */
152 group_cipher
= *( u32
* ) rsn
;
153 gcrypt
= sec80211_rsn_get_net80211_crypt ( group_cipher
);
155 if ( ! wpa_find_cryptosystem ( gcrypt
) ||
156 ! wpa_find_cryptosystem ( dev
->associating
->crypto
) ) {
157 DBG ( "WPA: No support for (GC:%d, PC:%d)\n",
158 gcrypt
, dev
->associating
->crypto
);
162 /* Everything looks good - make our IE. */
164 /* WPA IEs need 4 more bytes for the OUI+type */
165 ie_len
= ieee80211_rsn_size ( 1, 1, 0, is_rsn
) + ( 4 * ! is_rsn
);
166 iep
= malloc ( ie_len
);
170 *ie_ret
= ( union ieee80211_ie
* ) iep
;
172 /* Store ID and length bytes. */
173 *iep
++ = ( is_rsn ? IEEE80211_IE_RSN
: IEEE80211_IE_VENDOR
);
176 /* Store OUI+type for WPA IEs. */
178 *( u32
* ) iep
= IEEE80211_WPA_OUI_VEN
;
182 /* If this is a WPA IE, the id and len bytes in the
183 ieee80211_ie_rsn structure will not be valid, but by doing
184 the cast we can fill all the other fields much more
187 ie
= ( struct ieee80211_ie_rsn
* ) ( iep
- 2 );
188 ie
->version
= IEEE80211_RSN_VERSION
;
189 ie
->group_cipher
= group_cipher
;
190 ie
->pairwise_count
= 1;
191 ie
->pairwise_cipher
[0] =
192 sec80211_rsn_get_crypto_desc ( dev
->associating
->crypto
,
196 sec80211_rsn_get_akm_desc ( dev
->associating
->handshaking
,
208 * Set up generic WPA support to handle 4-Way Handshake
210 * @v dev 802.11 device
211 * @v ctx WPA common context
212 * @v pmk Pairwise Master Key to use for session
213 * @v pmk_len Length of PMK, almost always 32
214 * @ret rc Return status code
216 int wpa_start ( struct net80211_device
*dev
, struct wpa_common_ctx
*ctx
,
217 const void *pmk
, size_t pmk_len
)
219 struct io_buffer
*iob
;
220 struct ieee80211_frame
*hdr
;
221 struct ieee80211_beacon
*beacon
;
222 u8
*ap_rsn_ie
= NULL
, *ap_rsn_ie_end
;
224 if ( ! dev
->rsn_ie
|| ! dev
->associating
)
228 memcpy ( ctx
->pmk
, pmk
, ctx
->pmk_len
= pmk_len
);
229 ctx
->state
= WPA_READY
;
232 iob
= dev
->associating
->beacon
;
234 beacon
= ( struct ieee80211_beacon
* ) hdr
->data
;
235 ap_rsn_ie
= sec80211_find_rsn ( beacon
->info_element
, iob
->tail
,
236 &ctx
->ap_rsn_is_rsn
, &ap_rsn_ie_end
);
238 ctx
->ap_rsn_ie
= malloc ( ap_rsn_ie_end
- ap_rsn_ie
);
239 if ( ! ctx
->ap_rsn_ie
)
241 memcpy ( ctx
->ap_rsn_ie
, ap_rsn_ie
, ap_rsn_ie_end
- ap_rsn_ie
);
242 ctx
->ap_rsn_ie_len
= ap_rsn_ie_end
- ap_rsn_ie
;
247 ctx
->crypt
= dev
->associating
->crypto
;
248 ctx
->gcrypt
= NET80211_CRYPT_UNKNOWN
;
250 list_add_tail ( &ctx
->list
, &wpa_contexts
);
256 * Disable handling of received WPA handshake frames
258 * @v dev 802.11 device
260 void wpa_stop ( struct net80211_device
*dev
)
262 struct wpa_common_ctx
*ctx
, *tmp
;
264 list_for_each_entry_safe ( ctx
, tmp
, &wpa_contexts
, list
) {
265 if ( ctx
->dev
== dev
) {
266 free ( ctx
->ap_rsn_ie
);
267 ctx
->ap_rsn_ie
= NULL
;
268 list_del ( &ctx
->list
);
275 * Derive pairwise transient key
277 * @v ctx WPA common context
279 static void wpa_derive_ptk ( struct wpa_common_ctx
*ctx
)
284 u8 nonce1
[WPA_NONCE_LEN
];
285 u8 nonce2
[WPA_NONCE_LEN
];
286 } __attribute__ (( packed
)) ptk_data
;
288 /* The addresses and nonces are stored in numerical order (!) */
290 if ( memcmp ( ctx
->dev
->netdev
->ll_addr
, ctx
->dev
->bssid
,
292 memcpy ( ptk_data
.mac1
, ctx
->dev
->netdev
->ll_addr
, ETH_ALEN
);
293 memcpy ( ptk_data
.mac2
, ctx
->dev
->bssid
, ETH_ALEN
);
295 memcpy ( ptk_data
.mac1
, ctx
->dev
->bssid
, ETH_ALEN
);
296 memcpy ( ptk_data
.mac2
, ctx
->dev
->netdev
->ll_addr
, ETH_ALEN
);
299 if ( memcmp ( ctx
->Anonce
, ctx
->Snonce
, WPA_NONCE_LEN
) < 0 ) {
300 memcpy ( ptk_data
.nonce1
, ctx
->Anonce
, WPA_NONCE_LEN
);
301 memcpy ( ptk_data
.nonce2
, ctx
->Snonce
, WPA_NONCE_LEN
);
303 memcpy ( ptk_data
.nonce1
, ctx
->Snonce
, WPA_NONCE_LEN
);
304 memcpy ( ptk_data
.nonce2
, ctx
->Anonce
, WPA_NONCE_LEN
);
307 DBGC2 ( ctx
, "WPA %p A1 %s, A2 %s\n", ctx
, eth_ntoa ( ptk_data
.mac1
),
308 eth_ntoa ( ptk_data
.mac2
) );
309 DBGC2 ( ctx
, "WPA %p Nonce1, Nonce2:\n", ctx
);
310 DBGC2_HD ( ctx
, ptk_data
.nonce1
, WPA_NONCE_LEN
);
311 DBGC2_HD ( ctx
, ptk_data
.nonce2
, WPA_NONCE_LEN
);
313 prf_sha1 ( ctx
->pmk
, ctx
->pmk_len
,
314 "Pairwise key expansion",
315 &ptk_data
, sizeof ( ptk_data
),
316 &ctx
->ptk
, sizeof ( ctx
->ptk
) );
318 DBGC2 ( ctx
, "WPA %p PTK:\n", ctx
);
319 DBGC2_HD ( ctx
, &ctx
->ptk
, sizeof ( ctx
->ptk
) );
324 * Install pairwise transient key
326 * @v ctx WPA common context
327 * @v len Key length (16 for CCMP, 32 for TKIP)
328 * @ret rc Return status code
330 static inline int wpa_install_ptk ( struct wpa_common_ctx
*ctx
, int len
)
332 DBGC ( ctx
, "WPA %p: installing %d-byte pairwise transient key\n",
334 DBGC2_HD ( ctx
, &ctx
->ptk
.tk
, len
);
336 return sec80211_install ( &ctx
->dev
->crypto
, ctx
->crypt
,
337 &ctx
->ptk
.tk
, len
, NULL
);
341 * Install group transient key
343 * @v ctx WPA common context
344 * @v len Key length (16 for CCMP, 32 for TKIP)
345 * @v rsc Receive sequence counter field in EAPOL-Key packet
346 * @ret rc Return status code
348 static inline int wpa_install_gtk ( struct wpa_common_ctx
*ctx
, int len
,
351 DBGC ( ctx
, "WPA %p: installing %d-byte group transient key\n",
353 DBGC2_HD ( ctx
, &ctx
->gtk
.tk
, len
);
355 return sec80211_install ( &ctx
->dev
->gcrypto
, ctx
->gcrypt
,
356 &ctx
->gtk
.tk
, len
, rsc
);
360 * Search for group transient key, and install it if found
362 * @v ctx WPA common context
363 * @v ie Pointer to first IE in key data field
364 * @v ie_end Pointer to first byte not in key data field
365 * @v rsc Receive sequence counter field in EAPOL-Key packet
366 * @ret rc Return status code
368 static int wpa_maybe_install_gtk ( struct wpa_common_ctx
*ctx
,
369 union ieee80211_ie
*ie
, void *ie_end
,
374 if ( ! ieee80211_ie_bound ( ie
, ie_end
) )
378 if ( ie
->id
== IEEE80211_IE_VENDOR
&&
379 ie
->vendor
.oui
== WPA_KDE_GTK
)
382 ie
= ieee80211_next_ie ( ie
, ie_end
);
388 if ( ie
->len
- 6u > sizeof ( ctx
->gtk
.tk
) ) {
389 DBGC ( ctx
, "WPA %p: GTK KDE is too long (%d bytes, max %zd)\n",
390 ctx
, ie
->len
- 4, sizeof ( ctx
->gtk
.tk
) );
394 /* XXX We ignore key ID for now. */
395 kde
= ( struct wpa_kde
* ) ie
;
396 memcpy ( &ctx
->gtk
.tk
, &kde
->gtk_encap
.gtk
, kde
->len
- 6 );
398 return wpa_install_gtk ( ctx
, kde
->len
- 6, rsc
);
403 * Allocate I/O buffer for construction of outgoing EAPOL-Key frame
405 * @v kdlen Maximum number of bytes in the Key Data field
406 * @ret iob Newly allocated I/O buffer
408 * The returned buffer will have space reserved for the link-layer and
409 * EAPOL headers, and will have @c iob->tail pointing to the start of
410 * the Key Data field. Thus, it is necessary to use iob_put() in
411 * filling the Key Data.
413 static struct io_buffer
* wpa_alloc_frame ( int kdlen
)
415 struct io_buffer
*ret
= alloc_iob ( sizeof ( struct eapol_key_pkt
) +
416 kdlen
+ EAPOL_HDR_LEN
+
421 iob_reserve ( ret
, MAX_LL_HEADER_LEN
+ EAPOL_HDR_LEN
);
422 memset ( iob_put ( ret
, sizeof ( struct eapol_key_pkt
) ), 0,
423 sizeof ( struct eapol_key_pkt
) );
430 * Send EAPOL-Key packet
432 * @v iob I/O buffer, with sufficient headroom for headers
433 * @v dev 802.11 device
434 * @v kie Key integrity and encryption handler
435 * @v is_rsn If TRUE, handshake uses new RSN format
436 * @ret rc Return status code
438 * If a KIE is specified, the MIC will be filled in before transmission.
440 static int wpa_send_eapol ( struct io_buffer
*iob
, struct wpa_common_ctx
*ctx
,
441 struct wpa_kie
*kie
)
443 struct eapol_key_pkt
*pkt
= iob
->data
;
444 struct eapol_frame
*eapol
= iob_push ( iob
, EAPOL_HDR_LEN
);
446 pkt
->info
= htons ( pkt
->info
);
447 pkt
->keysize
= htons ( pkt
->keysize
);
448 pkt
->datalen
= htons ( pkt
->datalen
);
449 pkt
->replay
= cpu_to_be64 ( pkt
->replay
);
450 eapol
->version
= EAPOL_THIS_VERSION
;
451 eapol
->type
= EAPOL_TYPE_KEY
;
452 eapol
->length
= htons ( iob
->tail
- iob
->data
- sizeof ( *eapol
) );
454 memset ( pkt
->mic
, 0, sizeof ( pkt
->mic
) );
456 kie
->mic ( &ctx
->ptk
.kck
, eapol
, EAPOL_HDR_LEN
+
457 sizeof ( *pkt
) + ntohs ( pkt
->datalen
),
460 return net_tx ( iob
, ctx
->dev
->netdev
, &eapol_protocol
,
461 ctx
->dev
->bssid
, ctx
->dev
->netdev
->ll_addr
);
466 * Send second frame in 4-Way Handshake
468 * @v ctx WPA common context
469 * @v pkt First frame, to which this is a reply
470 * @v is_rsn If TRUE, handshake uses new RSN format
471 * @v kie Key integrity and encryption handler
472 * @ret rc Return status code
474 static int wpa_send_2_of_4 ( struct wpa_common_ctx
*ctx
,
475 struct eapol_key_pkt
*pkt
, int is_rsn
,
476 struct wpa_kie
*kie
)
478 struct io_buffer
*iob
= wpa_alloc_frame ( ctx
->dev
->rsn_ie
->len
+ 2 );
479 struct eapol_key_pkt
*npkt
;
485 memcpy ( npkt
, pkt
, sizeof ( *pkt
) );
486 npkt
->info
&= ~EAPOL_KEY_INFO_KEY_ACK
;
487 npkt
->info
|= EAPOL_KEY_INFO_KEY_MIC
;
490 memcpy ( npkt
->nonce
, ctx
->Snonce
, sizeof ( npkt
->nonce
) );
491 npkt
->datalen
= ctx
->dev
->rsn_ie
->len
+ 2;
492 memcpy ( iob_put ( iob
, npkt
->datalen
), ctx
->dev
->rsn_ie
,
495 DBGC ( ctx
, "WPA %p: sending 2/4\n", ctx
);
497 return wpa_send_eapol ( iob
, ctx
, kie
);
502 * Handle receipt of first frame in 4-Way Handshake
504 * @v ctx WPA common context
505 * @v pkt EAPOL-Key packet
506 * @v is_rsn If TRUE, frame uses new RSN format
507 * @v kie Key integrity and encryption handler
508 * @ret rc Return status code
510 static int wpa_handle_1_of_4 ( struct wpa_common_ctx
*ctx
,
511 struct eapol_key_pkt
*pkt
, int is_rsn
,
512 struct wpa_kie
*kie
)
514 if ( ctx
->state
== WPA_WAITING
)
517 ctx
->state
= WPA_WORKING
;
518 memcpy ( ctx
->Anonce
, pkt
->nonce
, sizeof ( ctx
->Anonce
) );
519 if ( ! ctx
->have_Snonce
) {
520 rbg_generate ( NULL
, 0, 0, ctx
->Snonce
,
521 sizeof ( ctx
->Snonce
) );
522 ctx
->have_Snonce
= 1;
525 DBGC ( ctx
, "WPA %p: received 1/4, looks OK\n", ctx
);
527 wpa_derive_ptk ( ctx
);
529 return wpa_send_2_of_4 ( ctx
, pkt
, is_rsn
, kie
);
534 * Send fourth frame in 4-Way Handshake, or second in Group Key Handshake
536 * @v ctx WPA common context
537 * @v pkt EAPOL-Key packet for frame to which we're replying
538 * @v is_rsn If TRUE, frame uses new RSN format
539 * @v kie Key integrity and encryption handler
540 * @ret rc Return status code
542 static int wpa_send_final ( struct wpa_common_ctx
*ctx
,
543 struct eapol_key_pkt
*pkt
, int is_rsn
,
544 struct wpa_kie
*kie
)
546 struct io_buffer
*iob
= wpa_alloc_frame ( 0 );
547 struct eapol_key_pkt
*npkt
;
553 memcpy ( npkt
, pkt
, sizeof ( *pkt
) );
554 npkt
->info
&= ~( EAPOL_KEY_INFO_KEY_ACK
| EAPOL_KEY_INFO_INSTALL
|
555 EAPOL_KEY_INFO_KEY_ENC
);
558 memset ( npkt
->nonce
, 0, sizeof ( npkt
->nonce
) );
559 memset ( npkt
->iv
, 0, sizeof ( npkt
->iv
) );
562 if ( npkt
->info
& EAPOL_KEY_INFO_TYPE
)
563 DBGC ( ctx
, "WPA %p: sending 4/4\n", ctx
);
565 DBGC ( ctx
, "WPA %p: sending 2/2\n", ctx
);
567 return wpa_send_eapol ( iob
, ctx
, kie
);
573 * Handle receipt of third frame in 4-Way Handshake
575 * @v ctx WPA common context
576 * @v pkt EAPOL-Key packet
577 * @v is_rsn If TRUE, frame uses new RSN format
578 * @v kie Key integrity and encryption handler
579 * @ret rc Return status code
581 static int wpa_handle_3_of_4 ( struct wpa_common_ctx
*ctx
,
582 struct eapol_key_pkt
*pkt
, int is_rsn
,
583 struct wpa_kie
*kie
)
586 u8
*this_rsn
, *this_rsn_end
;
587 u8
*new_rsn
, *new_rsn_end
;
588 int this_is_rsn
, new_is_rsn
;
590 if ( ctx
->state
== WPA_WAITING
)
593 ctx
->state
= WPA_WORKING
;
596 if ( memcmp ( ctx
->Anonce
, pkt
->nonce
, WPA_NONCE_LEN
) != 0 ) {
597 DBGC ( ctx
, "WPA %p ALERT: nonce mismatch in 3/4\n", ctx
);
598 return wpa_fail ( ctx
, -EACCES
);
602 this_rsn
= sec80211_find_rsn ( ( union ieee80211_ie
* ) pkt
->data
,
603 pkt
->data
+ pkt
->datalen
,
604 &this_is_rsn
, &this_rsn_end
);
606 new_rsn
= sec80211_find_rsn ( ( union ieee80211_ie
* )
608 pkt
->data
+ pkt
->datalen
,
609 &new_is_rsn
, &new_rsn_end
);
613 if ( ! ctx
->ap_rsn_ie
|| ! this_rsn
||
614 ctx
->ap_rsn_ie_len
!= ( this_rsn_end
- this_rsn
) ||
615 ctx
->ap_rsn_is_rsn
!= this_is_rsn
||
616 memcmp ( ctx
->ap_rsn_ie
, this_rsn
, ctx
->ap_rsn_ie_len
) != 0 ) {
617 DBGC ( ctx
, "WPA %p ALERT: RSN mismatch in 3/4\n", ctx
);
618 DBGC2 ( ctx
, "WPA %p RSNs (in 3/4, in beacon):\n", ctx
);
619 DBGC2_HD ( ctx
, this_rsn
, this_rsn_end
- this_rsn
);
620 DBGC2_HD ( ctx
, ctx
->ap_rsn_ie
, ctx
->ap_rsn_ie_len
);
621 return wpa_fail ( ctx
, -EACCES
);
624 /* Don't switch if they just supplied both styles of IE
625 simultaneously; we need two RSN IEs or two WPA IEs to
626 switch ciphers. They'll be immediately consecutive because
627 of ordering guarantees. */
628 if ( new_rsn
&& this_is_rsn
== new_is_rsn
) {
629 struct net80211_wlan
*assoc
= ctx
->dev
->associating
;
630 DBGC ( ctx
, "WPA %p: accommodating bait-and-switch tactics\n",
632 DBGC2 ( ctx
, "WPA %p RSNs (in 3/4+beacon, new in 3/4):\n",
634 DBGC2_HD ( ctx
, this_rsn
, this_rsn_end
- this_rsn
);
635 DBGC2_HD ( ctx
, new_rsn
, new_rsn_end
- new_rsn
);
637 if ( ( rc
= sec80211_detect_ie ( new_is_rsn
, new_rsn
,
640 &assoc
->crypto
) ) != 0 )
641 DBGC ( ctx
, "WPA %p: bait-and-switch invalid, staying "
642 "with original request\n", ctx
);
645 new_is_rsn
= this_is_rsn
;
646 new_rsn_end
= this_rsn_end
;
649 /* Grab group cryptosystem ID */
650 ctx
->gcrypt
= sec80211_rsn_get_net80211_crypt ( *( u32
* )
653 /* Check for a GTK, if info field is encrypted */
654 if ( pkt
->info
& EAPOL_KEY_INFO_KEY_ENC
) {
655 rc
= wpa_maybe_install_gtk ( ctx
,
656 ( union ieee80211_ie
* ) pkt
->data
,
657 pkt
->data
+ pkt
->datalen
,
660 DBGC ( ctx
, "WPA %p did not install GTK in 3/4: %s\n",
661 ctx
, strerror ( rc
) );
663 return wpa_fail ( ctx
, rc
);
667 DBGC ( ctx
, "WPA %p: received 3/4, looks OK\n", ctx
);
669 /* Send final message */
670 rc
= wpa_send_final ( ctx
, pkt
, is_rsn
, kie
);
672 return wpa_fail ( ctx
, rc
);
675 rc
= wpa_install_ptk ( ctx
, pkt
->keysize
);
677 DBGC ( ctx
, "WPA %p failed to install PTK: %s\n", ctx
,
679 return wpa_fail ( ctx
, rc
);
682 /* Mark us as needing a new Snonce if we rekey */
683 ctx
->have_Snonce
= 0;
686 ctx
->state
= WPA_SUCCESS
;
692 * Handle receipt of first frame in Group Key Handshake
694 * @v ctx WPA common context
695 * @v pkt EAPOL-Key packet
696 * @v is_rsn If TRUE, frame uses new RSN format
697 * @v kie Key integrity and encryption handler
698 * @ret rc Return status code
700 static int wpa_handle_1_of_2 ( struct wpa_common_ctx
*ctx
,
701 struct eapol_key_pkt
*pkt
, int is_rsn
,
702 struct wpa_kie
*kie
)
707 * WPA and RSN do this completely differently.
709 * The idea of encoding the GTK (or PMKID, or various other
710 * things) into a KDE that looks like an information element
711 * is an RSN innovation; old WPA code never encapsulates
712 * things like that. If it looks like an info element, it
713 * really is (for the WPA IE check in frames 2/4 and 3/4). The
714 * "key data encrypted" bit in the info field is also specific
717 * So from an old WPA host, 3/4 does not contain an
718 * encapsulated GTK. The first frame of the GK handshake
719 * contains it, encrypted, but without a KDE wrapper, and with
720 * the key ID field (which iPXE doesn't use) shoved away in
721 * the reserved bits in the info field, and the TxRx bit
722 * stealing the Install bit's spot.
725 if ( is_rsn
&& ( pkt
->info
& EAPOL_KEY_INFO_KEY_ENC
) ) {
726 rc
= wpa_maybe_install_gtk ( ctx
,
727 ( union ieee80211_ie
* ) pkt
->data
,
728 pkt
->data
+ pkt
->datalen
,
731 DBGC ( ctx
, "WPA %p: failed to install GTK in 1/2: "
732 "%s\n", ctx
, strerror ( rc
) );
733 return wpa_fail ( ctx
, rc
);
736 rc
= kie
->decrypt ( &ctx
->ptk
.kek
, pkt
->iv
, pkt
->data
,
739 DBGC ( ctx
, "WPA %p: failed to decrypt GTK: %s\n",
740 ctx
, strerror ( rc
) );
741 return rc
; /* non-fatal */
743 if ( pkt
->datalen
> sizeof ( ctx
->gtk
.tk
) ) {
744 DBGC ( ctx
, "WPA %p: too much GTK data (%d > %zd)\n",
745 ctx
, pkt
->datalen
, sizeof ( ctx
->gtk
.tk
) );
746 return wpa_fail ( ctx
, -EINVAL
);
749 memcpy ( &ctx
->gtk
.tk
, pkt
->data
, pkt
->datalen
);
750 wpa_install_gtk ( ctx
, pkt
->datalen
, pkt
->rsc
);
753 DBGC ( ctx
, "WPA %p: received 1/2, looks OK\n", ctx
);
755 return wpa_send_final ( ctx
, pkt
, is_rsn
, kie
);
760 * Handle receipt of EAPOL-Key frame for WPA
763 * @v netdev Network device
764 * @v ll_dest Link-layer destination address
765 * @v ll_source Source link-layer address
767 static int eapol_key_rx ( struct io_buffer
*iob
, struct net_device
*netdev
,
768 const void *ll_dest __unused
,
769 const void *ll_source
)
771 struct net80211_device
*dev
= net80211_get ( netdev
);
772 struct eapol_key_pkt
*pkt
= iob
->data
;
773 int is_rsn
, found_ctx
;
774 struct wpa_common_ctx
*ctx
;
777 u8 their_mic
[16], our_mic
[16];
779 if ( pkt
->type
!= EAPOL_KEY_TYPE_WPA
&&
780 pkt
->type
!= EAPOL_KEY_TYPE_RSN
) {
781 DBG ( "EAPOL-Key: packet not of 802.11 type\n" );
786 is_rsn
= ( pkt
->type
== EAPOL_KEY_TYPE_RSN
);
789 DBG ( "EAPOL-Key: packet not from 802.11\n" );
794 if ( memcmp ( dev
->bssid
, ll_source
, ETH_ALEN
) != 0 ) {
795 DBG ( "EAPOL-Key: packet not from associated AP\n" );
800 if ( ! ( ntohs ( pkt
->info
) & EAPOL_KEY_INFO_KEY_ACK
) ) {
801 DBG ( "EAPOL-Key: packet sent in wrong direction\n" );
807 list_for_each_entry ( ctx
, &wpa_contexts
, list
) {
808 if ( ctx
->dev
== dev
) {
815 DBG ( "EAPOL-Key: no WPA context to handle packet for %p\n",
821 if ( ( void * ) ( pkt
+ 1 ) + ntohs ( pkt
->datalen
) > iob
->tail
) {
822 DBGC ( ctx
, "WPA %p: packet truncated (has %zd extra bytes, "
823 "states %d)\n", ctx
, iob
->tail
- ( void * ) ( pkt
+ 1 ),
824 ntohs ( pkt
->datalen
) );
829 /* Get a handle on key integrity/encryption handler */
830 kie
= wpa_find_kie ( ntohs ( pkt
->info
) & EAPOL_KEY_INFO_VERSION
);
832 DBGC ( ctx
, "WPA %p: no support for packet version %d\n", ctx
,
833 ntohs ( pkt
->info
) & EAPOL_KEY_INFO_VERSION
);
834 rc
= wpa_fail ( ctx
, -ENOTSUP
);
839 if ( ntohs ( pkt
->info
) & EAPOL_KEY_INFO_KEY_MIC
) {
840 memcpy ( their_mic
, pkt
->mic
, sizeof ( pkt
->mic
) );
841 memset ( pkt
->mic
, 0, sizeof ( pkt
->mic
) );
842 kie
->mic ( &ctx
->ptk
.kck
, ( void * ) pkt
- EAPOL_HDR_LEN
,
843 EAPOL_HDR_LEN
+ sizeof ( *pkt
) +
844 ntohs ( pkt
->datalen
), our_mic
);
845 DBGC2 ( ctx
, "WPA %p MIC comparison (theirs, ours):\n", ctx
);
846 DBGC2_HD ( ctx
, their_mic
, 16 );
847 DBGC2_HD ( ctx
, our_mic
, 16 );
848 if ( memcmp ( their_mic
, our_mic
, sizeof ( pkt
->mic
) ) != 0 ) {
849 DBGC ( ctx
, "WPA %p: EAPOL MIC failure\n", ctx
);
854 /* Fix byte order to local */
855 pkt
->info
= ntohs ( pkt
->info
);
856 pkt
->keysize
= ntohs ( pkt
->keysize
);
857 pkt
->datalen
= ntohs ( pkt
->datalen
);
858 pkt
->replay
= be64_to_cpu ( pkt
->replay
);
860 /* Check replay counter */
861 if ( ctx
->replay
!= ~0ULL && ctx
->replay
>= pkt
->replay
) {
862 DBGC ( ctx
, "WPA %p ALERT: Replay detected! "
863 "(%08x:%08x >= %08x:%08x)\n", ctx
,
864 ( u32
) ( ctx
->replay
>> 32 ), ( u32
) ctx
->replay
,
865 ( u32
) ( pkt
->replay
>> 32 ), ( u32
) pkt
->replay
);
866 rc
= 0; /* ignore without error */
869 ctx
->replay
= pkt
->replay
;
871 /* Decrypt key data */
872 if ( pkt
->info
& EAPOL_KEY_INFO_KEY_ENC
) {
873 rc
= kie
->decrypt ( &ctx
->ptk
.kek
, pkt
->iv
, pkt
->data
,
876 DBGC ( ctx
, "WPA %p: failed to decrypt packet: %s\n",
877 ctx
, strerror ( rc
) );
882 /* Hand it off to appropriate handler */
883 switch ( pkt
->info
& ( EAPOL_KEY_INFO_TYPE
|
884 EAPOL_KEY_INFO_KEY_MIC
) ) {
885 case EAPOL_KEY_TYPE_PTK
:
886 rc
= wpa_handle_1_of_4 ( ctx
, pkt
, is_rsn
, kie
);
889 case EAPOL_KEY_TYPE_PTK
| EAPOL_KEY_INFO_KEY_MIC
:
890 rc
= wpa_handle_3_of_4 ( ctx
, pkt
, is_rsn
, kie
);
893 case EAPOL_KEY_TYPE_GTK
| EAPOL_KEY_INFO_KEY_MIC
:
894 rc
= wpa_handle_1_of_2 ( ctx
, pkt
, is_rsn
, kie
);
898 DBGC ( ctx
, "WPA %p: Invalid combination of key flags %04x\n",
909 struct eapol_handler eapol_key_handler __eapol_handler
= {
910 .type
= EAPOL_TYPE_KEY
,
914 /* WPA always needs EAPOL in order to be useful */
915 REQUIRING_SYMBOL ( eapol_key_handler
);
916 REQUIRE_OBJECT ( eapol
);