]> git.ipfire.org Git - thirdparty/hostap.git/blob - wlantest/rx_eapol.c
wlantest: Add more pcapng notes on EAPOL processing
[thirdparty/hostap.git] / wlantest / rx_eapol.c
1 /*
2 * Received Data frame processing for EAPOL messages
3 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "utils/includes.h"
10
11 #include "utils/common.h"
12 #include "crypto/aes_wrap.h"
13 #include "crypto/crypto.h"
14 #include "common/defs.h"
15 #include "common/ieee802_11_defs.h"
16 #include "common/ieee802_11_common.h"
17 #include "common/eapol_common.h"
18 #include "common/wpa_common.h"
19 #include "rsn_supp/wpa_ie.h"
20 #include "wlantest.h"
21
22 extern int wpa_debug_level;
23
24
25 static int is_zero(const u8 *buf, size_t len)
26 {
27 size_t i;
28 for (i = 0; i < len; i++) {
29 if (buf[i])
30 return 0;
31 }
32 return 1;
33 }
34
35
36 static int check_mic(const u8 *kck, int ver, const u8 *data, size_t len)
37 {
38 u8 *buf;
39 int ret = -1;
40 struct ieee802_1x_hdr *hdr;
41 struct wpa_eapol_key *key;
42 u8 rx_mic[16];
43
44 buf = os_malloc(len);
45 if (buf == NULL)
46 return -1;
47 os_memcpy(buf, data, len);
48 hdr = (struct ieee802_1x_hdr *) buf;
49 key = (struct wpa_eapol_key *) (hdr + 1);
50
51 os_memcpy(rx_mic, key->key_mic, 16);
52 os_memset(key->key_mic, 0, 16);
53
54 if (wpa_eapol_key_mic(kck, ver, buf, len, key->key_mic) == 0 &&
55 os_memcmp(rx_mic, key->key_mic, 16) == 0)
56 ret = 0;
57
58 os_free(buf);
59
60 return ret;
61 }
62
63
64 static void rx_data_eapol_key_1_of_4(struct wlantest *wt, const u8 *dst,
65 const u8 *src, const u8 *data, size_t len)
66 {
67 struct wlantest_bss *bss;
68 struct wlantest_sta *sta;
69 const struct ieee802_1x_hdr *eapol;
70 const struct wpa_eapol_key *hdr;
71
72 wpa_printf(MSG_DEBUG, "EAPOL-Key 1/4 " MACSTR " -> " MACSTR,
73 MAC2STR(src), MAC2STR(dst));
74 bss = bss_get(wt, src);
75 if (bss == NULL)
76 return;
77 sta = sta_get(bss, dst);
78 if (sta == NULL)
79 return;
80
81 eapol = (const struct ieee802_1x_hdr *) data;
82 hdr = (const struct wpa_eapol_key *) (eapol + 1);
83 if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) {
84 add_note(wt, MSG_INFO, "EAPOL-Key 1/4 from " MACSTR
85 " used zero nonce", MAC2STR(src));
86 }
87 if (!is_zero(hdr->key_rsc, 8)) {
88 add_note(wt, MSG_INFO, "EAPOL-Key 1/4 from " MACSTR
89 " used non-zero Key RSC", MAC2STR(src));
90 }
91 os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
92 }
93
94
95 static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss,
96 struct wlantest_sta *sta, u16 ver,
97 const u8 *data, size_t len,
98 struct wlantest_pmk *pmk)
99 {
100 struct wpa_ptk ptk;
101 size_t ptk_len = sta->pairwise_cipher == WPA_CIPHER_TKIP ? 64 : 48;
102 wpa_pmk_to_ptk(pmk->pmk, sizeof(pmk->pmk),
103 "Pairwise key expansion",
104 bss->bssid, sta->addr, sta->anonce, sta->snonce,
105 (u8 *) &ptk, ptk_len,
106 wpa_key_mgmt_sha256(sta->key_mgmt));
107 if (check_mic(ptk.kck, ver, data, len) < 0)
108 return -1;
109
110 wpa_printf(MSG_INFO, "Derived PTK for STA " MACSTR " BSSID " MACSTR,
111 MAC2STR(sta->addr), MAC2STR(bss->bssid));
112 sta->counters[WLANTEST_STA_COUNTER_PTK_LEARNED]++;
113 if (sta->ptk_set) {
114 /*
115 * Rekeying - use new PTK for EAPOL-Key frames, but continue
116 * using the old PTK for frame decryption.
117 */
118 add_note(wt, MSG_DEBUG, "Derived PTK during rekeying");
119 os_memcpy(&sta->tptk, &ptk, sizeof(ptk));
120 wpa_hexdump(MSG_DEBUG, "TPTK:KCK", sta->tptk.kck, 16);
121 wpa_hexdump(MSG_DEBUG, "TPTK:KEK", sta->tptk.kek, 16);
122 wpa_hexdump(MSG_DEBUG, "TPTK:TK1", sta->tptk.tk1, 16);
123 if (ptk_len > 48)
124 wpa_hexdump(MSG_DEBUG, "TPTK:TK2", sta->tptk.u.tk2,
125 16);
126 sta->tptk_set = 1;
127 return 0;
128 }
129 add_note(wt, MSG_DEBUG, "Derived new PTK");
130 os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
131 wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16);
132 wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16);
133 wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16);
134 if (ptk_len > 48)
135 wpa_hexdump(MSG_DEBUG, "PTK:TK2", sta->ptk.u.tk2, 16);
136 sta->ptk_set = 1;
137 os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
138 os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
139 return 0;
140 }
141
142
143 static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss,
144 struct wlantest_sta *sta, u16 ver,
145 const u8 *data, size_t len)
146 {
147 struct wlantest_pmk *pmk;
148
149 wpa_printf(MSG_DEBUG, "Trying to derive PTK for " MACSTR,
150 MAC2STR(sta->addr));
151 dl_list_for_each(pmk, &bss->pmk, struct wlantest_pmk, list) {
152 wpa_printf(MSG_DEBUG, "Try per-BSS PMK");
153 if (try_pmk(wt, bss, sta, ver, data, len, pmk) == 0)
154 return;
155 }
156
157 dl_list_for_each(pmk, &wt->pmk, struct wlantest_pmk, list) {
158 wpa_printf(MSG_DEBUG, "Try global PMK");
159 if (try_pmk(wt, bss, sta, ver, data, len, pmk) == 0)
160 return;
161 }
162
163 if (!sta->ptk_set) {
164 struct wlantest_ptk *ptk;
165 int prev_level = wpa_debug_level;
166
167 wpa_debug_level = MSG_WARNING;
168 dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
169 if (check_mic(ptk->ptk.kck, ver, data, len) < 0)
170 continue;
171 wpa_printf(MSG_INFO, "Pre-set PTK matches for STA "
172 MACSTR " BSSID " MACSTR,
173 MAC2STR(sta->addr), MAC2STR(bss->bssid));
174 add_note(wt, MSG_DEBUG, "Using pre-set PTK");
175 os_memcpy(&sta->ptk, &ptk->ptk, sizeof(ptk->ptk));
176 wpa_hexdump(MSG_DEBUG, "PTK:KCK", sta->ptk.kck, 16);
177 wpa_hexdump(MSG_DEBUG, "PTK:KEK", sta->ptk.kek, 16);
178 wpa_hexdump(MSG_DEBUG, "PTK:TK1", sta->ptk.tk1, 16);
179 if (ptk->ptk_len > 48)
180 wpa_hexdump(MSG_DEBUG, "PTK:TK2",
181 sta->ptk.u.tk2, 16);
182 sta->ptk_set = 1;
183 os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
184 os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
185 }
186 wpa_debug_level = prev_level;
187 }
188
189 add_note(wt, MSG_DEBUG, "No matching PMK found to derive PTK");
190 }
191
192
193 static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst,
194 const u8 *src, const u8 *data, size_t len)
195 {
196 struct wlantest_bss *bss;
197 struct wlantest_sta *sta;
198 const struct ieee802_1x_hdr *eapol;
199 const struct wpa_eapol_key *hdr;
200 const u8 *key_data, *kck;
201 u16 key_info, key_data_len;
202 struct wpa_eapol_ie_parse ie;
203
204 wpa_printf(MSG_DEBUG, "EAPOL-Key 2/4 " MACSTR " -> " MACSTR,
205 MAC2STR(src), MAC2STR(dst));
206 bss = bss_get(wt, dst);
207 if (bss == NULL)
208 return;
209 sta = sta_get(bss, src);
210 if (sta == NULL)
211 return;
212
213 eapol = (const struct ieee802_1x_hdr *) data;
214 hdr = (const struct wpa_eapol_key *) (eapol + 1);
215 if (is_zero(hdr->key_nonce, WPA_NONCE_LEN)) {
216 add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR
217 " used zero nonce", MAC2STR(src));
218 }
219 if (!is_zero(hdr->key_rsc, 8)) {
220 add_note(wt, MSG_INFO, "EAPOL-Key 2/4 from " MACSTR
221 " used non-zero Key RSC", MAC2STR(src));
222 }
223 os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN);
224 key_info = WPA_GET_BE16(hdr->key_info);
225 key_data_len = WPA_GET_BE16(hdr->key_data_length);
226 derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len);
227
228 if (!sta->ptk_set && !sta->tptk_set) {
229 add_note(wt, MSG_DEBUG,
230 "No PTK known to process EAPOL-Key 2/4");
231 return;
232 }
233
234 kck = sta->ptk.kck;
235 if (sta->tptk_set) {
236 add_note(wt, MSG_DEBUG,
237 "Use TPTK for validation EAPOL-Key MIC");
238 kck = sta->tptk.kck;
239 }
240 if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
241 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/4 MIC");
242 return;
243 }
244 add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/4");
245
246 key_data = (const u8 *) (hdr + 1);
247
248 if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) {
249 add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
250 return;
251 }
252
253 if (ie.wpa_ie) {
254 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE",
255 ie.wpa_ie, ie.wpa_ie_len);
256 if (os_memcmp(ie.wpa_ie, sta->rsnie, ie.wpa_ie_len) != 0) {
257 struct ieee802_11_elems elems;
258 add_note(wt, MSG_INFO,
259 "Mismatch in WPA IE between EAPOL-Key 2/4 "
260 "and (Re)Association Request from " MACSTR,
261 MAC2STR(sta->addr));
262 wpa_hexdump(MSG_INFO, "WPA IE in EAPOL-Key",
263 ie.wpa_ie, ie.wpa_ie_len);
264 wpa_hexdump(MSG_INFO, "WPA IE in (Re)Association "
265 "Request",
266 sta->rsnie,
267 sta->rsnie[0] ? 2 + sta->rsnie[1] : 0);
268 /*
269 * The sniffer may have missed (Re)Association
270 * Request, so try to survive with the information from
271 * EAPOL-Key.
272 */
273 os_memset(&elems, 0, sizeof(elems));
274 elems.wpa_ie = ie.wpa_ie + 2;
275 elems.wpa_ie_len = ie.wpa_ie_len - 2;
276 wpa_printf(MSG_DEBUG, "Update STA data based on WPA "
277 "IE in EAPOL-Key 2/4");
278 sta_update_assoc(sta, &elems);
279 }
280 }
281
282 if (ie.rsn_ie) {
283 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE",
284 ie.rsn_ie, ie.rsn_ie_len);
285 if (os_memcmp(ie.rsn_ie, sta->rsnie, ie.rsn_ie_len) != 0) {
286 struct ieee802_11_elems elems;
287 add_note(wt, MSG_INFO,
288 "Mismatch in RSN IE between EAPOL-Key 2/4 "
289 "and (Re)Association Request from " MACSTR,
290 MAC2STR(sta->addr));
291 wpa_hexdump(MSG_INFO, "RSN IE in EAPOL-Key",
292 ie.rsn_ie, ie.rsn_ie_len);
293 wpa_hexdump(MSG_INFO, "RSN IE in (Re)Association "
294 "Request",
295 sta->rsnie,
296 sta->rsnie[0] ? 2 + sta->rsnie[1] : 0);
297 /*
298 * The sniffer may have missed (Re)Association
299 * Request, so try to survive with the information from
300 * EAPOL-Key.
301 */
302 os_memset(&elems, 0, sizeof(elems));
303 elems.rsn_ie = ie.rsn_ie + 2;
304 elems.rsn_ie_len = ie.rsn_ie_len - 2;
305 wpa_printf(MSG_DEBUG, "Update STA data based on RSN "
306 "IE in EAPOL-Key 2/4");
307 sta_update_assoc(sta, &elems);
308 }
309 }
310 }
311
312
313 static u8 * decrypt_eapol_key_data_rc4(struct wlantest *wt, const u8 *kek,
314 const struct wpa_eapol_key *hdr,
315 size_t *len)
316 {
317 u8 ek[32], *buf;
318 u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);
319
320 buf = os_malloc(keydatalen);
321 if (buf == NULL)
322 return NULL;
323
324 os_memcpy(ek, hdr->key_iv, 16);
325 os_memcpy(ek + 16, kek, 16);
326 os_memcpy(buf, hdr + 1, keydatalen);
327 if (rc4_skip(ek, 32, 256, buf, keydatalen)) {
328 add_note(wt, MSG_INFO, "RC4 failed");
329 os_free(buf);
330 return NULL;
331 }
332
333 *len = keydatalen;
334 return buf;
335 }
336
337
338 static u8 * decrypt_eapol_key_data_aes(struct wlantest *wt, const u8 *kek,
339 const struct wpa_eapol_key *hdr,
340 size_t *len)
341 {
342 u8 *buf;
343 u16 keydatalen = WPA_GET_BE16(hdr->key_data_length);
344
345 if (keydatalen % 8) {
346 add_note(wt, MSG_INFO, "Unsupported AES-WRAP len %d",
347 keydatalen);
348 return NULL;
349 }
350 keydatalen -= 8; /* AES-WRAP adds 8 bytes */
351 buf = os_malloc(keydatalen);
352 if (buf == NULL)
353 return NULL;
354 if (aes_unwrap(kek, keydatalen / 8, (u8 *) (hdr + 1), buf)) {
355 os_free(buf);
356 add_note(wt, MSG_INFO,
357 "AES unwrap failed - could not decrypt EAPOL-Key "
358 "key data");
359 return NULL;
360 }
361
362 *len = keydatalen;
363 return buf;
364 }
365
366
367 static u8 * decrypt_eapol_key_data(struct wlantest *wt, const u8 *kek, u16 ver,
368 const struct wpa_eapol_key *hdr,
369 size_t *len)
370 {
371 switch (ver) {
372 case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
373 return decrypt_eapol_key_data_rc4(wt, kek, hdr, len);
374 case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
375 case WPA_KEY_INFO_TYPE_AES_128_CMAC:
376 return decrypt_eapol_key_data_aes(wt, kek, hdr, len);
377 default:
378 add_note(wt, MSG_INFO,
379 "Unsupported EAPOL-Key Key Descriptor Version %u",
380 ver);
381 return NULL;
382 }
383 }
384
385
386 static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss,
387 struct wlantest_sta *sta,
388 const u8 *buf, size_t len, const u8 *rsc)
389 {
390 struct wpa_eapol_ie_parse ie;
391
392 if (wpa_supplicant_parse_ies(buf, len, &ie) < 0) {
393 add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
394 return;
395 }
396
397 if (ie.wpa_ie) {
398 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE",
399 ie.wpa_ie, ie.wpa_ie_len);
400 }
401
402 if (ie.rsn_ie) {
403 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE",
404 ie.rsn_ie, ie.rsn_ie_len);
405 }
406
407 if (ie.gtk) {
408 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - GTK KDE",
409 ie.gtk, ie.gtk_len);
410 if (ie.gtk_len >= 2 && ie.gtk_len <= 2 + 32) {
411 int id;
412 id = ie.gtk[0] & 0x03;
413 add_note(wt, MSG_DEBUG, "GTK KeyID=%u tx=%u",
414 id, !!(ie.gtk[0] & 0x04));
415 if ((ie.gtk[0] & 0xf8) || ie.gtk[1]) {
416 add_note(wt, MSG_INFO,
417 "GTK KDE: Reserved field set: "
418 "%02x %02x", ie.gtk[0], ie.gtk[1]);
419 }
420 wpa_hexdump(MSG_DEBUG, "GTK", ie.gtk + 2,
421 ie.gtk_len - 2);
422 bss->gtk_len[id] = ie.gtk_len - 2;
423 sta->gtk_len = ie.gtk_len - 2;
424 os_memcpy(bss->gtk[id], ie.gtk + 2, ie.gtk_len - 2);
425 os_memcpy(sta->gtk, ie.gtk + 2, ie.gtk_len - 2);
426 bss->rsc[id][0] = rsc[5];
427 bss->rsc[id][1] = rsc[4];
428 bss->rsc[id][2] = rsc[3];
429 bss->rsc[id][3] = rsc[2];
430 bss->rsc[id][4] = rsc[1];
431 bss->rsc[id][5] = rsc[0];
432 bss->gtk_idx = id;
433 sta->gtk_idx = id;
434 wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[id], 6);
435 } else {
436 add_note(wt, MSG_INFO, "Invalid GTK KDE length %u",
437 (unsigned) ie.gtk_len);
438 }
439 }
440
441 if (ie.igtk) {
442 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - IGTK KDE",
443 ie.igtk, ie.igtk_len);
444 if (ie.igtk_len == 24) {
445 u16 id;
446 id = WPA_GET_LE16(ie.igtk);
447 if (id > 5) {
448 add_note(wt, MSG_INFO,
449 "Unexpected IGTK KeyID %u", id);
450 } else {
451 const u8 *ipn;
452 add_note(wt, MSG_DEBUG, "IGTK KeyID %u", id);
453 wpa_hexdump(MSG_DEBUG, "IPN", ie.igtk + 2, 6);
454 wpa_hexdump(MSG_DEBUG, "IGTK", ie.igtk + 8,
455 16);
456 os_memcpy(bss->igtk[id], ie.igtk + 8, 16);
457 bss->igtk_set[id] = 1;
458 ipn = ie.igtk + 2;
459 bss->ipn[id][0] = ipn[5];
460 bss->ipn[id][1] = ipn[4];
461 bss->ipn[id][2] = ipn[3];
462 bss->ipn[id][3] = ipn[2];
463 bss->ipn[id][4] = ipn[1];
464 bss->ipn[id][5] = ipn[0];
465 bss->igtk_idx = id;
466 }
467 } else {
468 add_note(wt, MSG_INFO, "Invalid IGTK KDE length %u",
469 (unsigned) ie.igtk_len);
470 }
471 }
472 }
473
474
475 static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
476 const u8 *src, const u8 *data, size_t len)
477 {
478 struct wlantest_bss *bss;
479 struct wlantest_sta *sta;
480 const struct ieee802_1x_hdr *eapol;
481 const struct wpa_eapol_key *hdr;
482 const u8 *key_data, *kck, *kek;
483 int recalc = 0;
484 u16 key_info, ver;
485 u8 *decrypted_buf = NULL;
486 const u8 *decrypted;
487 size_t decrypted_len = 0;
488 struct wpa_eapol_ie_parse ie;
489
490 wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR,
491 MAC2STR(src), MAC2STR(dst));
492 bss = bss_get(wt, src);
493 if (bss == NULL)
494 return;
495 sta = sta_get(bss, dst);
496 if (sta == NULL)
497 return;
498
499 eapol = (const struct ieee802_1x_hdr *) data;
500 hdr = (const struct wpa_eapol_key *) (eapol + 1);
501 key_info = WPA_GET_BE16(hdr->key_info);
502
503 if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) {
504 add_note(wt, MSG_INFO,
505 "EAPOL-Key ANonce mismatch between 1/4 and 3/4");
506 recalc = 1;
507 }
508 os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
509 if (recalc) {
510 derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK,
511 data, len);
512 }
513
514 if (!sta->ptk_set && !sta->tptk_set) {
515 add_note(wt, MSG_DEBUG,
516 "No PTK known to process EAPOL-Key 3/4");
517 return;
518 }
519
520 kek = sta->ptk.kek;
521 kck = sta->ptk.kck;
522 if (sta->tptk_set) {
523 add_note(wt, MSG_DEBUG,
524 "Use TPTK for validation EAPOL-Key MIC");
525 kck = sta->tptk.kck;
526 kek = sta->tptk.kek;
527 }
528 if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
529 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
530 return;
531 }
532 add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4");
533
534 key_data = (const u8 *) (hdr + 1);
535 if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
536 if (sta->proto & WPA_PROTO_RSN)
537 add_note(wt, MSG_INFO,
538 "EAPOL-Key 3/4 without EncrKeyData bit");
539 decrypted = key_data;
540 decrypted_len = WPA_GET_BE16(hdr->key_data_length);
541 } else {
542 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
543 decrypted_buf = decrypt_eapol_key_data(wt, kek, ver, hdr,
544 &decrypted_len);
545 if (decrypted_buf == NULL) {
546 add_note(wt, MSG_INFO,
547 "Failed to decrypt EAPOL-Key Key Data");
548 return;
549 }
550 decrypted = decrypted_buf;
551 wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
552 decrypted, decrypted_len);
553 }
554 if (wt->write_pcap_dumper && decrypted != key_data) {
555 /* Fill in a dummy Data frame header */
556 u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr)];
557 struct ieee80211_hdr *h;
558 struct wpa_eapol_key *k;
559 const u8 *p;
560 u8 *pos;
561 size_t plain_len;
562
563 plain_len = decrypted_len;
564 p = decrypted;
565 while (p + 1 < decrypted + decrypted_len) {
566 if (p[0] == 0xdd && p[1] == 0x00) {
567 /* Remove padding */
568 plain_len = p - decrypted;
569 break;
570 }
571 p += 2 + p[1];
572 }
573
574 os_memset(buf, 0, sizeof(buf));
575 h = (struct ieee80211_hdr *) buf;
576 h->frame_control = host_to_le16(0x0208);
577 os_memcpy(h->addr1, dst, ETH_ALEN);
578 os_memcpy(h->addr2, src, ETH_ALEN);
579 os_memcpy(h->addr3, src, ETH_ALEN);
580 pos = (u8 *) (h + 1);
581 os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8);
582 pos += 8;
583 os_memcpy(pos, eapol, sizeof(*eapol));
584 pos += sizeof(*eapol);
585 os_memcpy(pos, hdr, sizeof(*hdr));
586 k = (struct wpa_eapol_key *) pos;
587 WPA_PUT_BE16(k->key_info,
588 key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA);
589 WPA_PUT_BE16(k->key_data_length, plain_len);
590 write_pcap_decrypted(wt, buf, sizeof(buf),
591 decrypted, plain_len);
592 }
593
594 if (wpa_supplicant_parse_ies(decrypted, decrypted_len, &ie) < 0) {
595 add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
596 os_free(decrypted_buf);
597 return;
598 }
599
600 if ((ie.wpa_ie &&
601 os_memcmp(ie.wpa_ie, bss->wpaie, ie.wpa_ie_len) != 0) ||
602 (ie.wpa_ie == NULL && bss->wpaie[0])) {
603 add_note(wt, MSG_INFO,
604 "Mismatch in WPA IE between EAPOL-Key 3/4 and "
605 "Beacon/Probe Response from " MACSTR,
606 MAC2STR(bss->bssid));
607 wpa_hexdump(MSG_INFO, "WPA IE in EAPOL-Key",
608 ie.wpa_ie, ie.wpa_ie_len);
609 wpa_hexdump(MSG_INFO, "WPA IE in Beacon/Probe "
610 "Response",
611 bss->wpaie,
612 bss->wpaie[0] ? 2 + bss->wpaie[1] : 0);
613 }
614
615 if ((ie.rsn_ie &&
616 os_memcmp(ie.rsn_ie, bss->rsnie, ie.rsn_ie_len) != 0) ||
617 (ie.rsn_ie == NULL && bss->rsnie[0])) {
618 add_note(wt, MSG_INFO, "Mismatch in RSN IE between EAPOL-Key "
619 "3/4 and Beacon/Probe Response from " MACSTR,
620 MAC2STR(bss->bssid));
621 wpa_hexdump(MSG_INFO, "RSN IE in EAPOL-Key",
622 ie.rsn_ie, ie.rsn_ie_len);
623 wpa_hexdump(MSG_INFO, "RSN IE in (Re)Association "
624 "Request",
625 bss->rsnie,
626 bss->rsnie[0] ? 2 + bss->rsnie[1] : 0);
627 }
628
629 learn_kde_keys(wt, bss, sta, decrypted, decrypted_len, hdr->key_rsc);
630 os_free(decrypted_buf);
631 }
632
633
634 static void rx_data_eapol_key_4_of_4(struct wlantest *wt, const u8 *dst,
635 const u8 *src, const u8 *data, size_t len)
636 {
637 struct wlantest_bss *bss;
638 struct wlantest_sta *sta;
639 const struct ieee802_1x_hdr *eapol;
640 const struct wpa_eapol_key *hdr;
641 u16 key_info;
642 const u8 *kck;
643
644 wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
645 MAC2STR(src), MAC2STR(dst));
646 bss = bss_get(wt, dst);
647 if (bss == NULL)
648 return;
649 sta = sta_get(bss, src);
650 if (sta == NULL)
651 return;
652
653 eapol = (const struct ieee802_1x_hdr *) data;
654 hdr = (const struct wpa_eapol_key *) (eapol + 1);
655 if (!is_zero(hdr->key_rsc, 8)) {
656 add_note(wt, MSG_INFO, "EAPOL-Key 4/4 from " MACSTR " used "
657 "non-zero Key RSC", MAC2STR(src));
658 }
659 key_info = WPA_GET_BE16(hdr->key_info);
660
661 if (!sta->ptk_set && !sta->tptk_set) {
662 add_note(wt, MSG_DEBUG,
663 "No PTK known to process EAPOL-Key 4/4");
664 return;
665 }
666
667 kck = sta->ptk.kck;
668 if (sta->tptk_set) {
669 add_note(wt, MSG_DEBUG,
670 "Use TPTK for validation EAPOL-Key MIC");
671 kck = sta->tptk.kck;
672 }
673 if (check_mic(kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
674 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
675 return;
676 }
677 add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4");
678 if (sta->tptk_set) {
679 add_note(wt, MSG_DEBUG, "Update PTK (rekeying)");
680 os_memcpy(&sta->ptk, &sta->tptk, sizeof(sta->ptk));
681 sta->ptk_set = 1;
682 sta->tptk_set = 0;
683 os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
684 os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
685 }
686 }
687
688
689 static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
690 const u8 *src, const u8 *data, size_t len)
691 {
692 struct wlantest_bss *bss;
693 struct wlantest_sta *sta;
694 const struct ieee802_1x_hdr *eapol;
695 const struct wpa_eapol_key *hdr;
696 u16 key_info, ver;
697 u8 *decrypted;
698 size_t decrypted_len = 0;
699
700 wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR,
701 MAC2STR(src), MAC2STR(dst));
702 bss = bss_get(wt, src);
703 if (bss == NULL)
704 return;
705 sta = sta_get(bss, dst);
706 if (sta == NULL)
707 return;
708
709 eapol = (const struct ieee802_1x_hdr *) data;
710 hdr = (const struct wpa_eapol_key *) (eapol + 1);
711 key_info = WPA_GET_BE16(hdr->key_info);
712
713 if (!sta->ptk_set) {
714 add_note(wt, MSG_DEBUG,
715 "No PTK known to process EAPOL-Key 1/2");
716 return;
717 }
718
719 if (sta->ptk_set &&
720 check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
721 data, len) < 0) {
722 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC");
723 return;
724 }
725 add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 1/2");
726
727 if (sta->proto & WPA_PROTO_RSN &&
728 !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
729 add_note(wt, MSG_INFO, "EAPOL-Key 1/2 without EncrKeyData bit");
730 return;
731 }
732 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
733 decrypted = decrypt_eapol_key_data(wt, sta->ptk.kek, ver, hdr,
734 &decrypted_len);
735 if (decrypted == NULL) {
736 add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
737 return;
738 }
739 wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
740 decrypted, decrypted_len);
741 if (wt->write_pcap_dumper) {
742 /* Fill in a dummy Data frame header */
743 u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr)];
744 struct ieee80211_hdr *h;
745 struct wpa_eapol_key *k;
746 u8 *pos;
747 size_t plain_len;
748
749 plain_len = decrypted_len;
750 pos = decrypted;
751 while (pos + 1 < decrypted + decrypted_len) {
752 if (pos[0] == 0xdd && pos[1] == 0x00) {
753 /* Remove padding */
754 plain_len = pos - decrypted;
755 break;
756 }
757 pos += 2 + pos[1];
758 }
759
760 os_memset(buf, 0, sizeof(buf));
761 h = (struct ieee80211_hdr *) buf;
762 h->frame_control = host_to_le16(0x0208);
763 os_memcpy(h->addr1, dst, ETH_ALEN);
764 os_memcpy(h->addr2, src, ETH_ALEN);
765 os_memcpy(h->addr3, src, ETH_ALEN);
766 pos = (u8 *) (h + 1);
767 os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8);
768 pos += 8;
769 os_memcpy(pos, eapol, sizeof(*eapol));
770 pos += sizeof(*eapol);
771 os_memcpy(pos, hdr, sizeof(*hdr));
772 k = (struct wpa_eapol_key *) pos;
773 WPA_PUT_BE16(k->key_info,
774 key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA);
775 WPA_PUT_BE16(k->key_data_length, plain_len);
776 write_pcap_decrypted(wt, buf, sizeof(buf),
777 decrypted, plain_len);
778 }
779 if (sta->proto & WPA_PROTO_RSN)
780 learn_kde_keys(wt, bss, sta, decrypted, decrypted_len,
781 hdr->key_rsc);
782 else {
783 int klen = bss->group_cipher == WPA_CIPHER_TKIP ? 32 : 16;
784 if (decrypted_len == klen) {
785 const u8 *rsc = hdr->key_rsc;
786 int id;
787 id = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
788 WPA_KEY_INFO_KEY_INDEX_SHIFT;
789 add_note(wt, MSG_DEBUG, "GTK key index %d", id);
790 wpa_hexdump(MSG_DEBUG, "GTK", decrypted,
791 decrypted_len);
792 bss->gtk_len[id] = decrypted_len;
793 os_memcpy(bss->gtk[id], decrypted, decrypted_len);
794 bss->rsc[id][0] = rsc[5];
795 bss->rsc[id][1] = rsc[4];
796 bss->rsc[id][2] = rsc[3];
797 bss->rsc[id][3] = rsc[2];
798 bss->rsc[id][4] = rsc[1];
799 bss->rsc[id][5] = rsc[0];
800 wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[id], 6);
801 } else {
802 add_note(wt, MSG_INFO, "Unexpected WPA Key Data length "
803 "in Group Key msg 1/2 from " MACSTR,
804 MAC2STR(src));
805 }
806 }
807 os_free(decrypted);
808 }
809
810
811 static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
812 const u8 *src, const u8 *data, size_t len)
813 {
814 struct wlantest_bss *bss;
815 struct wlantest_sta *sta;
816 const struct ieee802_1x_hdr *eapol;
817 const struct wpa_eapol_key *hdr;
818 u16 key_info;
819
820 wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR,
821 MAC2STR(src), MAC2STR(dst));
822 bss = bss_get(wt, dst);
823 if (bss == NULL)
824 return;
825 sta = sta_get(bss, src);
826 if (sta == NULL)
827 return;
828
829 eapol = (const struct ieee802_1x_hdr *) data;
830 hdr = (const struct wpa_eapol_key *) (eapol + 1);
831 if (!is_zero(hdr->key_rsc, 8)) {
832 add_note(wt, MSG_INFO, "EAPOL-Key 2/2 from " MACSTR " used "
833 "non-zero Key RSC", MAC2STR(src));
834 }
835 key_info = WPA_GET_BE16(hdr->key_info);
836
837 if (!sta->ptk_set) {
838 add_note(wt, MSG_DEBUG,
839 "No PTK known to process EAPOL-Key 2/2");
840 return;
841 }
842
843 if (sta->ptk_set &&
844 check_mic(sta->ptk.kck, key_info & WPA_KEY_INFO_TYPE_MASK,
845 data, len) < 0) {
846 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC");
847 return;
848 }
849 add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/2");
850 }
851
852
853 static void rx_data_eapol_key(struct wlantest *wt, const u8 *dst,
854 const u8 *src, const u8 *data, size_t len,
855 int prot)
856 {
857 const struct ieee802_1x_hdr *eapol;
858 const struct wpa_eapol_key *hdr;
859 const u8 *key_data;
860 u16 key_info, key_length, ver, key_data_length;
861
862 eapol = (const struct ieee802_1x_hdr *) data;
863 hdr = (const struct wpa_eapol_key *) (eapol + 1);
864
865 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key",
866 (const u8 *) hdr, len - sizeof(*eapol));
867 if (len < sizeof(*hdr)) {
868 add_note(wt, MSG_INFO, "Too short EAPOL-Key frame from " MACSTR,
869 MAC2STR(src));
870 return;
871 }
872
873 if (hdr->type == EAPOL_KEY_TYPE_RC4) {
874 /* TODO: EAPOL-Key RC4 for WEP */
875 wpa_printf(MSG_INFO, "EAPOL-Key Descriptor Type RC4 from "
876 MACSTR, MAC2STR(src));
877 return;
878 }
879
880 if (hdr->type != EAPOL_KEY_TYPE_RSN &&
881 hdr->type != EAPOL_KEY_TYPE_WPA) {
882 wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Descriptor Type "
883 "%u from " MACSTR, hdr->type, MAC2STR(src));
884 return;
885 }
886
887 key_info = WPA_GET_BE16(hdr->key_info);
888 key_length = WPA_GET_BE16(hdr->key_length);
889 key_data_length = WPA_GET_BE16(hdr->key_data_length);
890 key_data = (const u8 *) (hdr + 1);
891 if (key_data + key_data_length > data + len) {
892 add_note(wt, MSG_INFO, "Truncated EAPOL-Key from " MACSTR,
893 MAC2STR(src));
894 return;
895 }
896 if (key_data + key_data_length < data + len) {
897 wpa_hexdump(MSG_DEBUG, "Extra data after EAPOL-Key Key Data "
898 "field", key_data + key_data_length,
899 data + len - key_data - key_data_length);
900 }
901
902
903 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
904 wpa_printf(MSG_DEBUG, "EAPOL-Key ver=%u %c idx=%u%s%s%s%s%s%s%s%s "
905 "datalen=%u",
906 ver, key_info & WPA_KEY_INFO_KEY_TYPE ? 'P' : 'G',
907 (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
908 WPA_KEY_INFO_KEY_INDEX_SHIFT,
909 (key_info & WPA_KEY_INFO_INSTALL) ? " Install" : "",
910 (key_info & WPA_KEY_INFO_ACK) ? " ACK" : "",
911 (key_info & WPA_KEY_INFO_MIC) ? " MIC" : "",
912 (key_info & WPA_KEY_INFO_SECURE) ? " Secure" : "",
913 (key_info & WPA_KEY_INFO_ERROR) ? " Error" : "",
914 (key_info & WPA_KEY_INFO_REQUEST) ? " Request" : "",
915 (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ? " Encr" : "",
916 (key_info & WPA_KEY_INFO_SMK_MESSAGE) ? " SMK" : "",
917 key_data_length);
918
919 if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
920 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
921 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
922 wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Key Descriptor "
923 "Version %u from " MACSTR, ver, MAC2STR(src));
924 return;
925 }
926
927 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Replay Counter",
928 hdr->replay_counter, WPA_REPLAY_COUNTER_LEN);
929 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Nonce",
930 hdr->key_nonce, WPA_NONCE_LEN);
931 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key IV",
932 hdr->key_iv, 16);
933 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC",
934 hdr->key_rsc, WPA_KEY_RSC_LEN);
935 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC",
936 hdr->key_mic, 16);
937 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data",
938 key_data, key_data_length);
939
940 if (hdr->type == EAPOL_KEY_TYPE_RSN &&
941 (key_info & (WPA_KEY_INFO_KEY_INDEX_MASK | BIT(14) | BIT(15))) !=
942 0) {
943 wpa_printf(MSG_INFO, "RSN EAPOL-Key with non-zero reserved "
944 "Key Info bits 0x%x from " MACSTR,
945 key_info, MAC2STR(src));
946 }
947
948 if (hdr->type == EAPOL_KEY_TYPE_WPA &&
949 (key_info & (WPA_KEY_INFO_ENCR_KEY_DATA |
950 WPA_KEY_INFO_SMK_MESSAGE |BIT(14) | BIT(15))) != 0) {
951 wpa_printf(MSG_INFO, "WPA EAPOL-Key with non-zero reserved "
952 "Key Info bits 0x%x from " MACSTR,
953 key_info, MAC2STR(src));
954 }
955
956 if (key_length > 32) {
957 wpa_printf(MSG_INFO, "EAPOL-Key with invalid Key Length %d "
958 "from " MACSTR, key_length, MAC2STR(src));
959 }
960
961 if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
962 !is_zero(hdr->key_iv, 16)) {
963 wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key IV "
964 "(reserved with ver=%d) field from " MACSTR,
965 ver, MAC2STR(src));
966 wpa_hexdump(MSG_INFO, "EAPOL-Key Key IV (reserved)",
967 hdr->key_iv, 16);
968 }
969
970 if (!is_zero(hdr->key_id, 8)) {
971 wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key ID "
972 "(reserved) field from " MACSTR, MAC2STR(src));
973 wpa_hexdump(MSG_INFO, "EAPOL-Key Key ID (reserved)",
974 hdr->key_id, 8);
975 }
976
977 if (hdr->key_rsc[6] || hdr->key_rsc[7]) {
978 wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key RSC octets "
979 "(last two are unused)" MACSTR, MAC2STR(src));
980 }
981
982 if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST))
983 return;
984
985 if (key_info & WPA_KEY_INFO_SMK_MESSAGE)
986 return;
987
988 if (key_info & WPA_KEY_INFO_KEY_TYPE) {
989 /* 4-Way Handshake */
990 switch (key_info & (WPA_KEY_INFO_SECURE |
991 WPA_KEY_INFO_MIC |
992 WPA_KEY_INFO_ACK |
993 WPA_KEY_INFO_INSTALL)) {
994 case WPA_KEY_INFO_ACK:
995 rx_data_eapol_key_1_of_4(wt, dst, src, data, len);
996 break;
997 case WPA_KEY_INFO_MIC:
998 if (key_data_length == 0)
999 rx_data_eapol_key_4_of_4(wt, dst, src, data,
1000 len);
1001 else
1002 rx_data_eapol_key_2_of_4(wt, dst, src, data,
1003 len);
1004 break;
1005 case WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK |
1006 WPA_KEY_INFO_INSTALL:
1007 /* WPA does not include Secure bit in 3/4 */
1008 rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
1009 break;
1010 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
1011 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL:
1012 rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
1013 break;
1014 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
1015 if (key_data_length == 0)
1016 rx_data_eapol_key_4_of_4(wt, dst, src, data,
1017 len);
1018 else
1019 rx_data_eapol_key_2_of_4(wt, dst, src, data,
1020 len);
1021 break;
1022 default:
1023 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
1024 break;
1025 }
1026 } else {
1027 /* Group Key Handshake */
1028 switch (key_info & (WPA_KEY_INFO_SECURE |
1029 WPA_KEY_INFO_MIC |
1030 WPA_KEY_INFO_ACK)) {
1031 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
1032 WPA_KEY_INFO_ACK:
1033 rx_data_eapol_key_1_of_2(wt, dst, src, data, len);
1034 break;
1035 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
1036 rx_data_eapol_key_2_of_2(wt, dst, src, data, len);
1037 break;
1038 default:
1039 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
1040 break;
1041 }
1042 }
1043 }
1044
1045
1046 void rx_data_eapol(struct wlantest *wt, const u8 *dst, const u8 *src,
1047 const u8 *data, size_t len, int prot)
1048 {
1049 const struct ieee802_1x_hdr *hdr;
1050 u16 length;
1051 const u8 *p;
1052
1053 wpa_hexdump(MSG_EXCESSIVE, "EAPOL", data, len);
1054 if (len < sizeof(*hdr)) {
1055 wpa_printf(MSG_INFO, "Too short EAPOL frame from " MACSTR,
1056 MAC2STR(src));
1057 return;
1058 }
1059
1060 hdr = (const struct ieee802_1x_hdr *) data;
1061 length = be_to_host16(hdr->length);
1062 wpa_printf(MSG_DEBUG, "RX EAPOL: " MACSTR " -> " MACSTR "%s ver=%u "
1063 "type=%u len=%u",
1064 MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "",
1065 hdr->version, hdr->type, length);
1066 if (hdr->version < 1 || hdr->version > 3) {
1067 wpa_printf(MSG_INFO, "Unexpected EAPOL version %u from "
1068 MACSTR, hdr->version, MAC2STR(src));
1069 }
1070 if (sizeof(*hdr) + length > len) {
1071 wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR,
1072 MAC2STR(src));
1073 return;
1074 }
1075
1076 if (sizeof(*hdr) + length < len) {
1077 wpa_printf(MSG_INFO, "EAPOL frame with %d extra bytes",
1078 (int) (len - sizeof(*hdr) - length));
1079 }
1080 p = (const u8 *) (hdr + 1);
1081
1082 switch (hdr->type) {
1083 case IEEE802_1X_TYPE_EAP_PACKET:
1084 wpa_hexdump(MSG_MSGDUMP, "EAPOL - EAP packet", p, length);
1085 break;
1086 case IEEE802_1X_TYPE_EAPOL_START:
1087 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Start", p, length);
1088 break;
1089 case IEEE802_1X_TYPE_EAPOL_LOGOFF:
1090 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Logoff", p, length);
1091 break;
1092 case IEEE802_1X_TYPE_EAPOL_KEY:
1093 rx_data_eapol_key(wt, dst, src, data, sizeof(*hdr) + length,
1094 prot);
1095 break;
1096 case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
1097 wpa_hexdump(MSG_MSGDUMP, "EAPOL - Encapsulated ASF alert",
1098 p, length);
1099 break;
1100 default:
1101 wpa_hexdump(MSG_MSGDUMP, "Unknown EAPOL payload", p, length);
1102 break;
1103 }
1104 }