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