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