]> git.ipfire.org Git - thirdparty/hostap.git/blame - wlantest/rx_eapol.c
tests: Use proper temp files for dynamically created config
[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 }
faf6894f
JM
551
552 if (ie.bigtk) {
553 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - BIGTK KDE",
554 ie.bigtk, ie.bigtk_len);
555 if (ie.bigtk_len == 24) {
556 u16 id;
557
558 id = WPA_GET_LE16(ie.bigtk);
559 if (id < 6 || id > 7) {
560 add_note(wt, MSG_INFO,
561 "Unexpected BIGTK KeyID %u", id);
562 } else {
563 const u8 *ipn;
564
565 add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", id);
566 wpa_hexdump(MSG_DEBUG, "BIPN", ie.bigtk + 2, 6);
567 wpa_hexdump(MSG_DEBUG, "BIGTK", ie.bigtk + 8,
568 16);
569 os_memcpy(bss->igtk[id], ie.bigtk + 8, 16);
570 bss->igtk_len[id] = 16;
571 ipn = ie.bigtk + 2;
572 bss->ipn[id][0] = ipn[5];
573 bss->ipn[id][1] = ipn[4];
574 bss->ipn[id][2] = ipn[3];
575 bss->ipn[id][3] = ipn[2];
576 bss->ipn[id][4] = ipn[1];
577 bss->ipn[id][5] = ipn[0];
578 bss->bigtk_idx = id;
579 }
580 } else if (ie.bigtk_len == 40) {
581 u16 id;
582
583 id = WPA_GET_LE16(ie.bigtk);
584 if (id < 6 || id > 7) {
585 add_note(wt, MSG_INFO,
586 "Unexpected BIGTK KeyID %u", id);
587 } else {
588 const u8 *ipn;
589
590 add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", id);
591 wpa_hexdump(MSG_DEBUG, "BIPN", ie.bigtk + 2, 6);
592 wpa_hexdump(MSG_DEBUG, "BIGTK", ie.bigtk + 8,
593 32);
594 os_memcpy(bss->igtk[id], ie.bigtk + 8, 32);
595 bss->igtk_len[id] = 32;
596 ipn = ie.bigtk + 2;
597 bss->ipn[id][0] = ipn[5];
598 bss->ipn[id][1] = ipn[4];
599 bss->ipn[id][2] = ipn[3];
600 bss->ipn[id][3] = ipn[2];
601 bss->ipn[id][4] = ipn[1];
602 bss->ipn[id][5] = ipn[0];
603 bss->bigtk_idx = id;
604 }
605 } else {
606 add_note(wt, MSG_INFO, "Invalid BIGTK KDE length %u",
607 (unsigned) ie.bigtk_len);
608 }
609 }
161d0339
JM
610}
611
612
613static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst,
614 const u8 *src, const u8 *data, size_t len)
615{
616 struct wlantest_bss *bss;
617 struct wlantest_sta *sta;
618 const struct ieee802_1x_hdr *eapol;
619 const struct wpa_eapol_key *hdr;
6d014ffc
JM
620 const u8 *key_data, *kck, *kek, *mic;
621 size_t kck_len, kek_len, mic_len;
161d0339
JM
622 int recalc = 0;
623 u16 key_info, ver;
624 u8 *decrypted_buf = NULL;
625 const u8 *decrypted;
626 size_t decrypted_len = 0;
627 struct wpa_eapol_ie_parse ie;
628
629 wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR,
630 MAC2STR(src), MAC2STR(dst));
631 bss = bss_get(wt, src);
632 if (bss == NULL)
633 return;
634 sta = sta_get(bss, dst);
635 if (sta == NULL)
636 return;
567da5bb 637 mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN);
161d0339
JM
638
639 eapol = (const struct ieee802_1x_hdr *) data;
640 hdr = (const struct wpa_eapol_key *) (eapol + 1);
6d014ffc 641 mic = (const u8 *) (hdr + 1);
161d0339
JM
642 key_info = WPA_GET_BE16(hdr->key_info);
643
644 if (os_memcmp(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN) != 0) {
e4d99217
JM
645 add_note(wt, MSG_INFO,
646 "EAPOL-Key ANonce mismatch between 1/4 and 3/4");
161d0339
JM
647 recalc = 1;
648 }
649 os_memcpy(sta->anonce, hdr->key_nonce, WPA_NONCE_LEN);
650 if (recalc) {
651 derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK,
652 data, len);
653 }
654
d0b251d2 655 if (!sta->ptk_set && !sta->tptk_set) {
e4d99217
JM
656 add_note(wt, MSG_DEBUG,
657 "No PTK known to process EAPOL-Key 3/4");
161d0339
JM
658 return;
659 }
660
3c56f0e2 661 kek = sta->ptk.kek;
98cd3d1c 662 kek_len = sta->ptk.kek_len;
d0b251d2 663 kck = sta->ptk.kck;
98cd3d1c 664 kck_len = sta->ptk.kck_len;
d0b251d2 665 if (sta->tptk_set) {
e4d99217
JM
666 add_note(wt, MSG_DEBUG,
667 "Use TPTK for validation EAPOL-Key MIC");
d0b251d2 668 kck = sta->tptk.kck;
98cd3d1c 669 kck_len = sta->tptk.kck_len;
3c56f0e2 670 kek = sta->tptk.kek;
98cd3d1c 671 kek_len = sta->tptk.kek_len;
d0b251d2 672 }
98cd3d1c
JM
673 if (check_mic(kck, kck_len, sta->key_mgmt,
674 key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
e4d99217 675 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 3/4 MIC");
161d0339
JM
676 return;
677 }
e4d99217 678 add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 3/4");
161d0339 679
6d014ffc 680 key_data = mic + mic_len + 2;
161d0339
JM
681 if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
682 if (sta->proto & WPA_PROTO_RSN)
e4d99217
JM
683 add_note(wt, MSG_INFO,
684 "EAPOL-Key 3/4 without EncrKeyData bit");
161d0339 685 decrypted = key_data;
6d014ffc 686 decrypted_len = WPA_GET_BE16(mic + mic_len);
161d0339
JM
687 } else {
688 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
6d014ffc
JM
689 decrypted_buf = decrypt_eapol_key_data(wt, sta->key_mgmt,
690 kek, kek_len, ver,
98cd3d1c 691 hdr, &decrypted_len);
161d0339 692 if (decrypted_buf == NULL) {
e4d99217
JM
693 add_note(wt, MSG_INFO,
694 "Failed to decrypt EAPOL-Key Key Data");
161d0339
JM
695 return;
696 }
697 decrypted = decrypted_buf;
698 wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
699 decrypted, decrypted_len);
700 }
dd4722df 701 if ((wt->write_pcap_dumper || wt->pcapng) && decrypted != key_data) {
161d0339 702 /* Fill in a dummy Data frame header */
19e7ddf7 703 u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr) + 64];
161d0339
JM
704 struct ieee80211_hdr *h;
705 struct wpa_eapol_key *k;
706 const u8 *p;
707 u8 *pos;
708 size_t plain_len;
709
710 plain_len = decrypted_len;
711 p = decrypted;
712 while (p + 1 < decrypted + decrypted_len) {
713 if (p[0] == 0xdd && p[1] == 0x00) {
714 /* Remove padding */
715 plain_len = p - decrypted;
faf0fef1 716 p = NULL;
161d0339
JM
717 break;
718 }
719 p += 2 + p[1];
720 }
faf0fef1
JM
721 if (p && p > decrypted && *p == 0xdd &&
722 p + 1 == decrypted + decrypted_len) {
723 /* Remove padding */
724 p--;
725 plain_len = p - decrypted;
726 }
161d0339
JM
727
728 os_memset(buf, 0, sizeof(buf));
729 h = (struct ieee80211_hdr *) buf;
730 h->frame_control = host_to_le16(0x0208);
731 os_memcpy(h->addr1, dst, ETH_ALEN);
732 os_memcpy(h->addr2, src, ETH_ALEN);
733 os_memcpy(h->addr3, src, ETH_ALEN);
734 pos = (u8 *) (h + 1);
735 os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8);
736 pos += 8;
737 os_memcpy(pos, eapol, sizeof(*eapol));
738 pos += sizeof(*eapol);
6d014ffc 739 os_memcpy(pos, hdr, sizeof(*hdr) + mic_len);
161d0339 740 k = (struct wpa_eapol_key *) pos;
6d014ffc 741 pos += sizeof(struct wpa_eapol_key) + mic_len;
161d0339
JM
742 WPA_PUT_BE16(k->key_info,
743 key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA);
6d014ffc 744 WPA_PUT_BE16(pos, plain_len);
19e7ddf7
JM
745 write_pcap_decrypted(wt, buf, 24 + 8 + sizeof(*eapol) +
746 sizeof(*hdr) + mic_len + 2,
161d0339
JM
747 decrypted, plain_len);
748 }
749
750 if (wpa_supplicant_parse_ies(decrypted, decrypted_len, &ie) < 0) {
e4d99217 751 add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data");
161d0339
JM
752 os_free(decrypted_buf);
753 return;
754 }
755
756 if ((ie.wpa_ie &&
757 os_memcmp(ie.wpa_ie, bss->wpaie, ie.wpa_ie_len) != 0) ||
758 (ie.wpa_ie == NULL && bss->wpaie[0])) {
e4d99217
JM
759 add_note(wt, MSG_INFO,
760 "Mismatch in WPA IE between EAPOL-Key 3/4 and "
761 "Beacon/Probe Response from " MACSTR,
762 MAC2STR(bss->bssid));
161d0339
JM
763 wpa_hexdump(MSG_INFO, "WPA IE in EAPOL-Key",
764 ie.wpa_ie, ie.wpa_ie_len);
765 wpa_hexdump(MSG_INFO, "WPA IE in Beacon/Probe "
766 "Response",
767 bss->wpaie,
768 bss->wpaie[0] ? 2 + bss->wpaie[1] : 0);
769 }
770
771 if ((ie.rsn_ie &&
772 os_memcmp(ie.rsn_ie, bss->rsnie, ie.rsn_ie_len) != 0) ||
773 (ie.rsn_ie == NULL && bss->rsnie[0])) {
e4d99217
JM
774 add_note(wt, MSG_INFO, "Mismatch in RSN IE between EAPOL-Key "
775 "3/4 and Beacon/Probe Response from " MACSTR,
776 MAC2STR(bss->bssid));
161d0339
JM
777 wpa_hexdump(MSG_INFO, "RSN IE in EAPOL-Key",
778 ie.rsn_ie, ie.rsn_ie_len);
7d273679 779 wpa_hexdump(MSG_INFO, "RSN IE in Beacon/Probe Response",
161d0339
JM
780 bss->rsnie,
781 bss->rsnie[0] ? 2 + bss->rsnie[1] : 0);
782 }
783
e4d99217 784 learn_kde_keys(wt, bss, sta, decrypted, decrypted_len, hdr->key_rsc);
161d0339
JM
785 os_free(decrypted_buf);
786}
787
788
789static void rx_data_eapol_key_4_of_4(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;
796 u16 key_info;
d0b251d2 797 const u8 *kck;
98cd3d1c 798 size_t kck_len;
161d0339
JM
799
800 wpa_printf(MSG_DEBUG, "EAPOL-Key 4/4 " MACSTR " -> " MACSTR,
801 MAC2STR(src), MAC2STR(dst));
802 bss = bss_get(wt, dst);
803 if (bss == NULL)
804 return;
805 sta = sta_get(bss, src);
806 if (sta == NULL)
807 return;
808
809 eapol = (const struct ieee802_1x_hdr *) data;
810 hdr = (const struct wpa_eapol_key *) (eapol + 1);
811 if (!is_zero(hdr->key_rsc, 8)) {
c41e1d7c
JM
812 add_note(wt, MSG_INFO, "EAPOL-Key 4/4 from " MACSTR " used "
813 "non-zero Key RSC", MAC2STR(src));
161d0339
JM
814 }
815 key_info = WPA_GET_BE16(hdr->key_info);
816
d0b251d2 817 if (!sta->ptk_set && !sta->tptk_set) {
c41e1d7c
JM
818 add_note(wt, MSG_DEBUG,
819 "No PTK known to process EAPOL-Key 4/4");
161d0339
JM
820 return;
821 }
822
d0b251d2 823 kck = sta->ptk.kck;
98cd3d1c 824 kck_len = sta->ptk.kck_len;
d0b251d2 825 if (sta->tptk_set) {
c41e1d7c
JM
826 add_note(wt, MSG_DEBUG,
827 "Use TPTK for validation EAPOL-Key MIC");
d0b251d2 828 kck = sta->tptk.kck;
98cd3d1c 829 kck_len = sta->tptk.kck_len;
d0b251d2 830 }
98cd3d1c
JM
831 if (check_mic(kck, kck_len, sta->key_mgmt,
832 key_info & WPA_KEY_INFO_TYPE_MASK, data, len) < 0) {
c41e1d7c 833 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 4/4 MIC");
161d0339
JM
834 return;
835 }
c41e1d7c 836 add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 4/4");
d0b251d2 837 if (sta->tptk_set) {
c41e1d7c 838 add_note(wt, MSG_DEBUG, "Update PTK (rekeying)");
d0b251d2
JM
839 os_memcpy(&sta->ptk, &sta->tptk, sizeof(sta->ptk));
840 sta->ptk_set = 1;
841 sta->tptk_set = 0;
842 os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods));
843 os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds));
844 }
161d0339
JM
845}
846
847
848static void rx_data_eapol_key_1_of_2(struct wlantest *wt, const u8 *dst,
849 const u8 *src, const u8 *data, size_t len)
850{
851 struct wlantest_bss *bss;
852 struct wlantest_sta *sta;
853 const struct ieee802_1x_hdr *eapol;
854 const struct wpa_eapol_key *hdr;
161d0339
JM
855 u16 key_info, ver;
856 u8 *decrypted;
857 size_t decrypted_len = 0;
6d014ffc 858 size_t mic_len;
161d0339
JM
859
860 wpa_printf(MSG_DEBUG, "EAPOL-Key 1/2 " MACSTR " -> " MACSTR,
861 MAC2STR(src), MAC2STR(dst));
862 bss = bss_get(wt, src);
863 if (bss == NULL)
864 return;
865 sta = sta_get(bss, dst);
866 if (sta == NULL)
867 return;
567da5bb 868 mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN);
161d0339
JM
869
870 eapol = (const struct ieee802_1x_hdr *) data;
871 hdr = (const struct wpa_eapol_key *) (eapol + 1);
872 key_info = WPA_GET_BE16(hdr->key_info);
873
874 if (!sta->ptk_set) {
c41e1d7c
JM
875 add_note(wt, MSG_DEBUG,
876 "No PTK known to process EAPOL-Key 1/2");
161d0339
JM
877 return;
878 }
879
880 if (sta->ptk_set &&
98cd3d1c 881 check_mic(sta->ptk.kck, sta->ptk.kck_len, sta->key_mgmt,
929a2ea5 882 key_info & WPA_KEY_INFO_TYPE_MASK,
161d0339 883 data, len) < 0) {
c41e1d7c 884 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 1/2 MIC");
161d0339
JM
885 return;
886 }
c41e1d7c 887 add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 1/2");
161d0339 888
161d0339
JM
889 if (sta->proto & WPA_PROTO_RSN &&
890 !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
c41e1d7c 891 add_note(wt, MSG_INFO, "EAPOL-Key 1/2 without EncrKeyData bit");
161d0339
JM
892 return;
893 }
894 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
6d014ffc
JM
895 decrypted = decrypt_eapol_key_data(wt, sta->key_mgmt,
896 sta->ptk.kek, sta->ptk.kek_len,
98cd3d1c 897 ver, hdr, &decrypted_len);
161d0339 898 if (decrypted == NULL) {
c41e1d7c 899 add_note(wt, MSG_INFO, "Failed to decrypt EAPOL-Key Key Data");
161d0339
JM
900 return;
901 }
902 wpa_hexdump(MSG_DEBUG, "Decrypted EAPOL-Key Key Data",
903 decrypted, decrypted_len);
dd4722df 904 if (wt->write_pcap_dumper || wt->pcapng) {
161d0339 905 /* Fill in a dummy Data frame header */
19e7ddf7 906 u8 buf[24 + 8 + sizeof(*eapol) + sizeof(*hdr) + 64];
161d0339
JM
907 struct ieee80211_hdr *h;
908 struct wpa_eapol_key *k;
909 u8 *pos;
910 size_t plain_len;
911
912 plain_len = decrypted_len;
913 pos = decrypted;
914 while (pos + 1 < decrypted + decrypted_len) {
915 if (pos[0] == 0xdd && pos[1] == 0x00) {
916 /* Remove padding */
917 plain_len = pos - decrypted;
918 break;
919 }
920 pos += 2 + pos[1];
921 }
922
923 os_memset(buf, 0, sizeof(buf));
924 h = (struct ieee80211_hdr *) buf;
925 h->frame_control = host_to_le16(0x0208);
926 os_memcpy(h->addr1, dst, ETH_ALEN);
927 os_memcpy(h->addr2, src, ETH_ALEN);
928 os_memcpy(h->addr3, src, ETH_ALEN);
929 pos = (u8 *) (h + 1);
930 os_memcpy(pos, "\xaa\xaa\x03\x00\x00\x00\x88\x8e", 8);
931 pos += 8;
932 os_memcpy(pos, eapol, sizeof(*eapol));
933 pos += sizeof(*eapol);
6d014ffc 934 os_memcpy(pos, hdr, sizeof(*hdr) + mic_len);
161d0339 935 k = (struct wpa_eapol_key *) pos;
6d014ffc 936 pos += sizeof(struct wpa_eapol_key) + mic_len;
161d0339
JM
937 WPA_PUT_BE16(k->key_info,
938 key_info & ~WPA_KEY_INFO_ENCR_KEY_DATA);
6d014ffc 939 WPA_PUT_BE16(pos, plain_len);
19e7ddf7
JM
940 write_pcap_decrypted(wt, buf, 24 + 8 + sizeof(*eapol) +
941 sizeof(*hdr) + mic_len + 2,
161d0339
JM
942 decrypted, plain_len);
943 }
944 if (sta->proto & WPA_PROTO_RSN)
e4d99217 945 learn_kde_keys(wt, bss, sta, decrypted, decrypted_len,
fd848ab9 946 hdr->key_rsc);
161d0339 947 else {
30e09b0d
JM
948 int klen = bss->group_cipher == WPA_CIPHER_TKIP ? 32 : 16;
949 if (decrypted_len == klen) {
161d0339
JM
950 const u8 *rsc = hdr->key_rsc;
951 int id;
952 id = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
953 WPA_KEY_INFO_KEY_INDEX_SHIFT;
c41e1d7c 954 add_note(wt, MSG_DEBUG, "GTK key index %d", id);
161d0339
JM
955 wpa_hexdump(MSG_DEBUG, "GTK", decrypted,
956 decrypted_len);
957 bss->gtk_len[id] = decrypted_len;
958 os_memcpy(bss->gtk[id], decrypted, decrypted_len);
959 bss->rsc[id][0] = rsc[5];
960 bss->rsc[id][1] = rsc[4];
961 bss->rsc[id][2] = rsc[3];
962 bss->rsc[id][3] = rsc[2];
963 bss->rsc[id][4] = rsc[1];
964 bss->rsc[id][5] = rsc[0];
965 wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[id], 6);
966 } else {
c41e1d7c
JM
967 add_note(wt, MSG_INFO, "Unexpected WPA Key Data length "
968 "in Group Key msg 1/2 from " MACSTR,
969 MAC2STR(src));
161d0339
JM
970 }
971 }
972 os_free(decrypted);
973}
974
975
976static void rx_data_eapol_key_2_of_2(struct wlantest *wt, const u8 *dst,
977 const u8 *src, const u8 *data, size_t len)
978{
979 struct wlantest_bss *bss;
980 struct wlantest_sta *sta;
981 const struct ieee802_1x_hdr *eapol;
982 const struct wpa_eapol_key *hdr;
983 u16 key_info;
984
985 wpa_printf(MSG_DEBUG, "EAPOL-Key 2/2 " MACSTR " -> " MACSTR,
986 MAC2STR(src), MAC2STR(dst));
987 bss = bss_get(wt, dst);
988 if (bss == NULL)
989 return;
990 sta = sta_get(bss, src);
991 if (sta == NULL)
992 return;
993
994 eapol = (const struct ieee802_1x_hdr *) data;
995 hdr = (const struct wpa_eapol_key *) (eapol + 1);
996 if (!is_zero(hdr->key_rsc, 8)) {
c41e1d7c
JM
997 add_note(wt, MSG_INFO, "EAPOL-Key 2/2 from " MACSTR " used "
998 "non-zero Key RSC", MAC2STR(src));
161d0339
JM
999 }
1000 key_info = WPA_GET_BE16(hdr->key_info);
1001
1002 if (!sta->ptk_set) {
c41e1d7c
JM
1003 add_note(wt, MSG_DEBUG,
1004 "No PTK known to process EAPOL-Key 2/2");
161d0339
JM
1005 return;
1006 }
1007
1008 if (sta->ptk_set &&
98cd3d1c 1009 check_mic(sta->ptk.kck, sta->ptk.kck_len, sta->key_mgmt,
929a2ea5 1010 key_info & WPA_KEY_INFO_TYPE_MASK,
161d0339 1011 data, len) < 0) {
c41e1d7c 1012 add_note(wt, MSG_INFO, "Mismatch in EAPOL-Key 2/2 MIC");
161d0339
JM
1013 return;
1014 }
c41e1d7c 1015 add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/2");
161d0339
JM
1016}
1017
1018
6d014ffc
JM
1019static void rx_data_eapol_key(struct wlantest *wt, const u8 *bssid,
1020 const u8 *sta_addr, const u8 *dst,
161d0339
JM
1021 const u8 *src, const u8 *data, size_t len,
1022 int prot)
1023{
1024 const struct ieee802_1x_hdr *eapol;
1025 const struct wpa_eapol_key *hdr;
1026 const u8 *key_data;
1027 u16 key_info, key_length, ver, key_data_length;
6d014ffc
JM
1028 size_t mic_len = 16;
1029 const u8 *mic;
1030 struct wlantest_bss *bss;
1031 struct wlantest_sta *sta;
1032
1033 bss = bss_get(wt, bssid);
1034 if (bss) {
1035 sta = sta_get(bss, sta_addr);
1036 if (sta)
567da5bb 1037 mic_len = wpa_mic_len(sta->key_mgmt, PMK_LEN);
6d014ffc 1038 }
161d0339
JM
1039
1040 eapol = (const struct ieee802_1x_hdr *) data;
1041 hdr = (const struct wpa_eapol_key *) (eapol + 1);
1042
1043 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key",
1044 (const u8 *) hdr, len - sizeof(*eapol));
6d014ffc 1045 if (len < sizeof(*hdr) + mic_len + 2) {
c41e1d7c
JM
1046 add_note(wt, MSG_INFO, "Too short EAPOL-Key frame from " MACSTR,
1047 MAC2STR(src));
161d0339
JM
1048 return;
1049 }
6d014ffc 1050 mic = (const u8 *) (hdr + 1);
161d0339
JM
1051
1052 if (hdr->type == EAPOL_KEY_TYPE_RC4) {
1053 /* TODO: EAPOL-Key RC4 for WEP */
1054 wpa_printf(MSG_INFO, "EAPOL-Key Descriptor Type RC4 from "
1055 MACSTR, MAC2STR(src));
1056 return;
1057 }
1058
1059 if (hdr->type != EAPOL_KEY_TYPE_RSN &&
1060 hdr->type != EAPOL_KEY_TYPE_WPA) {
1061 wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Descriptor Type "
1062 "%u from " MACSTR, hdr->type, MAC2STR(src));
1063 return;
1064 }
1065
1066 key_info = WPA_GET_BE16(hdr->key_info);
1067 key_length = WPA_GET_BE16(hdr->key_length);
6d014ffc
JM
1068 key_data_length = WPA_GET_BE16(mic + mic_len);
1069 key_data = mic + mic_len + 2;
161d0339 1070 if (key_data + key_data_length > data + len) {
c41e1d7c
JM
1071 add_note(wt, MSG_INFO, "Truncated EAPOL-Key from " MACSTR,
1072 MAC2STR(src));
161d0339
JM
1073 return;
1074 }
1075 if (key_data + key_data_length < data + len) {
1076 wpa_hexdump(MSG_DEBUG, "Extra data after EAPOL-Key Key Data "
1077 "field", key_data + key_data_length,
1078 data + len - key_data - key_data_length);
1079 }
1080
1081
1082 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
1083 wpa_printf(MSG_DEBUG, "EAPOL-Key ver=%u %c idx=%u%s%s%s%s%s%s%s%s "
1084 "datalen=%u",
1085 ver, key_info & WPA_KEY_INFO_KEY_TYPE ? 'P' : 'G',
1086 (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
1087 WPA_KEY_INFO_KEY_INDEX_SHIFT,
1088 (key_info & WPA_KEY_INFO_INSTALL) ? " Install" : "",
1089 (key_info & WPA_KEY_INFO_ACK) ? " ACK" : "",
1090 (key_info & WPA_KEY_INFO_MIC) ? " MIC" : "",
1091 (key_info & WPA_KEY_INFO_SECURE) ? " Secure" : "",
1092 (key_info & WPA_KEY_INFO_ERROR) ? " Error" : "",
1093 (key_info & WPA_KEY_INFO_REQUEST) ? " Request" : "",
1094 (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) ? " Encr" : "",
1095 (key_info & WPA_KEY_INFO_SMK_MESSAGE) ? " SMK" : "",
1096 key_data_length);
1097
1098 if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
1099 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
f6ff5160
JM
1100 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
1101 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
161d0339
JM
1102 wpa_printf(MSG_INFO, "Unsupported EAPOL-Key Key Descriptor "
1103 "Version %u from " MACSTR, ver, MAC2STR(src));
1104 return;
1105 }
1106
1107 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Replay Counter",
1108 hdr->replay_counter, WPA_REPLAY_COUNTER_LEN);
1109 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Nonce",
1110 hdr->key_nonce, WPA_NONCE_LEN);
1111 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key IV",
1112 hdr->key_iv, 16);
1113 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key RSC",
1114 hdr->key_rsc, WPA_KEY_RSC_LEN);
1115 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key MIC",
6d014ffc 1116 mic, mic_len);
161d0339
JM
1117 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data",
1118 key_data, key_data_length);
1119
1120 if (hdr->type == EAPOL_KEY_TYPE_RSN &&
1121 (key_info & (WPA_KEY_INFO_KEY_INDEX_MASK | BIT(14) | BIT(15))) !=
1122 0) {
1123 wpa_printf(MSG_INFO, "RSN EAPOL-Key with non-zero reserved "
1124 "Key Info bits 0x%x from " MACSTR,
1125 key_info, MAC2STR(src));
1126 }
1127
1128 if (hdr->type == EAPOL_KEY_TYPE_WPA &&
1129 (key_info & (WPA_KEY_INFO_ENCR_KEY_DATA |
1130 WPA_KEY_INFO_SMK_MESSAGE |BIT(14) | BIT(15))) != 0) {
1131 wpa_printf(MSG_INFO, "WPA EAPOL-Key with non-zero reserved "
1132 "Key Info bits 0x%x from " MACSTR,
1133 key_info, MAC2STR(src));
1134 }
1135
1136 if (key_length > 32) {
1137 wpa_printf(MSG_INFO, "EAPOL-Key with invalid Key Length %d "
1138 "from " MACSTR, key_length, MAC2STR(src));
1139 }
1140
1141 if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
1142 !is_zero(hdr->key_iv, 16)) {
1143 wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key IV "
1144 "(reserved with ver=%d) field from " MACSTR,
1145 ver, MAC2STR(src));
1146 wpa_hexdump(MSG_INFO, "EAPOL-Key Key IV (reserved)",
1147 hdr->key_iv, 16);
1148 }
1149
1150 if (!is_zero(hdr->key_id, 8)) {
1151 wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key ID "
1152 "(reserved) field from " MACSTR, MAC2STR(src));
1153 wpa_hexdump(MSG_INFO, "EAPOL-Key Key ID (reserved)",
1154 hdr->key_id, 8);
1155 }
1156
1157 if (hdr->key_rsc[6] || hdr->key_rsc[7]) {
1158 wpa_printf(MSG_INFO, "EAPOL-Key with non-zero Key RSC octets "
1159 "(last two are unused)" MACSTR, MAC2STR(src));
1160 }
1161
1162 if (key_info & (WPA_KEY_INFO_ERROR | WPA_KEY_INFO_REQUEST))
1163 return;
1164
1165 if (key_info & WPA_KEY_INFO_SMK_MESSAGE)
1166 return;
1167
1168 if (key_info & WPA_KEY_INFO_KEY_TYPE) {
1169 /* 4-Way Handshake */
1170 switch (key_info & (WPA_KEY_INFO_SECURE |
1171 WPA_KEY_INFO_MIC |
1172 WPA_KEY_INFO_ACK |
1173 WPA_KEY_INFO_INSTALL)) {
1174 case WPA_KEY_INFO_ACK:
1175 rx_data_eapol_key_1_of_4(wt, dst, src, data, len);
1176 break;
1177 case WPA_KEY_INFO_MIC:
1178 if (key_data_length == 0)
1179 rx_data_eapol_key_4_of_4(wt, dst, src, data,
1180 len);
1181 else
1182 rx_data_eapol_key_2_of_4(wt, dst, src, data,
1183 len);
1184 break;
1185 case WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK |
1186 WPA_KEY_INFO_INSTALL:
1187 /* WPA does not include Secure bit in 3/4 */
1188 rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
1189 break;
1190 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
1191 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL:
555ff857
JM
1192 case WPA_KEY_INFO_SECURE |
1193 WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL:
161d0339
JM
1194 rx_data_eapol_key_3_of_4(wt, dst, src, data, len);
1195 break;
1196 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
555ff857 1197 case WPA_KEY_INFO_SECURE:
d0b251d2
JM
1198 if (key_data_length == 0)
1199 rx_data_eapol_key_4_of_4(wt, dst, src, data,
1200 len);
1201 else
1202 rx_data_eapol_key_2_of_4(wt, dst, src, data,
1203 len);
161d0339
JM
1204 break;
1205 default:
1206 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
1207 break;
1208 }
1209 } else {
1210 /* Group Key Handshake */
1211 switch (key_info & (WPA_KEY_INFO_SECURE |
1212 WPA_KEY_INFO_MIC |
1213 WPA_KEY_INFO_ACK)) {
1214 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC |
1215 WPA_KEY_INFO_ACK:
555ff857 1216 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ACK:
161d0339
JM
1217 rx_data_eapol_key_1_of_2(wt, dst, src, data, len);
1218 break;
1219 case WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC:
555ff857 1220 case WPA_KEY_INFO_SECURE:
161d0339
JM
1221 rx_data_eapol_key_2_of_2(wt, dst, src, data, len);
1222 break;
1223 default:
1224 wpa_printf(MSG_DEBUG, "Unsupported EAPOL-Key frame");
1225 break;
1226 }
1227 }
1228}
1229
1230
6d014ffc
JM
1231void rx_data_eapol(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr,
1232 const u8 *dst, const u8 *src,
161d0339
JM
1233 const u8 *data, size_t len, int prot)
1234{
1235 const struct ieee802_1x_hdr *hdr;
1236 u16 length;
1237 const u8 *p;
1238
1239 wpa_hexdump(MSG_EXCESSIVE, "EAPOL", data, len);
1240 if (len < sizeof(*hdr)) {
1241 wpa_printf(MSG_INFO, "Too short EAPOL frame from " MACSTR,
1242 MAC2STR(src));
1243 return;
1244 }
1245
1246 hdr = (const struct ieee802_1x_hdr *) data;
1247 length = be_to_host16(hdr->length);
1248 wpa_printf(MSG_DEBUG, "RX EAPOL: " MACSTR " -> " MACSTR "%s ver=%u "
1249 "type=%u len=%u",
1250 MAC2STR(src), MAC2STR(dst), prot ? " Prot" : "",
1251 hdr->version, hdr->type, length);
1252 if (hdr->version < 1 || hdr->version > 3) {
1253 wpa_printf(MSG_INFO, "Unexpected EAPOL version %u from "
1254 MACSTR, hdr->version, MAC2STR(src));
1255 }
1256 if (sizeof(*hdr) + length > len) {
1257 wpa_printf(MSG_INFO, "Truncated EAPOL frame from " MACSTR,
1258 MAC2STR(src));
1259 return;
1260 }
1261
1262 if (sizeof(*hdr) + length < len) {
1263 wpa_printf(MSG_INFO, "EAPOL frame with %d extra bytes",
1264 (int) (len - sizeof(*hdr) - length));
1265 }
1266 p = (const u8 *) (hdr + 1);
1267
1268 switch (hdr->type) {
1269 case IEEE802_1X_TYPE_EAP_PACKET:
1270 wpa_hexdump(MSG_MSGDUMP, "EAPOL - EAP packet", p, length);
1271 break;
1272 case IEEE802_1X_TYPE_EAPOL_START:
1273 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Start", p, length);
1274 break;
1275 case IEEE802_1X_TYPE_EAPOL_LOGOFF:
1276 wpa_hexdump(MSG_MSGDUMP, "EAPOL-Logoff", p, length);
1277 break;
1278 case IEEE802_1X_TYPE_EAPOL_KEY:
6d014ffc
JM
1279 rx_data_eapol_key(wt, bssid, sta_addr, dst, src, data,
1280 sizeof(*hdr) + length, prot);
161d0339
JM
1281 break;
1282 case IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT:
1283 wpa_hexdump(MSG_MSGDUMP, "EAPOL - Encapsulated ASF alert",
1284 p, length);
1285 break;
1286 default:
1287 wpa_hexdump(MSG_MSGDUMP, "Unknown EAPOL payload", p, length);
1288 break;
1289 }
1290}