iPXE
wpa.c File Reference

Handler for the aspects of WPA handshaking that are independent of 802.1X/PSK or TKIP/CCMP; this mostly involves the 4-Way Handshake. More...

#include <ipxe/net80211.h>
#include <ipxe/sec80211.h>
#include <ipxe/wpa.h>
#include <ipxe/eapol.h>
#include <ipxe/crypto.h>
#include <ipxe/arc4.h>
#include <ipxe/crc32.h>
#include <ipxe/sha1.h>
#include <ipxe/hmac.h>
#include <ipxe/list.h>
#include <ipxe/ethernet.h>
#include <ipxe/rbg.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FILE_SECBOOT (FORBIDDEN)
static int wpa_fail (struct wpa_common_ctx *ctx, int rc)
 Return an error code and deauthenticate.
static struct net80211_cryptowpa_find_cryptosystem (enum net80211_crypto_alg crypt)
 Find a cryptosystem handler structure from a crypto ID.
struct wpa_kiewpa_find_kie (int version)
 Find WPA key integrity and encryption handler from key version field.
int wpa_make_rsn_ie (struct net80211_device *dev, union ieee80211_ie **ie_ret)
 Construct RSN or WPA information element.
int wpa_start (struct net80211_device *dev, struct wpa_common_ctx *ctx, const void *pmk, size_t pmk_len)
 Set up generic WPA support to handle 4-Way Handshake.
void wpa_stop (struct net80211_device *dev)
 Disable handling of received WPA handshake frames.
static void wpa_derive_ptk (struct wpa_common_ctx *ctx)
 Derive pairwise transient key.
static int wpa_install_ptk (struct wpa_common_ctx *ctx, int len)
 Install pairwise transient key.
static int wpa_install_gtk (struct wpa_common_ctx *ctx, int len, const void *rsc)
 Install group transient key.
static int wpa_maybe_install_gtk (struct wpa_common_ctx *ctx, union ieee80211_ie *ie, void *ie_end, const void *rsc)
 Search for group transient key, and install it if found.
static struct io_bufferwpa_alloc_frame (int kdlen)
 Allocate I/O buffer for construction of outgoing EAPOL-Key frame.
static int wpa_send_eapol (struct io_buffer *iob, struct wpa_common_ctx *ctx, struct wpa_kie *kie)
 Send EAPOL-Key packet.
static int wpa_send_2_of_4 (struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
 Send second frame in 4-Way Handshake.
static int wpa_handle_1_of_4 (struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
 Handle receipt of first frame in 4-Way Handshake.
static int wpa_send_final (struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
 Send fourth frame in 4-Way Handshake, or second in Group Key Handshake.
static int wpa_handle_3_of_4 (struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
 Handle receipt of third frame in 4-Way Handshake.
static int wpa_handle_1_of_2 (struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
 Handle receipt of first frame in Group Key Handshake.
static int eapol_key_rx (struct eapol_supplicant *supplicant, struct io_buffer *iob, const void *ll_source)
 Handle receipt of EAPOL-Key frame for WPA.
 REQUIRING_SYMBOL (eapol_key_handler)
 REQUIRE_OBJECT (eapol)

Variables

struct list_head wpa_contexts = LIST_HEAD_INIT ( wpa_contexts )
 List of WPA contexts in active use.
struct eapol_handler eapol_key_handler __eapol_handler

Detailed Description

Handler for the aspects of WPA handshaking that are independent of 802.1X/PSK or TKIP/CCMP; this mostly involves the 4-Way Handshake.

Definition in file wpa.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER )

◆ FILE_SECBOOT()

FILE_SECBOOT ( FORBIDDEN )

◆ wpa_fail()

int wpa_fail ( struct wpa_common_ctx * ctx,
int rc )
static

Return an error code and deauthenticate.

Parameters
ctxWPA common context
rcReturn status code
Return values
rcThe passed return status code

Definition at line 57 of file wpa.c.

58{
60 return rc;
61}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
void net80211_deauthenticate(struct net80211_device *dev, int rc)
Deauthenticate from current network and try again.
Definition net80211.c:2391

References ctx, net80211_deauthenticate(), and rc.

Referenced by eapol_key_rx(), wpa_handle_1_of_2(), and wpa_handle_3_of_4().

◆ wpa_find_cryptosystem()

struct net80211_crypto * wpa_find_cryptosystem ( enum net80211_crypto_alg crypt)
static

Find a cryptosystem handler structure from a crypto ID.

Parameters
cryptCryptosystem ID
Return values
cryptoCryptosystem handler structure

If support for crypt is not compiled in to iPXE, or if crypt is NET80211_CRYPT_UNKNOWN, returns NULL.

Definition at line 74 of file wpa.c.

75{
76 struct net80211_crypto *crypto;
77
79 if ( crypto->algorithm == crypt )
80 return crypto;
81 }
82
83 return NULL;
84}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define NET80211_CRYPTOS
Definition net80211.h:769
Interface to an 802.11 cryptosystem.
Definition net80211.h:690
enum net80211_crypto_alg algorithm
The cryptographic algorithm implemented.
Definition net80211.h:692
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386

References net80211_crypto::algorithm, for_each_table_entry, NET80211_CRYPTOS, and NULL.

Referenced by wpa_make_rsn_ie().

◆ wpa_find_kie()

struct wpa_kie * wpa_find_kie ( int version)

Find WPA key integrity and encryption handler from key version field.

Parameters
verVersion bits of EAPOL-Key info field
Return values
kieKey integrity and encryption handler

Definition at line 93 of file wpa.c.

94{
95 struct wpa_kie *kie;
96
98 if ( kie->version == version )
99 return kie;
100 }
101
102 return NULL;
103}
u32 version
Driver version.
Definition ath9k_hw.c:1985
WPA handshake key integrity and encryption handler.
Definition wpa.h:371
int version
Value of version bits in EAPOL-Key info field for which to use.
Definition wpa.h:376
#define WPA_KIES
Definition wpa.h:407

References for_each_table_entry, NULL, version, wpa_kie::version, and WPA_KIES.

Referenced by eapol_key_rx().

◆ wpa_make_rsn_ie()

int wpa_make_rsn_ie ( struct net80211_device * dev,
union ieee80211_ie ** ie_ret )

Construct RSN or WPA information element.

Parameters
dev802.11 device
Return values
ie_retRSN or WPA information element
rcReturn status code

This function allocates, fills, and returns a RSN or WPA information element suitable for including in an association request frame to the network identified by dev->associating. If it is impossible to construct an information element consistent with iPXE's capabilities that is compatible with that network, or if none should be sent because that network's beacon included no security information, returns an error indication and leaves ie_ret unchanged.

The returned IE will be of the same type (RSN or WPA) as was included in the beacon for the network it is destined for.

Definition at line 125 of file wpa.c.

126{
127 u8 *rsn, *rsn_end;
128 int is_rsn;
130 enum net80211_crypto_alg gcrypt;
131 int ie_len;
132 u8 *iep;
133 struct ieee80211_ie_rsn *ie;
134 struct ieee80211_frame *hdr;
135 struct ieee80211_beacon *beacon;
136
137 if ( ! dev->associating ) {
138 DBG ( "WPA: Can't make RSN IE for a non-associating device\n" );
139 return -EINVAL;
140 }
141
142 hdr = dev->associating->beacon->data;
143 beacon = ( struct ieee80211_beacon * ) hdr->data;
144 rsn = sec80211_find_rsn ( beacon->info_element,
145 dev->associating->beacon->tail, &is_rsn,
146 &rsn_end );
147 if ( ! rsn ) {
148 DBG ( "WPA: Can't make RSN IE when we didn't get one\n" );
149 return -EINVAL;
150 }
151
152 rsn += 2; /* skip version */
153 group_cipher = *( u32 * ) rsn;
155
156 if ( ! wpa_find_cryptosystem ( gcrypt ) ||
158 DBG ( "WPA: No support for (GC:%d, PC:%d)\n",
159 gcrypt, dev->associating->crypto );
160 return -ENOTSUP;
161 }
162
163 /* Everything looks good - make our IE. */
164
165 /* WPA IEs need 4 more bytes for the OUI+type */
166 ie_len = ieee80211_rsn_size ( 1, 1, 0, is_rsn ) + ( 4 * ! is_rsn );
167 iep = malloc ( ie_len );
168 if ( ! iep )
169 return -ENOMEM;
170
171 *ie_ret = ( union ieee80211_ie * ) iep;
172
173 /* Store ID and length bytes. */
174 *iep++ = ( is_rsn ? IEEE80211_IE_RSN : IEEE80211_IE_VENDOR );
175 *iep++ = ie_len - 2;
176
177 /* Store OUI+type for WPA IEs. */
178 if ( ! is_rsn ) {
179 *( u32 * ) iep = IEEE80211_WPA_OUI_VEN;
180 iep += 4;
181 }
182
183 /* If this is a WPA IE, the id and len bytes in the
184 ieee80211_ie_rsn structure will not be valid, but by doing
185 the cast we can fill all the other fields much more
186 readily. */
187
188 ie = ( struct ieee80211_ie_rsn * ) ( iep - 2 );
191 ie->pairwise_count = 1;
192 ie->pairwise_cipher[0] =
194 is_rsn );
195 ie->akm_count = 1;
196 ie->akm_list[0] =
198 is_rsn );
199 if ( is_rsn ) {
200 ie->rsn_capab = 0;
201 ie->pmkid_count = 0;
202 }
203
204 return 0;
205}
struct golan_inbox_hdr hdr
Message header.
Definition CIB_PRM.h:0
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
static size_t ieee80211_rsn_size(int npair, int nauth, int npmkid, int rsn_ie)
Calculate necessary size of RSN information element.
Definition ieee80211.h:844
#define IEEE80211_WPA_OUI_VEN
Old vendor-type WPA IE OUI type + subtype.
Definition ieee80211.h:869
#define IEEE80211_IE_VENDOR
Information element ID for Vendor Specific information element.
Definition ieee80211.h:960
#define IEEE80211_RSN_VERSION
802.11 RSN IE: expected version number
Definition ieee80211.h:873
#define IEEE80211_IE_RSN
Information element ID for Robust Security Network information element.
Definition ieee80211.h:834
#define ieee80211_beacon
Definition ieee80211.h:1069
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
#define ENOTSUP
Operation not supported.
Definition errno.h:590
u32 group_cipher
Cipher ID for the cipher used in multicast/broadcast frames.
Definition ieee80211.h:10
#define u8
Definition igbvf_osdep.h:40
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
net80211_crypto_alg
An 802.11 data encryption algorithm.
Definition net80211.h:129
u8 * sec80211_find_rsn(union ieee80211_ie *ie, void *ie_end, int *is_rsn, u8 **end)
Find the RSN or WPA information element in the provided beacon frame.
Definition sec80211.c:284
enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt(u32 desc)
Determine net80211 cryptosystem number from RSN descriptor.
Definition sec80211.c:509
u32 sec80211_rsn_get_crypto_desc(enum net80211_crypto_alg crypt, int rsnie)
Determine RSN descriptor for specified net80211 cryptosystem number.
Definition sec80211.c:482
u32 sec80211_rsn_get_akm_desc(enum net80211_security_proto secprot, int rsnie)
Determine RSN descriptor for specified net80211 handshaker number.
Definition sec80211.c:497
An 802.11 data or management frame without QoS or WDS header fields.
Definition ieee80211.h:301
802.11 Robust Security Network ("WPA") information element
Definition ieee80211.h:798
u16 akm_count
Number of authentication types supported.
Definition ieee80211.h:818
u16 pairwise_count
Number of unicast ciphers supported.
Definition ieee80211.h:812
u32 akm_list[1]
List of authentication type IDs for supported types.
Definition ieee80211.h:821
u32 pairwise_cipher[1]
List of cipher IDs for supported unicast frame ciphers.
Definition ieee80211.h:815
u16 rsn_capab
Security capabilities field (RSN only)
Definition ieee80211.h:824
u32 group_cipher
Cipher ID for the cipher used in multicast/broadcast frames.
Definition ieee80211.h:809
u16 pmkid_count
Number of PMKIDs included (present only in association frames)
Definition ieee80211.h:827
u16 version
RSN information element version.
Definition ieee80211.h:806
void * data
Start of data.
Definition iobuf.h:53
void * tail
End of data.
Definition iobuf.h:55
struct net80211_wlan * associating
Network with which we are associating.
Definition net80211.h:866
struct io_buffer * beacon
The complete beacon or probe-response frame received.
Definition net80211.h:1081
enum net80211_crypto_alg crypto
Cryptographic algorithm used on the network.
Definition net80211.h:1087
enum net80211_security_proto handshaking
Security handshaking method used on the network.
Definition net80211.h:1084
Any 802.11 information element.
Definition ieee80211.h:973
#define u32
Definition vga.h:21
static struct net80211_crypto * wpa_find_cryptosystem(enum net80211_crypto_alg crypt)
Find a cryptosystem handler structure from a crypto ID.
Definition wpa.c:74

References ieee80211_ie_rsn::akm_count, ieee80211_ie_rsn::akm_list, net80211_device::associating, net80211_wlan::beacon, net80211_wlan::crypto, io_buffer::data, DBG, EINVAL, ENOMEM, ENOTSUP, group_cipher, ieee80211_ie_rsn::group_cipher, net80211_wlan::handshaking, hdr, ieee80211_beacon, IEEE80211_IE_RSN, IEEE80211_IE_VENDOR, ieee80211_rsn_size(), IEEE80211_RSN_VERSION, IEEE80211_WPA_OUI_VEN, malloc(), ieee80211_ie_rsn::pairwise_cipher, ieee80211_ie_rsn::pairwise_count, ieee80211_ie_rsn::pmkid_count, ieee80211_ie_rsn::rsn_capab, sec80211_find_rsn(), sec80211_rsn_get_akm_desc(), sec80211_rsn_get_crypto_desc(), sec80211_rsn_get_net80211_crypt(), io_buffer::tail, u32, u8, ieee80211_ie_rsn::version, and wpa_find_cryptosystem().

Referenced by wpa_psk_init().

◆ wpa_start()

int wpa_start ( struct net80211_device * dev,
struct wpa_common_ctx * ctx,
const void * pmk,
size_t pmk_len )

Set up generic WPA support to handle 4-Way Handshake.

Parameters
dev802.11 device
ctxWPA common context
pmkPairwise Master Key to use for session
pmk_lenLength of PMK, almost always 32
Return values
rcReturn status code

Definition at line 217 of file wpa.c.

219{
220 struct io_buffer *iob;
221 struct ieee80211_frame *hdr;
222 struct ieee80211_beacon *beacon;
223 u8 *ap_rsn_ie = NULL, *ap_rsn_ie_end;
224
225 if ( ! dev->rsn_ie || ! dev->associating )
226 return -EINVAL;
227
228 ctx->dev = dev;
229 memcpy ( ctx->pmk, pmk, ctx->pmk_len = pmk_len );
230 ctx->state = WPA_READY;
231 ctx->replay = ~0ULL;
232
233 iob = dev->associating->beacon;
234 hdr = iob->data;
235 beacon = ( struct ieee80211_beacon * ) hdr->data;
236 ap_rsn_ie = sec80211_find_rsn ( beacon->info_element, iob->tail,
237 &ctx->ap_rsn_is_rsn, &ap_rsn_ie_end );
238 if ( ap_rsn_ie ) {
239 ctx->ap_rsn_ie = malloc ( ap_rsn_ie_end - ap_rsn_ie );
240 if ( ! ctx->ap_rsn_ie )
241 return -ENOMEM;
242 memcpy ( ctx->ap_rsn_ie, ap_rsn_ie, ap_rsn_ie_end - ap_rsn_ie );
243 ctx->ap_rsn_ie_len = ap_rsn_ie_end - ap_rsn_ie;
244 } else {
245 return -ENOENT;
246 }
247
248 ctx->crypt = dev->associating->crypto;
249 ctx->gcrypt = NET80211_CRYPT_UNKNOWN;
250
251 list_add_tail ( &ctx->list, &wpa_contexts );
252 return 0;
253}
#define ENOENT
No such file or directory.
Definition errno.h:515
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
@ NET80211_CRYPT_UNKNOWN
Dummy value used when the cryptosystem can't be detected.
Definition net80211.h:177
A persistent I/O buffer.
Definition iobuf.h:38
union ieee80211_ie * rsn_ie
RSN or WPA information element to include with association.
Definition net80211.h:932
struct list_head wpa_contexts
List of WPA contexts in active use.
Definition wpa.c:47
@ WPA_READY
Ready for 4-Way Handshake.
Definition wpa.h:181

References net80211_device::associating, net80211_wlan::beacon, net80211_wlan::crypto, ctx, io_buffer::data, EINVAL, ENOENT, ENOMEM, hdr, ieee80211_beacon, list_add_tail, malloc(), memcpy(), NET80211_CRYPT_UNKNOWN, NULL, net80211_device::rsn_ie, sec80211_find_rsn(), io_buffer::tail, u8, wpa_contexts, and WPA_READY.

Referenced by wpa_psk_start().

◆ wpa_stop()

void wpa_stop ( struct net80211_device * dev)

Disable handling of received WPA handshake frames.

Parameters
dev802.11 device

Definition at line 261 of file wpa.c.

262{
263 struct wpa_common_ctx *ctx, *tmp;
264
266 if ( ctx->dev == dev ) {
267 free ( ctx->ap_rsn_ie );
268 ctx->ap_rsn_ie = NULL;
269 list_del ( &ctx->list );
270 }
271 }
272}
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
Common context for WPA security handshaking.
Definition wpa.h:292
struct list_head list
List entry.
Definition wpa.h:362
struct net80211_device * dev
802.11 device we are authenticating for
Definition wpa.h:294

References ctx, wpa_common_ctx::dev, free, wpa_common_ctx::list, list_del, list_for_each_entry_safe, NULL, tmp, and wpa_contexts.

Referenced by wpa_psk_stop().

◆ wpa_derive_ptk()

void wpa_derive_ptk ( struct wpa_common_ctx * ctx)
static

Derive pairwise transient key.

Parameters
ctxWPA common context

Definition at line 280 of file wpa.c.

281{
282 struct {
283 u8 mac1[ETH_ALEN];
284 u8 mac2[ETH_ALEN];
285 u8 nonce1[WPA_NONCE_LEN];
286 u8 nonce2[WPA_NONCE_LEN];
287 } __attribute__ (( packed )) ptk_data;
288
289 /* The addresses and nonces are stored in numerical order (!) */
290
291 if ( memcmp ( ctx->dev->netdev->ll_addr, ctx->dev->bssid,
292 ETH_ALEN ) < 0 ) {
293 memcpy ( ptk_data.mac1, ctx->dev->netdev->ll_addr, ETH_ALEN );
294 memcpy ( ptk_data.mac2, ctx->dev->bssid, ETH_ALEN );
295 } else {
296 memcpy ( ptk_data.mac1, ctx->dev->bssid, ETH_ALEN );
297 memcpy ( ptk_data.mac2, ctx->dev->netdev->ll_addr, ETH_ALEN );
298 }
299
300 if ( memcmp ( ctx->Anonce, ctx->Snonce, WPA_NONCE_LEN ) < 0 ) {
301 memcpy ( ptk_data.nonce1, ctx->Anonce, WPA_NONCE_LEN );
302 memcpy ( ptk_data.nonce2, ctx->Snonce, WPA_NONCE_LEN );
303 } else {
304 memcpy ( ptk_data.nonce1, ctx->Snonce, WPA_NONCE_LEN );
305 memcpy ( ptk_data.nonce2, ctx->Anonce, WPA_NONCE_LEN );
306 }
307
308 DBGC2 ( ctx, "WPA %p A1 %s", ctx, eth_ntoa ( ptk_data.mac1 ) );
309 DBGC2 ( ctx, ", A2 %s\n", eth_ntoa ( ptk_data.mac2 ) );
310
311 DBGC2 ( ctx, "WPA %p Nonce1, Nonce2:\n", ctx );
312 DBGC2_HD ( ctx, ptk_data.nonce1, WPA_NONCE_LEN );
313 DBGC2_HD ( ctx, ptk_data.nonce2, WPA_NONCE_LEN );
314
315 prf_sha1 ( ctx->pmk, ctx->pmk_len,
316 "Pairwise key expansion",
317 &ptk_data, sizeof ( ptk_data ),
318 &ctx->ptk, sizeof ( ctx->ptk ) );
319
320 DBGC2 ( ctx, "WPA %p PTK:\n", ctx );
321 DBGC2_HD ( ctx, &ctx->ptk, sizeof ( ctx->ptk ) );
322}
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:176
#define DBGC2(...)
Definition compiler.h:522
#define DBGC2_HD(...)
Definition compiler.h:524
#define ETH_ALEN
Definition if_ether.h:9
#define __attribute__(x)
Definition compiler.h:10
void prf_sha1(const void *key, size_t key_len, const char *label, const void *data, size_t data_len, void *prf, size_t prf_len)
SHA1 pseudorandom function for creating derived keys.
Definition sha1extra.c:44
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
#define WPA_NONCE_LEN
Length of a nonce.
Definition wpa.h:204

References __attribute__, ctx, DBGC2, DBGC2_HD, ETH_ALEN, eth_ntoa(), memcmp(), memcpy(), prf_sha1(), u8, and WPA_NONCE_LEN.

Referenced by wpa_handle_1_of_4().

◆ wpa_install_ptk()

int wpa_install_ptk ( struct wpa_common_ctx * ctx,
int len )
inlinestatic

Install pairwise transient key.

Parameters
ctxWPA common context
lenKey length (16 for CCMP, 32 for TKIP)
Return values
rcReturn status code

Definition at line 332 of file wpa.c.

333{
334 DBGC ( ctx, "WPA %p: installing %d-byte pairwise transient key\n",
335 ctx, len );
336 DBGC2_HD ( ctx, &ctx->ptk.tk, len );
337
338 return sec80211_install ( &ctx->dev->crypto, ctx->crypt,
339 &ctx->ptk.tk, len, NULL );
340}
ring len
Length.
Definition dwmac.h:226
#define DBGC(...)
Definition compiler.h:505
int sec80211_install(struct net80211_crypto **which, enum net80211_crypto_alg crypt, const void *key, int len, const void *rsc)
Install 802.11 cryptosystem.
Definition sec80211.c:114

References ctx, DBGC, DBGC2_HD, len, NULL, and sec80211_install().

Referenced by wpa_handle_3_of_4().

◆ wpa_install_gtk()

int wpa_install_gtk ( struct wpa_common_ctx * ctx,
int len,
const void * rsc )
inlinestatic

Install group transient key.

Parameters
ctxWPA common context
lenKey length (16 for CCMP, 32 for TKIP)
rscReceive sequence counter field in EAPOL-Key packet
Return values
rcReturn status code

Definition at line 350 of file wpa.c.

352{
353 DBGC ( ctx, "WPA %p: installing %d-byte group transient key\n",
354 ctx, len );
355 DBGC2_HD ( ctx, &ctx->gtk.tk, len );
356
357 return sec80211_install ( &ctx->dev->gcrypto, ctx->gcrypt,
358 &ctx->gtk.tk, len, rsc );
359}
u8 rsc[8]
Receive sequence counter for GTK.
Definition wpa.h:42

References ctx, DBGC, DBGC2_HD, len, rsc, and sec80211_install().

Referenced by wpa_handle_1_of_2(), and wpa_maybe_install_gtk().

◆ wpa_maybe_install_gtk()

int wpa_maybe_install_gtk ( struct wpa_common_ctx * ctx,
union ieee80211_ie * ie,
void * ie_end,
const void * rsc )
static

Search for group transient key, and install it if found.

Parameters
ctxWPA common context
iePointer to first IE in key data field
ie_endPointer to first byte not in key data field
rscReceive sequence counter field in EAPOL-Key packet
Return values
rcReturn status code

Definition at line 370 of file wpa.c.

373{
374 struct wpa_kde *kde;
375
376 if ( ! ieee80211_ie_bound ( ie, ie_end ) )
377 return -ENOENT;
378
379 while ( ie ) {
380 if ( ie->id == IEEE80211_IE_VENDOR &&
381 ie->vendor.oui == WPA_KDE_GTK )
382 break;
383
384 ie = ieee80211_next_ie ( ie, ie_end );
385 }
386
387 if ( ! ie )
388 return -ENOENT;
389
390 if ( ie->len - 6u > sizeof ( ctx->gtk.tk ) ) {
391 DBGC ( ctx, "WPA %p: GTK KDE is too long (%d bytes, max %zd)\n",
392 ctx, ie->len - 4, sizeof ( ctx->gtk.tk ) );
393 return -EINVAL;
394 }
395
396 /* XXX We ignore key ID for now. */
397 kde = ( struct wpa_kde * ) ie;
398 memcpy ( &ctx->gtk.tk, &kde->gtk_encap.gtk, kde->len - 6 );
399
400 return wpa_install_gtk ( ctx, kde->len - 6, rsc );
401}
static int ieee80211_ie_bound(union ieee80211_ie *ie, void *end)
Check that 802.11 information element is bounded by buffer.
Definition ieee80211.h:1012
static union ieee80211_ie * ieee80211_next_ie(union ieee80211_ie *ie, void *end)
Advance to next 802.11 information element.
Definition ieee80211.h:1028
#define WPA_KDE_GTK
KDE type for an encapsulated Group Transient Key (requires encryption)
Definition wpa.h:442
u32 oui
OUI and vendor-specific type byte.
Definition ieee80211.h:955
struct wpa_gtk gtk
Encapsulated group transient key.
Definition wpa.h:431
Any key descriptor element type.
Definition wpa.h:465
u8 len
Length, not including ie_type and length fields.
Definition wpa.h:470
struct wpa_kde_gtk_encap gtk_encap
For GTK-type KDEs, encapsulated GTK.
Definition wpa.h:478
u8 len
Information element data length.
Definition ieee80211.h:977
struct ieee80211_ie_vendor vendor
Vendor-specific.
Definition ieee80211.h:1003
u8 id
Information element ID.
Definition ieee80211.h:976
static int wpa_install_gtk(struct wpa_common_ctx *ctx, int len, const void *rsc)
Install group transient key.
Definition wpa.c:350

References ctx, DBGC, EINVAL, ENOENT, wpa_kde_gtk_encap::gtk, wpa_kde::gtk_encap, ieee80211_ie::id, ieee80211_ie_bound(), IEEE80211_IE_VENDOR, ieee80211_next_ie(), ieee80211_ie::len, wpa_kde::len, memcpy(), ieee80211_ie_vendor::oui, rsc, ieee80211_ie::vendor, wpa_install_gtk(), and WPA_KDE_GTK.

Referenced by wpa_handle_1_of_2(), and wpa_handle_3_of_4().

◆ wpa_alloc_frame()

struct io_buffer * wpa_alloc_frame ( int kdlen)
static

Allocate I/O buffer for construction of outgoing EAPOL-Key frame.

Parameters
kdlenMaximum number of bytes in the Key Data field
Return values
iobNewly allocated I/O buffer

The returned buffer will have space reserved for the link-layer and EAPOL headers, and will have iob->tail pointing to the start of the Key Data field. Thus, it is necessary to use iob_put() in filling the Key Data.

Definition at line 415 of file wpa.c.

416{
417 struct io_buffer *ret = alloc_iob ( sizeof ( struct eapol_key_pkt ) +
418 kdlen +
419 sizeof ( struct eapol_header ) +
421 if ( ! ret )
422 return NULL;
423
424 iob_reserve ( ret, MAX_LL_HEADER_LEN + sizeof ( struct eapol_header ) );
425 memset ( iob_put ( ret, sizeof ( struct eapol_key_pkt ) ), 0,
426 sizeof ( struct eapol_key_pkt ) );
427
428 return ret;
429}
void * memset(void *dest, int character, size_t len) __nonnull
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
#define iob_put(iobuf, len)
Definition iobuf.h:125
#define iob_reserve(iobuf, len)
Definition iobuf.h:72
#define MAX_LL_HEADER_LEN
Maximum length of a link-layer header.
Definition netdevice.h:46
EAPoL header.
Definition eapol.h:19
An EAPOL-Key packet.
Definition wpa.h:105

References alloc_iob(), iob_put, iob_reserve, MAX_LL_HEADER_LEN, memset(), and NULL.

Referenced by wpa_send_2_of_4(), and wpa_send_final().

◆ wpa_send_eapol()

int wpa_send_eapol ( struct io_buffer * iob,
struct wpa_common_ctx * ctx,
struct wpa_kie * kie )
static

Send EAPOL-Key packet.

Parameters
iobI/O buffer, with sufficient headroom for headers
dev802.11 device
kieKey integrity and encryption handler
is_rsnIf TRUE, handshake uses new RSN format
Return values
rcReturn status code

If a KIE is specified, the MIC will be filled in before transmission.

Definition at line 443 of file wpa.c.

445{
446 struct eapol_key_pkt *pkt = iob->data;
447 struct eapol_header *eapol = iob_push ( iob, sizeof ( *eapol ) );
448
449 pkt->info = htons ( pkt->info );
450 pkt->keysize = htons ( pkt->keysize );
451 pkt->datalen = htons ( pkt->datalen );
452 pkt->replay = cpu_to_be64 ( pkt->replay );
454 eapol->type = EAPOL_TYPE_KEY;
455 eapol->len = htons ( iob->tail - iob->data - sizeof ( *eapol ) );
456
457 memset ( pkt->mic, 0, sizeof ( pkt->mic ) );
458 if ( kie )
459 kie->mic ( &ctx->ptk.kck, eapol, sizeof ( *eapol ) +
460 sizeof ( *pkt ) + ntohs ( pkt->datalen ),
461 pkt->mic );
462
463 return net_tx ( iob, ctx->dev->netdev, &eapol_protocol,
464 ctx->dev->bssid, ctx->dev->netdev->ll_addr );
465}
#define EAPOL_VERSION_2001
802.1X-2001
Definition eapol.h:29
#define EAPOL_TYPE_KEY
EAPoL key.
Definition eapol.h:38
#define htons(value)
Definition byteswap.h:136
#define ntohs(value)
Definition byteswap.h:137
#define cpu_to_be64(value)
Definition byteswap.h:112
#define iob_push(iobuf, len)
Definition iobuf.h:89
int net_tx(struct io_buffer *iobuf, struct net_device *netdev, struct net_protocol *net_protocol, const void *ll_dest, const void *ll_source)
Transmit network-layer packet.
Definition netdevice.c:1074
uint8_t version
Version.
Definition eapol.h:21
uint8_t type
Type.
Definition eapol.h:23
uint16_t len
Payload length.
Definition eapol.h:25
u16 keysize
Length of encryption key to be used, network byte order.
Definition wpa.h:116
u8 mic[16]
Message integrity code over the entire EAPOL frame.
Definition wpa.h:160
u16 info
Bitfield of key characteristics, network byte order.
Definition wpa.h:110
u16 datalen
Length of the data field in bytes, network byte order.
Definition wpa.h:163
u64 replay
Monotonically increasing value for EAPOL-Key conversations.
Definition wpa.h:124
void(* mic)(const void *kck, const void *msg, size_t len, void *mic)
Calculate MIC over message.
Definition wpa.h:388

References cpu_to_be64, ctx, io_buffer::data, eapol_key_pkt::datalen, EAPOL_TYPE_KEY, EAPOL_VERSION_2001, htons, eapol_key_pkt::info, iob_push, eapol_key_pkt::keysize, eapol_header::len, memset(), eapol_key_pkt::mic, wpa_kie::mic, net_tx(), ntohs, eapol_key_pkt::replay, io_buffer::tail, eapol_header::type, and eapol_header::version.

Referenced by wpa_send_2_of_4(), and wpa_send_final().

◆ wpa_send_2_of_4()

int wpa_send_2_of_4 ( struct wpa_common_ctx * ctx,
struct eapol_key_pkt * pkt,
int is_rsn,
struct wpa_kie * kie )
static

Send second frame in 4-Way Handshake.

Parameters
ctxWPA common context
pktFirst frame, to which this is a reply
is_rsnIf TRUE, handshake uses new RSN format
kieKey integrity and encryption handler
Return values
rcReturn status code

Definition at line 477 of file wpa.c.

480{
481 struct io_buffer *iob = wpa_alloc_frame ( ctx->dev->rsn_ie->len + 2 );
482 struct eapol_key_pkt *npkt;
483
484 if ( ! iob )
485 return -ENOMEM;
486
487 npkt = iob->data;
488 memcpy ( npkt, pkt, sizeof ( *pkt ) );
491 if ( is_rsn )
492 npkt->keysize = 0;
493 memcpy ( npkt->nonce, ctx->Snonce, sizeof ( npkt->nonce ) );
494 npkt->datalen = ctx->dev->rsn_ie->len + 2;
495 memcpy ( iob_put ( iob, npkt->datalen ), ctx->dev->rsn_ie,
496 npkt->datalen );
497
498 DBGC ( ctx, "WPA %p: sending 2/4\n", ctx );
499
500 return wpa_send_eapol ( iob, ctx, kie );
501}
#define EAPOL_KEY_INFO_KEY_MIC
Key MIC bit; set when the MIC field is valid, on messages 3 and 4.
Definition wpa.h:59
#define EAPOL_KEY_INFO_KEY_ACK
Key ACK bit; set when a response is required, on all messages except #4.
Definition wpa.h:56
u8 nonce[32]
Nonce value.
Definition wpa.h:131
static int wpa_send_eapol(struct io_buffer *iob, struct wpa_common_ctx *ctx, struct wpa_kie *kie)
Send EAPOL-Key packet.
Definition wpa.c:443
static struct io_buffer * wpa_alloc_frame(int kdlen)
Allocate I/O buffer for construction of outgoing EAPOL-Key frame.
Definition wpa.c:415

References ctx, io_buffer::data, eapol_key_pkt::datalen, DBGC, EAPOL_KEY_INFO_KEY_ACK, EAPOL_KEY_INFO_KEY_MIC, ENOMEM, eapol_key_pkt::info, iob_put, eapol_key_pkt::keysize, memcpy(), eapol_key_pkt::nonce, wpa_alloc_frame(), and wpa_send_eapol().

Referenced by wpa_handle_1_of_4().

◆ wpa_handle_1_of_4()

int wpa_handle_1_of_4 ( struct wpa_common_ctx * ctx,
struct eapol_key_pkt * pkt,
int is_rsn,
struct wpa_kie * kie )
static

Handle receipt of first frame in 4-Way Handshake.

Parameters
ctxWPA common context
pktEAPOL-Key packet
is_rsnIf TRUE, frame uses new RSN format
kieKey integrity and encryption handler
Return values
rcReturn status code

Definition at line 513 of file wpa.c.

516{
517 if ( ctx->state == WPA_WAITING )
518 return -EINVAL;
519
520 ctx->state = WPA_WORKING;
521 memcpy ( ctx->Anonce, pkt->nonce, sizeof ( ctx->Anonce ) );
522 if ( ! ctx->have_Snonce ) {
523 rbg_generate ( NULL, 0, 0, ctx->Snonce,
524 sizeof ( ctx->Snonce ) );
525 ctx->have_Snonce = 1;
526 }
527
528 DBGC ( ctx, "WPA %p: received 1/4, looks OK\n", ctx );
529
531
532 return wpa_send_2_of_4 ( ctx, pkt, is_rsn, kie );
533}
int rbg_generate(const void *additional, size_t additional_len, int prediction_resist, void *data, size_t len)
Generate bits using RBG.
Definition rbg.c:117
static int wpa_send_2_of_4(struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
Send second frame in 4-Way Handshake.
Definition wpa.c:477
static void wpa_derive_ptk(struct wpa_common_ctx *ctx)
Derive pairwise transient key.
Definition wpa.c:280
@ WPA_WAITING
Waiting for PMK to be set.
Definition wpa.h:178
@ WPA_WORKING
Performing 4-Way Handshake.
Definition wpa.h:184

References ctx, DBGC, EINVAL, memcpy(), eapol_key_pkt::nonce, NULL, rbg_generate(), wpa_derive_ptk(), wpa_send_2_of_4(), WPA_WAITING, and WPA_WORKING.

Referenced by eapol_key_rx().

◆ wpa_send_final()

int wpa_send_final ( struct wpa_common_ctx * ctx,
struct eapol_key_pkt * pkt,
int is_rsn,
struct wpa_kie * kie )
static

Send fourth frame in 4-Way Handshake, or second in Group Key Handshake.

Parameters
ctxWPA common context
pktEAPOL-Key packet for frame to which we're replying
is_rsnIf TRUE, frame uses new RSN format
kieKey integrity and encryption handler
Return values
rcReturn status code

Definition at line 545 of file wpa.c.

548{
549 struct io_buffer *iob = wpa_alloc_frame ( 0 );
550 struct eapol_key_pkt *npkt;
551
552 if ( ! iob )
553 return -ENOMEM;
554
555 npkt = iob->data;
556 memcpy ( npkt, pkt, sizeof ( *pkt ) );
559 if ( is_rsn )
560 npkt->keysize = 0;
561 memset ( npkt->nonce, 0, sizeof ( npkt->nonce ) );
562 memset ( npkt->iv, 0, sizeof ( npkt->iv ) );
563 npkt->datalen = 0;
564
565 if ( npkt->info & EAPOL_KEY_INFO_TYPE )
566 DBGC ( ctx, "WPA %p: sending 4/4\n", ctx );
567 else
568 DBGC ( ctx, "WPA %p: sending 2/2\n", ctx );
569
570 return wpa_send_eapol ( iob, ctx, kie );
571
572}
#define EAPOL_KEY_INFO_KEY_ENC
Key Encrypted bit; set when the Key Data field is encrypted.
Definition wpa.h:71
#define EAPOL_KEY_INFO_INSTALL
Key install bit; set on message 3 except when legacy hacks are used.
Definition wpa.h:53
#define EAPOL_KEY_INFO_TYPE
Key type bit, indicating pairwise or group.
Definition wpa.h:50
u8 iv[16]
Initialization vector.
Definition wpa.h:139

References ctx, io_buffer::data, eapol_key_pkt::datalen, DBGC, EAPOL_KEY_INFO_INSTALL, EAPOL_KEY_INFO_KEY_ACK, EAPOL_KEY_INFO_KEY_ENC, EAPOL_KEY_INFO_TYPE, ENOMEM, eapol_key_pkt::info, eapol_key_pkt::iv, eapol_key_pkt::keysize, memcpy(), memset(), eapol_key_pkt::nonce, wpa_alloc_frame(), and wpa_send_eapol().

Referenced by wpa_handle_1_of_2(), and wpa_handle_3_of_4().

◆ wpa_handle_3_of_4()

int wpa_handle_3_of_4 ( struct wpa_common_ctx * ctx,
struct eapol_key_pkt * pkt,
int is_rsn,
struct wpa_kie * kie )
static

Handle receipt of third frame in 4-Way Handshake.

Parameters
ctxWPA common context
pktEAPOL-Key packet
is_rsnIf TRUE, frame uses new RSN format
kieKey integrity and encryption handler
Return values
rcReturn status code

Definition at line 584 of file wpa.c.

587{
588 int rc;
589 u8 *this_rsn, *this_rsn_end;
590 u8 *new_rsn, *new_rsn_end;
591 int this_is_rsn, new_is_rsn;
592
593 if ( ctx->state == WPA_WAITING )
594 return -EINVAL;
595
596 ctx->state = WPA_WORKING;
597
598 /* Check nonce */
599 if ( memcmp ( ctx->Anonce, pkt->nonce, WPA_NONCE_LEN ) != 0 ) {
600 DBGC ( ctx, "WPA %p ALERT: nonce mismatch in 3/4\n", ctx );
601 return wpa_fail ( ctx, -EACCES );
602 }
603
604 /* Check RSN IE */
605 this_rsn = sec80211_find_rsn ( ( union ieee80211_ie * ) pkt->data,
606 pkt->data + pkt->datalen,
607 &this_is_rsn, &this_rsn_end );
608 if ( this_rsn )
609 new_rsn = sec80211_find_rsn ( ( union ieee80211_ie * )
610 this_rsn_end,
611 pkt->data + pkt->datalen,
612 &new_is_rsn, &new_rsn_end );
613 else
614 new_rsn = NULL;
615
616 if ( ! ctx->ap_rsn_ie || ! this_rsn ||
617 ctx->ap_rsn_ie_len != ( this_rsn_end - this_rsn ) ||
618 ctx->ap_rsn_is_rsn != this_is_rsn ||
619 memcmp ( ctx->ap_rsn_ie, this_rsn, ctx->ap_rsn_ie_len ) != 0 ) {
620 DBGC ( ctx, "WPA %p ALERT: RSN mismatch in 3/4\n", ctx );
621 DBGC2 ( ctx, "WPA %p RSNs (in 3/4, in beacon):\n", ctx );
622 DBGC2_HD ( ctx, this_rsn, this_rsn_end - this_rsn );
623 DBGC2_HD ( ctx, ctx->ap_rsn_ie, ctx->ap_rsn_ie_len );
624 return wpa_fail ( ctx, -EACCES );
625 }
626
627 /* Don't switch if they just supplied both styles of IE
628 simultaneously; we need two RSN IEs or two WPA IEs to
629 switch ciphers. They'll be immediately consecutive because
630 of ordering guarantees. */
631 if ( new_rsn && this_is_rsn == new_is_rsn ) {
632 struct net80211_wlan *assoc = ctx->dev->associating;
633 DBGC ( ctx, "WPA %p: accommodating bait-and-switch tactics\n",
634 ctx );
635 DBGC2 ( ctx, "WPA %p RSNs (in 3/4+beacon, new in 3/4):\n",
636 ctx );
637 DBGC2_HD ( ctx, this_rsn, this_rsn_end - this_rsn );
638 DBGC2_HD ( ctx, new_rsn, new_rsn_end - new_rsn );
639
640 if ( ( rc = sec80211_detect_ie ( new_is_rsn, new_rsn,
641 new_rsn_end,
642 &assoc->handshaking,
643 &assoc->crypto ) ) != 0 )
644 DBGC ( ctx, "WPA %p: bait-and-switch invalid, staying "
645 "with original request\n", ctx );
646 } else {
647 new_rsn = this_rsn;
648 new_is_rsn = this_is_rsn;
649 new_rsn_end = this_rsn_end;
650 }
651
652 /* Grab group cryptosystem ID */
653 ctx->gcrypt = sec80211_rsn_get_net80211_crypt ( *( u32 * )
654 ( new_rsn + 2 ) );
655
656 /* Check for a GTK, if info field is encrypted */
657 if ( pkt->info & EAPOL_KEY_INFO_KEY_ENC ) {
659 ( union ieee80211_ie * ) pkt->data,
660 pkt->data + pkt->datalen,
661 pkt->rsc );
662 if ( rc < 0 ) {
663 DBGC ( ctx, "WPA %p did not install GTK in 3/4: %s\n",
664 ctx, strerror ( rc ) );
665 if ( rc != -ENOENT )
666 return wpa_fail ( ctx, rc );
667 }
668 }
669
670 DBGC ( ctx, "WPA %p: received 3/4, looks OK\n", ctx );
671
672 /* Send final message */
673 rc = wpa_send_final ( ctx, pkt, is_rsn, kie );
674 if ( rc < 0 )
675 return wpa_fail ( ctx, rc );
676
677 /* Install PTK */
678 rc = wpa_install_ptk ( ctx, pkt->keysize );
679 if ( rc < 0 ) {
680 DBGC ( ctx, "WPA %p failed to install PTK: %s\n", ctx,
681 strerror ( rc ) );
682 return wpa_fail ( ctx, rc );
683 }
684
685 /* Mark us as needing a new Snonce if we rekey */
686 ctx->have_Snonce = 0;
687
688 /* Done! */
689 ctx->state = WPA_SUCCESS;
690 return 0;
691}
#define EACCES
Permission denied.
Definition errno.h:299
int sec80211_detect_ie(int is_rsn, u8 *start, u8 *end, enum net80211_security_proto *secprot, enum net80211_crypto_alg *crypt)
Detect crypto and AKM types from RSN information element.
Definition sec80211.c:341
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
u8 data[0]
Key data.
Definition wpa.h:171
u8 rsc[8]
Receive sequence counter for GTK.
Definition wpa.h:148
Structure representing a probed network.
Definition net80211.h:1057
static int wpa_install_ptk(struct wpa_common_ctx *ctx, int len)
Install pairwise transient key.
Definition wpa.c:332
static int wpa_fail(struct wpa_common_ctx *ctx, int rc)
Return an error code and deauthenticate.
Definition wpa.c:57
static int wpa_maybe_install_gtk(struct wpa_common_ctx *ctx, union ieee80211_ie *ie, void *ie_end, const void *rsc)
Search for group transient key, and install it if found.
Definition wpa.c:370
static int wpa_send_final(struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
Send fourth frame in 4-Way Handshake, or second in Group Key Handshake.
Definition wpa.c:545
@ WPA_SUCCESS
4-Way Handshake succeeded
Definition wpa.h:187

References net80211_wlan::crypto, ctx, eapol_key_pkt::data, eapol_key_pkt::datalen, DBGC, DBGC2, DBGC2_HD, EACCES, EAPOL_KEY_INFO_KEY_ENC, EINVAL, ENOENT, net80211_wlan::handshaking, eapol_key_pkt::info, eapol_key_pkt::keysize, memcmp(), eapol_key_pkt::nonce, NULL, rc, eapol_key_pkt::rsc, sec80211_detect_ie(), sec80211_find_rsn(), sec80211_rsn_get_net80211_crypt(), strerror(), u32, u8, wpa_fail(), wpa_install_ptk(), wpa_maybe_install_gtk(), WPA_NONCE_LEN, wpa_send_final(), WPA_SUCCESS, WPA_WAITING, and WPA_WORKING.

Referenced by eapol_key_rx().

◆ wpa_handle_1_of_2()

int wpa_handle_1_of_2 ( struct wpa_common_ctx * ctx,
struct eapol_key_pkt * pkt,
int is_rsn,
struct wpa_kie * kie )
static

Handle receipt of first frame in Group Key Handshake.

Parameters
ctxWPA common context
pktEAPOL-Key packet
is_rsnIf TRUE, frame uses new RSN format
kieKey integrity and encryption handler
Return values
rcReturn status code

Definition at line 703 of file wpa.c.

706{
707 int rc;
708
709 /*
710 * WPA and RSN do this completely differently.
711 *
712 * The idea of encoding the GTK (or PMKID, or various other
713 * things) into a KDE that looks like an information element
714 * is an RSN innovation; old WPA code never encapsulates
715 * things like that. If it looks like an info element, it
716 * really is (for the WPA IE check in frames 2/4 and 3/4). The
717 * "key data encrypted" bit in the info field is also specific
718 * to RSN.
719 *
720 * So from an old WPA host, 3/4 does not contain an
721 * encapsulated GTK. The first frame of the GK handshake
722 * contains it, encrypted, but without a KDE wrapper, and with
723 * the key ID field (which iPXE doesn't use) shoved away in
724 * the reserved bits in the info field, and the TxRx bit
725 * stealing the Install bit's spot.
726 */
727
728 if ( is_rsn && ( pkt->info & EAPOL_KEY_INFO_KEY_ENC ) ) {
730 ( union ieee80211_ie * ) pkt->data,
731 pkt->data + pkt->datalen,
732 pkt->rsc );
733 if ( rc < 0 ) {
734 DBGC ( ctx, "WPA %p: failed to install GTK in 1/2: "
735 "%s\n", ctx, strerror ( rc ) );
736 return wpa_fail ( ctx, rc );
737 }
738 } else {
739 rc = kie->decrypt ( &ctx->ptk.kek, pkt->iv, pkt->data,
740 &pkt->datalen );
741 if ( rc < 0 ) {
742 DBGC ( ctx, "WPA %p: failed to decrypt GTK: %s\n",
743 ctx, strerror ( rc ) );
744 return rc; /* non-fatal */
745 }
746 if ( pkt->datalen > sizeof ( ctx->gtk.tk ) ) {
747 DBGC ( ctx, "WPA %p: too much GTK data (%d > %zd)\n",
748 ctx, pkt->datalen, sizeof ( ctx->gtk.tk ) );
749 return wpa_fail ( ctx, -EINVAL );
750 }
751
752 memcpy ( &ctx->gtk.tk, pkt->data, pkt->datalen );
753 wpa_install_gtk ( ctx, pkt->datalen, pkt->rsc );
754 }
755
756 DBGC ( ctx, "WPA %p: received 1/2, looks OK\n", ctx );
757
758 return wpa_send_final ( ctx, pkt, is_rsn, kie );
759}
int(* decrypt)(const void *kek, const void *iv, void *msg, u16 *len)
Decrypt key data.
Definition wpa.h:403

References ctx, eapol_key_pkt::data, eapol_key_pkt::datalen, DBGC, wpa_kie::decrypt, EAPOL_KEY_INFO_KEY_ENC, EINVAL, eapol_key_pkt::info, eapol_key_pkt::iv, memcpy(), rc, eapol_key_pkt::rsc, strerror(), wpa_fail(), wpa_install_gtk(), wpa_maybe_install_gtk(), and wpa_send_final().

Referenced by eapol_key_rx().

◆ eapol_key_rx()

int eapol_key_rx ( struct eapol_supplicant * supplicant,
struct io_buffer * iob,
const void * ll_source )
static

Handle receipt of EAPOL-Key frame for WPA.

Parameters
supplicantEAPoL supplicant
iobI/O buffer
ll_sourceSource link-layer address

Definition at line 769 of file wpa.c.

771{
772 struct net_device *netdev = supplicant->eap.netdev;
773 struct net80211_device *dev = net80211_get ( netdev );
774 struct eapol_header *eapol;
775 struct eapol_key_pkt *pkt;
776 int is_rsn, found_ctx;
777 struct wpa_common_ctx *ctx;
778 int rc = 0;
779 struct wpa_kie *kie;
780 u8 their_mic[16], our_mic[16];
781
782 eapol = iob->data;
783 pkt = ( ( ( void * ) eapol ) + sizeof ( *eapol ) );
784
785 if ( pkt->type != EAPOL_KEY_TYPE_WPA &&
786 pkt->type != EAPOL_KEY_TYPE_RSN ) {
787 DBG ( "EAPOL-Key: packet not of 802.11 type\n" );
788 rc = -EINVAL;
789 goto drop;
790 }
791
792 is_rsn = ( pkt->type == EAPOL_KEY_TYPE_RSN );
793
794 if ( ! dev ) {
795 DBG ( "EAPOL-Key: packet not from 802.11\n" );
796 rc = -EINVAL;
797 goto drop;
798 }
799
800 if ( memcmp ( dev->bssid, ll_source, ETH_ALEN ) != 0 ) {
801 DBG ( "EAPOL-Key: packet not from associated AP\n" );
802 rc = -EINVAL;
803 goto drop;
804 }
805
806 if ( ! ( ntohs ( pkt->info ) & EAPOL_KEY_INFO_KEY_ACK ) ) {
807 DBG ( "EAPOL-Key: packet sent in wrong direction\n" );
808 rc = -EINVAL;
809 goto drop;
810 }
811
812 found_ctx = 0;
814 if ( ctx->dev == dev ) {
815 found_ctx = 1;
816 break;
817 }
818 }
819
820 if ( ! found_ctx ) {
821 DBG ( "EAPOL-Key: no WPA context to handle packet for %p\n",
822 dev );
823 rc = -ENOENT;
824 goto drop;
825 }
826
827 if ( ( void * ) ( pkt + 1 ) + ntohs ( pkt->datalen ) > iob->tail ) {
828 DBGC ( ctx, "WPA %p: packet truncated (has %zd extra bytes, "
829 "states %d)\n", ctx, iob->tail - ( void * ) ( pkt + 1 ),
830 ntohs ( pkt->datalen ) );
831 rc = -EINVAL;
832 goto drop;
833 }
834
835 /* Get a handle on key integrity/encryption handler */
836 kie = wpa_find_kie ( ntohs ( pkt->info ) & EAPOL_KEY_INFO_VERSION );
837 if ( ! kie ) {
838 DBGC ( ctx, "WPA %p: no support for packet version %d\n", ctx,
839 ntohs ( pkt->info ) & EAPOL_KEY_INFO_VERSION );
840 rc = wpa_fail ( ctx, -ENOTSUP );
841 goto drop;
842 }
843
844 /* Check MIC */
845 if ( ntohs ( pkt->info ) & EAPOL_KEY_INFO_KEY_MIC ) {
846 memcpy ( their_mic, pkt->mic, sizeof ( pkt->mic ) );
847 memset ( pkt->mic, 0, sizeof ( pkt->mic ) );
848 kie->mic ( &ctx->ptk.kck, eapol,
849 sizeof ( *eapol ) + sizeof ( *pkt ) +
850 ntohs ( pkt->datalen ), our_mic );
851 DBGC2 ( ctx, "WPA %p MIC comparison (theirs, ours):\n", ctx );
852 DBGC2_HD ( ctx, their_mic, 16 );
853 DBGC2_HD ( ctx, our_mic, 16 );
854 if ( memcmp ( their_mic, our_mic, sizeof ( pkt->mic ) ) != 0 ) {
855 DBGC ( ctx, "WPA %p: EAPOL MIC failure\n", ctx );
856 goto drop;
857 }
858 }
859
860 /* Fix byte order to local */
861 pkt->info = ntohs ( pkt->info );
862 pkt->keysize = ntohs ( pkt->keysize );
863 pkt->datalen = ntohs ( pkt->datalen );
864 pkt->replay = be64_to_cpu ( pkt->replay );
865
866 /* Check replay counter */
867 if ( ctx->replay != ~0ULL && ctx->replay >= pkt->replay ) {
868 DBGC ( ctx, "WPA %p ALERT: Replay detected! "
869 "(%08x:%08x >= %08x:%08x)\n", ctx,
870 ( u32 ) ( ctx->replay >> 32 ), ( u32 ) ctx->replay,
871 ( u32 ) ( pkt->replay >> 32 ), ( u32 ) pkt->replay );
872 rc = 0; /* ignore without error */
873 goto drop;
874 }
875 ctx->replay = pkt->replay;
876
877 /* Decrypt key data */
878 if ( pkt->info & EAPOL_KEY_INFO_KEY_ENC ) {
879 rc = kie->decrypt ( &ctx->ptk.kek, pkt->iv, pkt->data,
880 &pkt->datalen );
881 if ( rc < 0 ) {
882 DBGC ( ctx, "WPA %p: failed to decrypt packet: %s\n",
883 ctx, strerror ( rc ) );
884 goto drop;
885 }
886 }
887
888 /* Hand it off to appropriate handler */
889 switch ( pkt->info & ( EAPOL_KEY_INFO_TYPE |
892 rc = wpa_handle_1_of_4 ( ctx, pkt, is_rsn, kie );
893 break;
894
896 rc = wpa_handle_3_of_4 ( ctx, pkt, is_rsn, kie );
897 break;
898
900 rc = wpa_handle_1_of_2 ( ctx, pkt, is_rsn, kie );
901 break;
902
903 default:
904 DBGC ( ctx, "WPA %p: Invalid combination of key flags %04x\n",
905 ctx, pkt->info );
906 rc = -EINVAL;
907 break;
908 }
909
910 drop:
911 free_iob ( iob );
912 return rc;
913}
static struct net_device * netdev
Definition gdbudp.c:53
#define EAPOL_KEY_TYPE_PTK
Key type field value for a PTK (pairwise) key handshake.
Definition wpa.h:84
#define EAPOL_KEY_INFO_VERSION
Key descriptor version, indicating WPA or WPA2.
Definition wpa.h:47
#define EAPOL_KEY_TYPE_GTK
Key type field value for a GTK (group) key handshake.
Definition wpa.h:87
struct net80211_device * net80211_get(struct net_device *netdev)
Get 802.11 device from wrapping network device.
Definition net80211.c:625
#define be64_to_cpu(value)
Definition byteswap.h:118
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
struct net_device * netdev
Network device.
Definition eap.h:141
u8 type
One of the EAPOL_KEY_TYPE_* defines.
Definition wpa.h:107
struct eap_supplicant eap
EAP supplicant.
Definition eapol.h:43
Structure encapsulating the complete state of an 802.11 device.
Definition net80211.h:787
u8 bssid[ETH_ALEN]
MAC address of the access point most recently associated.
Definition net80211.h:954
A network device.
Definition netdevice.h:353
struct wpa_kie * wpa_find_kie(int version)
Find WPA key integrity and encryption handler from key version field.
Definition wpa.c:93
static int wpa_handle_3_of_4(struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
Handle receipt of third frame in 4-Way Handshake.
Definition wpa.c:584
static int wpa_handle_1_of_2(struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
Handle receipt of first frame in Group Key Handshake.
Definition wpa.c:703
static int wpa_handle_1_of_4(struct wpa_common_ctx *ctx, struct eapol_key_pkt *pkt, int is_rsn, struct wpa_kie *kie)
Handle receipt of first frame in 4-Way Handshake.
Definition wpa.c:513
#define EAPOL_KEY_TYPE_WPA
Old EAPOL-Key type field used by WPA1 hardware before 802.11i ratified.
Definition wpa.h:38
#define EAPOL_KEY_TYPE_RSN
EAPOL-Key type field for modern 802.11i/RSN WPA packets.
Definition wpa.h:35

References be64_to_cpu, net80211_device::bssid, ctx, eapol_key_pkt::data, io_buffer::data, eapol_key_pkt::datalen, DBG, DBGC, DBGC2, DBGC2_HD, wpa_kie::decrypt, eapol_supplicant::eap, EAPOL_KEY_INFO_KEY_ACK, EAPOL_KEY_INFO_KEY_ENC, EAPOL_KEY_INFO_KEY_MIC, EAPOL_KEY_INFO_TYPE, EAPOL_KEY_INFO_VERSION, EAPOL_KEY_TYPE_GTK, EAPOL_KEY_TYPE_PTK, EAPOL_KEY_TYPE_RSN, EAPOL_KEY_TYPE_WPA, EINVAL, ENOENT, ENOTSUP, ETH_ALEN, free_iob(), eapol_key_pkt::info, eapol_key_pkt::iv, eapol_key_pkt::keysize, list_for_each_entry, memcmp(), memcpy(), memset(), eapol_key_pkt::mic, wpa_kie::mic, net80211_get(), eap_supplicant::netdev, netdev, ntohs, rc, eapol_key_pkt::replay, strerror(), io_buffer::tail, eapol_key_pkt::type, u32, u8, wpa_contexts, wpa_fail(), wpa_find_kie(), wpa_handle_1_of_2(), wpa_handle_1_of_4(), and wpa_handle_3_of_4().

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( eapol_key_handler )

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( eapol )

Variable Documentation

◆ wpa_contexts

struct list_head wpa_contexts = LIST_HEAD_INIT ( wpa_contexts )

List of WPA contexts in active use.

Definition at line 47 of file wpa.c.

Referenced by eapol_key_rx(), wpa_start(), and wpa_stop().

◆ __eapol_handler

struct eapol_handler eapol_key_handler __eapol_handler
Initial value:
= {
.type = EAPOL_TYPE_KEY,
.rx = eapol_key_rx,
}
static int eapol_key_rx(struct eapol_supplicant *supplicant, struct io_buffer *iob, const void *ll_source)
Handle receipt of EAPOL-Key frame for WPA.
Definition wpa.c:769

Definition at line 915 of file wpa.c.

915 {
916 .type = EAPOL_TYPE_KEY,
917 .rx = eapol_key_rx,
918};