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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 FILE_LICENCE ( GPL2_OR_LATER
);
21 #include <gpxe/net80211.h>
22 #include <gpxe/sec80211.h>
24 #include <gpxe/eapol.h>
25 #include <gpxe/crypto.h>
26 #include <gpxe/arc4.h>
27 #include <gpxe/crc32.h>
28 #include <gpxe/sha1.h>
29 #include <gpxe/hmac.h>
30 #include <gpxe/list.h>
31 #include <gpxe/ethernet.h>
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.
42 /** List of WPA contexts in active use. */
43 struct list_head wpa_contexts
= LIST_HEAD_INIT ( wpa_contexts
);
47 * Return an error code and deauthenticate
49 * @v ctx WPA common context
50 * @v rc Return status code
51 * @ret rc The passed return status code
53 static int wpa_fail ( struct wpa_common_ctx
*ctx
, int rc
)
55 net80211_deauthenticate ( ctx
->dev
, rc
);
61 * Find a cryptosystem handler structure from a crypto ID
63 * @v crypt Cryptosystem ID
64 * @ret crypto Cryptosystem handler structure
66 * If support for @a crypt is not compiled in to gPXE, or if @a crypt
67 * is NET80211_CRYPT_UNKNOWN, returns @c NULL.
69 static struct net80211_crypto
*
70 wpa_find_cryptosystem ( enum net80211_crypto_alg crypt
)
72 struct net80211_crypto
*crypto
;
74 for_each_table_entry ( crypto
, NET80211_CRYPTOS
) {
75 if ( crypto
->algorithm
== crypt
)
84 * Find WPA key integrity and encryption handler from key version field
86 * @v ver Version bits of EAPOL-Key info field
87 * @ret kie Key integrity and encryption handler
89 struct wpa_kie
* wpa_find_kie ( int version
)
93 for_each_table_entry ( kie
, WPA_KIES
) {
94 if ( kie
->version
== version
)
103 * Construct RSN or WPA information element
105 * @v dev 802.11 device
106 * @ret ie_ret RSN or WPA information element
107 * @ret rc Return status code
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 gPXE'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.
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.
121 int wpa_make_rsn_ie ( struct net80211_device
*dev
, union ieee80211_ie
**ie_ret
)
126 enum net80211_crypto_alg gcrypt
;
129 struct ieee80211_ie_rsn
*ie
;
130 struct ieee80211_frame
*hdr
;
131 struct ieee80211_beacon
*beacon
;
133 if ( ! dev
->associating
) {
134 DBG ( "WPA: Can't make RSN IE for a non-associating device\n" );
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
,
144 DBG ( "WPA: Can't make RSN IE when we didn't get one\n" );
148 rsn
+= 2; /* skip version */
149 group_cipher
= *( u32
* ) rsn
;
150 gcrypt
= sec80211_rsn_get_net80211_crypt ( group_cipher
);
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
);
159 /* Everything looks good - make our IE. */
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
);
167 *ie_ret
= ( union ieee80211_ie
* ) iep
;
169 /* Store ID and length bytes. */
170 *iep
++ = ( is_rsn
? IEEE80211_IE_RSN
: IEEE80211_IE_VENDOR
);
173 /* Store OUI+type for WPA IEs. */
175 *( u32
* ) iep
= IEEE80211_WPA_OUI_VEN
;
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
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
,
193 sec80211_rsn_get_akm_desc ( dev
->associating
->handshaking
,
205 * Set up generic WPA support to handle 4-Way Handshake
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
213 int wpa_start ( struct net80211_device
*dev
, struct wpa_common_ctx
*ctx
,
214 const void *pmk
, size_t pmk_len
)
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
;
221 if ( ! dev
->rsn_ie
|| ! dev
->associating
)
225 memcpy ( ctx
->pmk
, pmk
, ctx
->pmk_len
= pmk_len
);
226 ctx
->state
= WPA_READY
;
229 iob
= dev
->associating
->beacon
;
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
);
235 ctx
->ap_rsn_ie
= malloc ( ap_rsn_ie_end
- ap_rsn_ie
);
236 if ( ! ctx
->ap_rsn_ie
)
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
;
244 ctx
->crypt
= dev
->associating
->crypto
;
245 ctx
->gcrypt
= NET80211_CRYPT_UNKNOWN
;
247 list_add_tail ( &ctx
->list
, &wpa_contexts
);
253 * Disable handling of received WPA handshake frames
255 * @v dev 802.11 device
257 void wpa_stop ( struct net80211_device
*dev
)
259 struct wpa_common_ctx
*ctx
, *tmp
;
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
);
272 * Derive pairwise transient key
274 * @v ctx WPA common context
276 static void wpa_derive_ptk ( struct wpa_common_ctx
*ctx
)
281 u8 nonce1
[WPA_NONCE_LEN
];
282 u8 nonce2
[WPA_NONCE_LEN
];
283 } __attribute__ (( packed
)) ptk_data
;
285 /* The addresses and nonces are stored in numerical order (!) */
287 if ( memcmp ( ctx
->dev
->netdev
->ll_addr
, ctx
->dev
->bssid
,
289 memcpy ( ptk_data
.mac1
, ctx
->dev
->netdev
->ll_addr
, ETH_ALEN
);
290 memcpy ( ptk_data
.mac2
, ctx
->dev
->bssid
, ETH_ALEN
);
292 memcpy ( ptk_data
.mac1
, ctx
->dev
->bssid
, ETH_ALEN
);
293 memcpy ( ptk_data
.mac2
, ctx
->dev
->netdev
->ll_addr
, ETH_ALEN
);
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
);
300 memcpy ( ptk_data
.nonce1
, ctx
->Snonce
, WPA_NONCE_LEN
);
301 memcpy ( ptk_data
.nonce2
, ctx
->Anonce
, WPA_NONCE_LEN
);
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
);
310 prf_sha1 ( ctx
->pmk
, ctx
->pmk_len
,
311 "Pairwise key expansion",
312 &ptk_data
, sizeof ( ptk_data
),
313 &ctx
->ptk
, sizeof ( ctx
->ptk
) );
315 DBGC2 ( ctx
, "WPA %p PTK:\n", ctx
);
316 DBGC2_HD ( ctx
, &ctx
->ptk
, sizeof ( ctx
->ptk
) );
321 * Install pairwise transient key
323 * @v ctx WPA common context
324 * @v len Key length (16 for CCMP, 32 for TKIP)
325 * @ret rc Return status code
327 static inline int wpa_install_ptk ( struct wpa_common_ctx
*ctx
, int len
)
329 DBGC ( ctx
, "WPA %p: installing %d-byte pairwise transient key\n",
331 DBGC2_HD ( ctx
, &ctx
->ptk
.tk
, len
);
333 return sec80211_install ( &ctx
->dev
->crypto
, ctx
->crypt
,
334 &ctx
->ptk
.tk
, len
, NULL
);
338 * Install group transient key
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
345 static inline int wpa_install_gtk ( struct wpa_common_ctx
*ctx
, int len
,
348 DBGC ( ctx
, "WPA %p: installing %d-byte group transient key\n",
350 DBGC2_HD ( ctx
, &ctx
->gtk
.tk
, len
);
352 return sec80211_install ( &ctx
->dev
->gcrypto
, ctx
->gcrypt
,
353 &ctx
->gtk
.tk
, len
, rsc
);
357 * Search for group transient key, and install it if found
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
365 static int wpa_maybe_install_gtk ( struct wpa_common_ctx
*ctx
,
366 union ieee80211_ie
*ie
, void *ie_end
,
371 if ( ! ieee80211_ie_bound ( ie
, ie_end
) )
375 if ( ie
->id
== IEEE80211_IE_VENDOR
&&
376 ie
->vendor
.oui
== WPA_KDE_GTK
)
379 ie
= ieee80211_next_ie ( ie
, ie_end
);
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
) );
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 );
395 return wpa_install_gtk ( ctx
, kde
->len
- 6, rsc
);
400 * Allocate I/O buffer for construction of outgoing EAPOL-Key frame
402 * @v kdlen Maximum number of bytes in the Key Data field
403 * @ret iob Newly allocated I/O buffer
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.
410 static struct io_buffer
* wpa_alloc_frame ( int kdlen
)
412 struct io_buffer
*ret
= alloc_iob ( sizeof ( struct eapol_key_pkt
) +
413 kdlen
+ EAPOL_HDR_LEN
+
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
) );
427 * Send EAPOL-Key packet
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
435 * If a KIE is specified, the MIC will be filled in before transmission.
437 static int wpa_send_eapol ( struct io_buffer
*iob
, struct wpa_common_ctx
*ctx
,
438 struct wpa_kie
*kie
)
440 struct eapol_key_pkt
*pkt
= iob
->data
;
441 struct eapol_frame
*eapol
= iob_push ( iob
, EAPOL_HDR_LEN
);
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
) );
451 memset ( pkt
->mic
, 0, sizeof ( pkt
->mic
) );
453 kie
->mic ( &ctx
->ptk
.kck
, eapol
, EAPOL_HDR_LEN
+
454 sizeof ( *pkt
) + ntohs ( pkt
->datalen
),
457 return net_tx ( iob
, ctx
->dev
->netdev
, &eapol_protocol
,
463 * Send second frame in 4-Way Handshake
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
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
)
475 struct io_buffer
*iob
= wpa_alloc_frame ( ctx
->dev
->rsn_ie
->len
+ 2 );
476 struct eapol_key_pkt
*npkt
;
482 memcpy ( npkt
, pkt
, sizeof ( *pkt
) );
483 npkt
->info
&= ~EAPOL_KEY_INFO_KEY_ACK
;
484 npkt
->info
|= EAPOL_KEY_INFO_KEY_MIC
;
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
,
492 DBGC ( ctx
, "WPA %p: sending 2/4\n", ctx
);
494 return wpa_send_eapol ( iob
, ctx
, kie
);
499 * Handle receipt of first frame in 4-Way Handshake
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
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
)
511 if ( ctx
->state
== WPA_WAITING
)
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;
521 DBGC ( ctx
, "WPA %p: received 1/4, looks OK\n", ctx
);
523 wpa_derive_ptk ( ctx
);
525 return wpa_send_2_of_4 ( ctx
, pkt
, is_rsn
, kie
);
530 * Send fourth frame in 4-Way Handshake, or second in Group Key Handshake
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
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
)
542 struct io_buffer
*iob
= wpa_alloc_frame ( 0 );
543 struct eapol_key_pkt
*npkt
;
549 memcpy ( npkt
, pkt
, sizeof ( *pkt
) );
550 npkt
->info
&= ~( EAPOL_KEY_INFO_KEY_ACK
| EAPOL_KEY_INFO_INSTALL
|
551 EAPOL_KEY_INFO_KEY_ENC
);
554 memset ( npkt
->nonce
, 0, sizeof ( npkt
->nonce
) );
555 memset ( npkt
->iv
, 0, sizeof ( npkt
->iv
) );
558 if ( npkt
->info
& EAPOL_KEY_INFO_TYPE
)
559 DBGC ( ctx
, "WPA %p: sending 4/4\n", ctx
);
561 DBGC ( ctx
, "WPA %p: sending 2/2\n", ctx
);
563 return wpa_send_eapol ( iob
, ctx
, kie
);
569 * Handle receipt of third frame in 4-Way Handshake
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
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
)
582 u8
*this_rsn
, *this_rsn_end
;
583 u8
*new_rsn
, *new_rsn_end
;
584 int this_is_rsn
, new_is_rsn
;
586 if ( ctx
->state
== WPA_WAITING
)
589 ctx
->state
= WPA_WORKING
;
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
);
598 this_rsn
= sec80211_find_rsn ( ( union ieee80211_ie
* ) pkt
->data
,
599 pkt
->data
+ pkt
->datalen
,
600 &this_is_rsn
, &this_rsn_end
);
602 new_rsn
= sec80211_find_rsn ( ( union ieee80211_ie
* )
604 pkt
->data
+ pkt
->datalen
,
605 &new_is_rsn
, &new_rsn_end
);
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
);
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",
628 DBGC2 ( ctx
, "WPA %p RSNs (in 3/4+beacon, new in 3/4):\n",
630 DBGC2_HD ( ctx
, this_rsn
, this_rsn_end
- this_rsn
);
631 DBGC2_HD ( ctx
, new_rsn
, new_rsn_end
- new_rsn
);
633 if ( ( rc
= sec80211_detect_ie ( new_is_rsn
, new_rsn
,
636 &assoc
->crypto
) ) != 0 )
637 DBGC ( ctx
, "WPA %p: bait-and-switch invalid, staying "
638 "with original request\n", ctx
);
641 new_is_rsn
= this_is_rsn
;
642 new_rsn_end
= this_rsn_end
;
645 /* Grab group cryptosystem ID */
646 ctx
->gcrypt
= sec80211_rsn_get_net80211_crypt ( *( u32
* )
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
,
656 DBGC ( ctx
, "WPA %p did not install GTK in 3/4: %s\n",
657 ctx
, strerror ( rc
) );
659 return wpa_fail ( ctx
, rc
);
663 DBGC ( ctx
, "WPA %p: received 3/4, looks OK\n", ctx
);
665 /* Send final message */
666 rc
= wpa_send_final ( ctx
, pkt
, is_rsn
, kie
);
668 return wpa_fail ( ctx
, rc
);
671 rc
= wpa_install_ptk ( ctx
, pkt
->keysize
);
673 DBGC ( ctx
, "WPA %p failed to install PTK: %s\n", ctx
,
675 return wpa_fail ( ctx
, rc
);
678 /* Mark us as needing a new Snonce if we rekey */
679 ctx
->have_Snonce
= 0;
682 ctx
->state
= WPA_SUCCESS
;
688 * Handle receipt of first frame in Group Key Handshake
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
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
)
703 * WPA and RSN do this completely differently.
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
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 gPXE 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.
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
,
727 DBGC ( ctx
, "WPA %p: failed to install GTK in 1/2: "
728 "%s\n", ctx
, strerror ( rc
) );
729 return wpa_fail ( ctx
, rc
);
732 rc
= kie
->decrypt ( &ctx
->ptk
.kek
, pkt
->iv
, pkt
->data
,
735 DBGC ( ctx
, "WPA %p: failed to decrypt GTK: %s\n",
736 ctx
, strerror ( rc
) );
737 return rc
; /* non-fatal */
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
);
745 memcpy ( &ctx
->gtk
.tk
, pkt
->data
, pkt
->datalen
);
746 wpa_install_gtk ( ctx
, pkt
->datalen
, pkt
->rsc
);
749 DBGC ( ctx
, "WPA %p: received 1/2, looks OK\n", ctx
);
751 return wpa_send_final ( ctx
, pkt
, is_rsn
, kie
);
756 * Handle receipt of EAPOL-Key frame for WPA
759 * @v netdev Network device
760 * @v ll_source Source link-layer address
762 static int eapol_key_rx ( struct io_buffer
*iob
, struct net_device
*netdev
,
763 const void *ll_source
)
765 struct net80211_device
*dev
= net80211_get ( netdev
);
766 struct eapol_key_pkt
*pkt
= iob
->data
;
767 int is_rsn
, found_ctx
;
768 struct wpa_common_ctx
*ctx
;
771 u8 their_mic
[16], our_mic
[16];
773 if ( pkt
->type
!= EAPOL_KEY_TYPE_WPA
&&
774 pkt
->type
!= EAPOL_KEY_TYPE_RSN
) {
775 DBG ( "EAPOL-Key: packet not of 802.11 type\n" );
780 is_rsn
= ( pkt
->type
== EAPOL_KEY_TYPE_RSN
);
783 DBG ( "EAPOL-Key: packet not from 802.11\n" );
788 if ( memcmp ( dev
->bssid
, ll_source
, ETH_ALEN
) != 0 ) {
789 DBG ( "EAPOL-Key: packet not from associated AP\n" );
794 if ( ! ( ntohs ( pkt
->info
) & EAPOL_KEY_INFO_KEY_ACK
) ) {
795 DBG ( "EAPOL-Key: packet sent in wrong direction\n" );
801 list_for_each_entry ( ctx
, &wpa_contexts
, list
) {
802 if ( ctx
->dev
== dev
) {
809 DBG ( "EAPOL-Key: no WPA context to handle packet for %p\n",
815 if ( ( void * ) ( pkt
+ 1 ) + ntohs ( pkt
->datalen
) > iob
->tail
) {
816 DBGC ( ctx
, "WPA %p: packet truncated (has %zd extra bytes, "
817 "states %d)\n", ctx
, iob
->tail
- ( void * ) ( pkt
+ 1 ),
818 ntohs ( pkt
->datalen
) );
823 /* Get a handle on key integrity/encryption handler */
824 kie
= wpa_find_kie ( ntohs ( pkt
->info
) & EAPOL_KEY_INFO_VERSION
);
826 DBGC ( ctx
, "WPA %p: no support for packet version %d\n", ctx
,
827 ntohs ( pkt
->info
) & EAPOL_KEY_INFO_VERSION
);
828 rc
= wpa_fail ( ctx
, -ENOTSUP
);
833 if ( ntohs ( pkt
->info
) & EAPOL_KEY_INFO_KEY_MIC
) {
834 memcpy ( their_mic
, pkt
->mic
, sizeof ( pkt
->mic
) );
835 memset ( pkt
->mic
, 0, sizeof ( pkt
->mic
) );
836 kie
->mic ( &ctx
->ptk
.kck
, ( void * ) pkt
- EAPOL_HDR_LEN
,
837 EAPOL_HDR_LEN
+ sizeof ( *pkt
) +
838 ntohs ( pkt
->datalen
), our_mic
);
839 DBGC2 ( ctx
, "WPA %p MIC comparison (theirs, ours):\n", ctx
);
840 DBGC2_HD ( ctx
, their_mic
, 16 );
841 DBGC2_HD ( ctx
, our_mic
, 16 );
842 if ( memcmp ( their_mic
, our_mic
, sizeof ( pkt
->mic
) ) != 0 ) {
843 DBGC ( ctx
, "WPA %p: EAPOL MIC failure\n", ctx
);
848 /* Fix byte order to local */
849 pkt
->info
= ntohs ( pkt
->info
);
850 pkt
->keysize
= ntohs ( pkt
->keysize
);
851 pkt
->datalen
= ntohs ( pkt
->datalen
);
852 pkt
->replay
= be64_to_cpu ( pkt
->replay
);
854 /* Check replay counter */
855 if ( ctx
->replay
!= ~0ULL && ctx
->replay
>= pkt
->replay
) {
856 DBGC ( ctx
, "WPA %p ALERT: Replay detected! "
857 "(%08x:%08x >= %08x:%08x)\n", ctx
,
858 ( u32
) ( ctx
->replay
>> 32 ), ( u32
) ctx
->replay
,
859 ( u32
) ( pkt
->replay
>> 32 ), ( u32
) pkt
->replay
);
860 rc
= 0; /* ignore without error */
863 ctx
->replay
= pkt
->replay
;
865 /* Decrypt key data */
866 if ( pkt
->info
& EAPOL_KEY_INFO_KEY_ENC
) {
867 rc
= kie
->decrypt ( &ctx
->ptk
.kek
, pkt
->iv
, pkt
->data
,
870 DBGC ( ctx
, "WPA %p: failed to decrypt packet: %s\n",
871 ctx
, strerror ( rc
) );
876 /* Hand it off to appropriate handler */
877 switch ( pkt
->info
& ( EAPOL_KEY_INFO_TYPE
|
878 EAPOL_KEY_INFO_KEY_MIC
) ) {
879 case EAPOL_KEY_TYPE_PTK
:
880 rc
= wpa_handle_1_of_4 ( ctx
, pkt
, is_rsn
, kie
);
883 case EAPOL_KEY_TYPE_PTK
| EAPOL_KEY_INFO_KEY_MIC
:
884 rc
= wpa_handle_3_of_4 ( ctx
, pkt
, is_rsn
, kie
);
887 case EAPOL_KEY_TYPE_GTK
| EAPOL_KEY_INFO_KEY_MIC
:
888 rc
= wpa_handle_1_of_2 ( ctx
, pkt
, is_rsn
, kie
);
892 DBGC ( ctx
, "WPA %p: Invalid combination of key flags %04x\n",
903 struct eapol_handler eapol_key_handler __eapol_handler
= {
904 .type
= EAPOL_TYPE_KEY
,
908 /* WPA always needs EAPOL in order to be useful */
909 REQUIRE_OBJECT ( eapol
);