1 /*
2 * Received Management frame processing
3 * Copyright (c) 2010-2020, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "utils/includes.h"
10
11 #include "utils/common.h"
12 #include "common/defs.h"
13 #include "common/ieee802_11_defs.h"
14 #include "common/ieee802_11_common.h"
15 #include "common/wpa_common.h"
16 #include "crypto/aes.h"
17 #include "crypto/aes_siv.h"
18 #include "crypto/aes_wrap.h"
19 #include "wlantest.h"
20
21
22 static int check_mmie_mic(unsigned int mgmt_group_cipher,
23 const u8 *igtk, size_t igtk_len,
24 const u8 *data, size_t len);
25
26
mgmt_stype(u16 stype)27 static const char * mgmt_stype(u16 stype)
28 {
29 switch (stype) {
30 case WLAN_FC_STYPE_ASSOC_REQ:
31 return "ASSOC-REQ";
32 case WLAN_FC_STYPE_ASSOC_RESP:
33 return "ASSOC-RESP";
34 case WLAN_FC_STYPE_REASSOC_REQ:
35 return "REASSOC-REQ";
36 case WLAN_FC_STYPE_REASSOC_RESP:
37 return "REASSOC-RESP";
38 case WLAN_FC_STYPE_PROBE_REQ:
39 return "PROBE-REQ";
40 case WLAN_FC_STYPE_PROBE_RESP:
41 return "PROBE-RESP";
42 case WLAN_FC_STYPE_BEACON:
43 return "BEACON";
44 case WLAN_FC_STYPE_ATIM:
45 return "ATIM";
46 case WLAN_FC_STYPE_DISASSOC:
47 return "DISASSOC";
48 case WLAN_FC_STYPE_AUTH:
49 return "AUTH";
50 case WLAN_FC_STYPE_DEAUTH:
51 return "DEAUTH";
52 case WLAN_FC_STYPE_ACTION:
53 return "ACTION";
54 case WLAN_FC_STYPE_ACTION_NO_ACK:
55 return "ACTION-NO-ACK";
56 }
57 return "??";
58 }
59
60
parse_basic_ml(const u8 * ie,size_t len,bool ap,struct wlantest_sta * sta,size_t fields_len)61 static void parse_basic_ml(const u8 *ie, size_t len, bool ap,
62 struct wlantest_sta *sta, size_t fields_len)
63 {
64 const u8 *pos, *end, *ci_end, *info_end, *li_end;
65 u16 ctrl, eml, cap;
66 const struct element *elem;
67 struct wpabuf *profile = NULL;
68
69 wpa_hexdump(MSG_MSGDUMP, "Basic MLE", ie, len);
70 pos = ie;
71 end = ie + len;
72
73 if (end - pos < 2)
74 return;
75 ctrl = WPA_GET_LE16(pos);
76 wpa_printf(MSG_DEBUG,
77 "Multi-Link Control: Type=%u Reserved=%u Presence Bitmap=0x%x",
78 ctrl & MULTI_LINK_CONTROL_TYPE_MASK,
79 ctrl & BIT(3),
80 ctrl >> 4);
81 pos += 2;
82
83 /* Common Info */
84
85 if (end - pos < 1)
86 return;
87 len = *pos;
88 if (len > end - pos) {
89 wpa_printf(MSG_INFO,
90 "Truncated Multi-Link Common Info (len=%zu left=%zu)",
91 len, (size_t) (end - pos));
92 return;
93 }
94 if (len < 1 + ETH_ALEN) {
95 wpa_printf(MSG_INFO,
96 "No room for MLD MAC Address in Multi-Link Common Info");
97 return;
98 }
99 ci_end = pos + len;
100
101 pos++;
102 wpa_hexdump(MSG_MSGDUMP, "Basic MLE - Common Info", pos, ci_end - pos);
103 wpa_printf(MSG_DEBUG, "MLD MAC Address: " MACSTR, MAC2STR(pos));
104 if (!ap && sta && is_zero_ether_addr(sta->mld_mac_addr)) {
105 os_memcpy(sta->mld_mac_addr, pos, ETH_ALEN);
106 wpa_printf(MSG_DEBUG,
107 "Learned non-AP STA MLD MAC Address from Basic MLE: "
108 MACSTR, MAC2STR(sta->mld_mac_addr));
109 }
110 pos += ETH_ALEN;
111
112 if (ctrl & BASIC_MULTI_LINK_CTRL_PRES_LINK_ID) {
113 if (ci_end - pos < 1) {
114 wpa_printf(MSG_INFO,
115 "No room for Link ID Info in Multi-Link Common Info");
116 return;
117 }
118 wpa_printf(MSG_DEBUG, "Link ID Info: 0x%x", *pos);
119 if (!ap)
120 wpa_printf(MSG_INFO,
121 "Unexpected Link ID Info in Common Info from a non-AP STA");
122 pos++;
123 }
124 if (ctrl & BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT) {
125 if (ci_end - pos < 1) {
126 wpa_printf(MSG_INFO,
127 "No room for BSS Parameters Change Count in Multi-Link Common Info");
128 return;
129 }
130 wpa_printf(MSG_DEBUG, "BSS Parameters Change Count: %u", *pos);
131 if (!ap)
132 wpa_printf(MSG_INFO,
133 "Unexpected BSS Parameters Change Count in Common Info from a non-AP STA");
134 pos++;
135 }
136 if (ctrl & BASIC_MULTI_LINK_CTRL_PRES_MSD_INFO) {
137 if (ci_end - pos < 2) {
138 wpa_printf(MSG_INFO,
139 "No room for Medium Synchronization Delay Information in Multi-Link Common Info");
140 return;
141 }
142 wpa_printf(MSG_DEBUG,
143 "Medium Synchronization Delay Information: 0x%x",
144 WPA_GET_LE16(pos));
145 if (!ap)
146 wpa_printf(MSG_INFO,
147 "Unexpected Medium Synchronization Delay Information in Common Info from a non-AP STA");
148 pos += 2;
149 }
150 if (ctrl & BASIC_MULTI_LINK_CTRL_PRES_EML_CAPA) {
151 if (ci_end - pos < 2) {
152 wpa_printf(MSG_INFO,
153 "No room for EML Capabilities in Multi-Link Common Info");
154 return;
155 }
156 eml = WPA_GET_LE16(pos);
157 pos += 2;
158 wpa_printf(MSG_DEBUG,
159 "EML Capabilities: 0x%x (EMLSR=%u EMLSR_Padding_Delay=%u EMLSR_Transition_Delay=%u EMLMR=%u EMLMR_Delay=%u Transition_Timeout=%u Reserved=%u)",
160 eml,
161 !!(eml & EHT_ML_EML_CAPA_EMLSR_SUPP),
162 (eml & EHT_ML_EML_CAPA_EMLSR_PADDING_DELAY_MASK) >>
163 1,
164 (eml & EHT_ML_EML_CAPA_EMLSR_TRANS_DELAY_MASK) >> 4,
165 !!(eml & EHT_ML_EML_CAPA_EMLMR_SUPP),
166 (eml & EHT_ML_EML_CAPA_EMLMR_DELAY_MASK) >> 8,
167 (eml & EHT_ML_EML_CAPA_TRANSITION_TIMEOUT_MASK) >>
168 11,
169 !!(eml & BIT(15)));
170 }
171 if (ctrl & BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA) {
172 if (ci_end - pos < 2) {
173 wpa_printf(MSG_INFO,
174 "No room for MLD Capabilities and Operations in Multi-Link Common Info");
175 return;
176 }
177 cap = WPA_GET_LE16(pos);
178 pos += 2;
179 wpa_printf(MSG_DEBUG,
180 "MLD Capabilities and Operations: 0x%x (Max_Simultaneous_Links=%u SRS=%u T2L=0x%x Freq_Sep_STR=0x%x AAR=%u Reserved=0x%x)",
181 cap,
182 cap & EHT_ML_MLD_CAPA_MAX_NUM_SIM_LINKS_MASK,
183 !!(cap & EHT_ML_MLD_CAPA_SRS_SUPP),
184 (cap &
185 EHT_ML_MLD_CAPA_TID_TO_LINK_MAP_NEG_SUPP_MSK) >> 5,
186 (cap & EHT_ML_MLD_CAPA_FREQ_SEP_FOR_STR_MASK) >> 7,
187 !!(cap & EHT_ML_MLD_CAPA_AAR_SUPP),
188 (cap & 0xe000) >> 13);
189 }
190 if (ctrl & BASIC_MULTI_LINK_CTRL_PRES_AP_MLD_ID) {
191 if (ci_end - pos < 1) {
192 wpa_printf(MSG_INFO,
193 "No room for AP MLD ID in Multi-Link Common Info");
194 return;
195 }
196 wpa_printf(MSG_DEBUG, "AP MLD ID: %u", *pos);
197 pos++;
198 }
199
200 if (pos < ci_end) {
201 wpa_hexdump(MSG_INFO,
202 "Extra information at the end of Common Info",
203 pos, ci_end - pos);
204 pos = ci_end;
205 }
206
207 /* Link Info */
208 wpa_hexdump(MSG_MSGDUMP, "Basic MLE - Link Info", pos, end - pos);
209
210 li_end = end;
211 for_each_element(elem, pos, li_end - pos) {
212 u8 link_id;
213 const u8 *fpos;
214 u8 flen;
215
216 if (elem->id == EHT_ML_SUB_ELEM_FRAGMENT)
217 continue;
218
219 if (elem->id != EHT_ML_SUB_ELEM_PER_STA_PROFILE) {
220 wpa_printf(MSG_DEBUG, "Link Info subelement id=%u",
221 elem->id);
222 wpa_hexdump(MSG_DEBUG, "Link Info subelement data",
223 elem->data, elem->datalen);
224 continue;
225 }
226
227 wpabuf_free(profile);
228 profile = wpabuf_alloc_copy(elem->data, elem->datalen);
229 if (!profile)
230 continue;
231 flen = elem->datalen;
232 fpos = elem->data + flen;
233 while (flen == 255 && li_end - fpos >= 2 &&
234 *fpos == EHT_ML_SUB_ELEM_FRAGMENT &&
235 li_end - fpos >= 2 + fpos[1]) {
236 /* Reassemble truncated subelement */
237 fpos++;
238 flen = *fpos++;
239 if (wpabuf_resize(&profile, flen) < 0)
240 continue;
241 wpabuf_put_data(profile, fpos, flen);
242 fpos += flen;
243 }
244 pos = wpabuf_head(profile);
245 end = pos + wpabuf_len(profile);
246
247 if (end - pos < 2) {
248 wpa_printf(MSG_INFO,
249 "Truncated Per-STA Profile subelement");
250 continue;
251 }
252 wpa_hexdump(MSG_MSGDUMP, "Basic MLE - Per-STA Profile",
253 pos, end - pos);
254 ctrl = WPA_GET_LE16(pos);
255 pos += 2;
256
257 link_id = ctrl & BASIC_MLE_STA_CTRL_LINK_ID_MASK;
258 wpa_printf(MSG_DEBUG, "Per-STA Profile: len=%zu Link_ID=%u Complete=%u Reserved=0x%x",
259 wpabuf_len(profile),
260 link_id,
261 !!(ctrl & BASIC_MLE_STA_CTRL_COMPLETE_PROFILE),
262 (ctrl & 0xf000) >> 12);
263
264 if (end - pos < 1) {
265 wpa_printf(MSG_INFO, "No room for STA Info field");
266 continue;
267 }
268 len = *pos;
269 if (len < 1 || len > end - pos) {
270 wpa_printf(MSG_INFO, "Truncated STA Info field");
271 continue;
272 }
273 info_end = pos + len;
274 pos++;
275 if (ctrl & BASIC_MLE_STA_CTRL_PRES_STA_MAC) {
276 if (info_end - pos < ETH_ALEN) {
277 wpa_printf(MSG_INFO,
278 "Truncated STA MAC Address in STA Info");
279 continue;
280 }
281 wpa_printf(MSG_DEBUG, "STA MAC Address: " MACSTR,
282 MAC2STR(pos));
283 if (sta && link_id < MAX_NUM_MLD_LINKS) {
284 os_memcpy(sta->link_addr[link_id], pos,
285 ETH_ALEN);
286 wpa_printf(MSG_DEBUG,
287 "Learned Link ID %u MAC address "
288 MACSTR
289 " from Association Request",
290 link_id, MAC2STR(pos));
291 }
292 pos += ETH_ALEN;
293 }
294 if (ctrl & BASIC_MLE_STA_CTRL_PRES_BEACON_INT) {
295 if (info_end - pos < 2) {
296 wpa_printf(MSG_INFO,
297 "Truncated Beacon Interval in STA Info");
298 continue;
299 }
300 wpa_printf(MSG_DEBUG, "Beacon Interval: %u",
301 WPA_GET_LE16(pos));
302 pos += 2;
303 }
304 if (ctrl & BASIC_MLE_STA_CTRL_PRES_TSF_OFFSET) {
305 if (info_end - pos < 8) {
306 wpa_printf(MSG_INFO,
307 "Truncated TSF Offset in STA Info");
308 continue;
309 }
310 wpa_printf(MSG_DEBUG, "TSF Offset: 0x%llx",
311 (long long unsigned) WPA_GET_LE64(pos));
312 pos += 8;
313 }
314 if (ctrl & BASIC_MLE_STA_CTRL_PRES_DTIM_INFO) {
315 if (info_end - pos < 2) {
316 wpa_printf(MSG_INFO,
317 "Truncated DTIM Info in STA Info");
318 continue;
319 }
320 wpa_printf(MSG_DEBUG, "DTIM Info: 0x%x",
321 WPA_GET_LE16(pos));
322 pos += 2;
323 }
324 if ((ctrl & (BASIC_MLE_STA_CTRL_COMPLETE_PROFILE |
325 BASIC_MLE_STA_CTRL_PRES_NSTR_LINK_PAIR)) ==
326 (BASIC_MLE_STA_CTRL_COMPLETE_PROFILE |
327 BASIC_MLE_STA_CTRL_PRES_NSTR_LINK_PAIR)) {
328 if (ctrl & BASIC_MLE_STA_CTRL_NSTR_BITMAP) {
329 if (info_end - pos < 2) {
330 wpa_printf(MSG_INFO,
331 "Truncated NSTR Indication Bitmap in STA Info");
332 continue;
333 }
334 wpa_printf(MSG_DEBUG, "NSTR Indication Bitmap: 0x%04x",
335 WPA_GET_LE16(pos));
336 pos += 2;
337 } else {
338 if (info_end - pos < 1) {
339 wpa_printf(MSG_INFO,
340 "Truncated NSTR Indication Bitmap in STA Info");
341 continue;
342 }
343 wpa_printf(MSG_DEBUG, "NSTR Indication Bitmap: 0x%02x",
344 *pos);
345 pos++;
346 }
347 }
348 if (ctrl & BASIC_MLE_STA_CTRL_PRES_BSS_PARAM_COUNT) {
349 if (info_end - pos < 1) {
350 wpa_printf(MSG_INFO,
351 "Truncated BSS Parameters Change Count in STA Info");
352 continue;
353 }
354 wpa_printf(MSG_DEBUG, "BSS Parameters Change Count: %u",
355 *pos);
356 pos++;
357 }
358 if (info_end > pos) {
359 wpa_hexdump(MSG_INFO,
360 "Extra information at the end of STA Info",
361 pos, ci_end - pos);
362 pos = info_end;
363 }
364
365 wpa_hexdump(MSG_DEBUG, "STA Profile", pos, end - pos);
366 if (end - pos > fields_len) {
367 struct ieee802_11_elems elems;
368
369 if (ieee802_11_parse_elems(pos + fields_len,
370 end - pos - fields_len,
371 &elems, 0) != ParseFailed) {
372 if (elems.rsn_ie)
373 wpa_hexdump(MSG_DEBUG, "RSNE",
374 elems.rsn_ie,
375 elems.rsn_ie_len);
376 if (elems.rsnxe)
377 wpa_hexdump(MSG_DEBUG, "RSNXE",
378 elems.rsnxe,
379 elems.rsnxe_len);
380 }
381 }
382 }
383
384 wpabuf_free(profile);
385 }
386
387
parse_basic_ml_elems(struct ieee802_11_elems * elems,bool ap,struct wlantest_sta * sta,size_t fields_len)388 static void parse_basic_ml_elems(struct ieee802_11_elems *elems, bool ap,
389 struct wlantest_sta *sta, size_t fields_len)
390 {
391 struct wpabuf *mlbuf;
392
393 mlbuf = ieee802_11_defrag(elems->basic_mle, elems->basic_mle_len, true);
394 if (mlbuf) {
395 parse_basic_ml(wpabuf_head(mlbuf), wpabuf_len(mlbuf), ap, sta,
396 fields_len);
397 wpabuf_free(mlbuf);
398 }
399 }
400
401
rx_mgmt_beacon(struct wlantest * wt,const u8 * data,size_t len)402 static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len)
403 {
404 const struct ieee80211_mgmt *mgmt;
405 struct wlantest_bss *bss;
406 struct ieee802_11_elems elems;
407 size_t offset;
408 const u8 *mme;
409 size_t mic_len;
410 u16 keyid;
411
412 mgmt = (const struct ieee80211_mgmt *) data;
413 offset = mgmt->u.beacon.variable - data;
414 if (len < offset)
415 return;
416 bss = bss_get(wt, mgmt->bssid);
417 if (bss == NULL)
418 return;
419 /* do not override with Beacon data */
420 if (!bss->proberesp_seen)
421 bss->capab_info = le_to_host16(mgmt->u.beacon.capab_info);
422 if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - offset,
423 &elems, 0) == ParseFailed) {
424 if (bss->parse_error_reported)
425 return;
426 add_note(wt, MSG_INFO, "Invalid IEs in a Beacon frame from "
427 MACSTR, MAC2STR(mgmt->sa));
428 bss->parse_error_reported = 1;
429 return;
430 }
431
432 if (elems.rsnxe) {
433 os_memcpy(bss->rsnxe, elems.rsnxe, elems.rsnxe_len);
434 bss->rsnxe_len = elems.rsnxe_len;
435 } else {
436 bss->rsnxe_len = 0;
437 }
438
439 if (elems.rsnxe_override) {
440 os_memcpy(bss->rsnxoe, elems.rsnxe_override + 4,
441 elems.rsnxe_override_len - 4);
442 bss->rsnxoe_len = elems.rsnxe_override_len;
443 } else {
444 bss->rsnxoe_len = 0;
445 }
446
447 if (!bss->proberesp_seen)
448 bss_update(wt, bss, &elems, 1);
449
450 if (elems.mbssid) {
451 const u8 *pos = elems.mbssid;
452 const u8 *end = elems.mbssid + elems.mbssid_len;
453 u8 max_bss = *pos++;
454
455 while (end - pos > 2) {
456 u8 s_id, s_len, ssid_len, bssid_idx;
457 const u8 *s_data, *ssid;
458 u16 capa;
459 u8 bssid[ETH_ALEN], b;
460 struct ieee802_11_elems m_elems, merged;
461 struct wlantest_bss *m_bss;
462
463 s_id = *pos++;
464 s_len = *pos++;
465
466 if (end - pos < s_len)
467 break;
468 s_data = pos;
469 pos += s_len;
470
471 if (s_id !=
472 WLAN_MBSSID_SUBELEMENT_NONTRANSMITTED_BSSID_PROFILE)
473 continue;
474
475 /* Nontransmitted BSSID Capability element */
476 if (pos - s_data < 4 ||
477 s_data[0] != WLAN_EID_NONTRANSMITTED_BSSID_CAPA ||
478 s_data[1] < 2)
479 continue;
480 capa = WPA_GET_LE16(&s_data[2]);
481 s_data += 2 + s_data[1];
482
483 /* SSID element */
484 if (pos - s_data < 2 ||
485 s_data[0] != WLAN_EID_SSID)
486 continue;
487 ssid = &s_data[2];
488 ssid_len = s_data[1];
489 s_data += 2 + s_data[1];
490
491 /* Multiple BSSID-Index element */
492 if (pos - s_data < 3 ||
493 s_data[0] != WLAN_EID_MULTIPLE_BSSID_INDEX)
494 continue;
495 bssid_idx = s_data[2];
496 s_data += 2 + s_data[1];
497
498 if (max_bss < 1 || max_bss > 8)
499 break;
500 os_memcpy(bssid, mgmt->bssid, ETH_ALEN);
501 b = bssid[5] % (1 << max_bss);
502 bssid[5] = bssid[5] - b +
503 (b + bssid_idx) % (1 << max_bss);
504 wpa_printf(MSG_MSGDUMP, "MBSSID: " MACSTR
505 " Capa 0x%x idx=%u MaxBSSID Indicator=%u",
506 MAC2STR(bssid), capa, bssid_idx, max_bss);
507
508 wpa_hexdump(MSG_MSGDUMP, "MBSSID: SSID",
509 ssid, ssid_len);
510
511 /* Rest of the elements */
512 wpa_hexdump(MSG_MSGDUMP, "MBSSID: Elements",
513 s_data, pos - s_data);
514 if (ieee802_11_parse_elems(s_data, pos - s_data,
515 &m_elems,
516 0) == ParseFailed) {
517 wpa_printf(MSG_DEBUG,
518 "MBSSID: Failed to parse nontransmitted BSS elements");
519 continue;
520 }
521
522 /* TODO: Noninheritance and rest of elements */
523 os_memcpy(&merged, &elems, sizeof(merged));
524 merged.ssid = ssid;
525 merged.ssid_len = ssid_len;
526
527 m_bss = bss_get(wt, bssid);
528 if (!m_bss)
529 continue;
530 if (!m_bss->proberesp_seen)
531 m_bss->capab_info = capa;
532
533 if (m_elems.basic_mle) {
534 merged.basic_mle = m_elems.basic_mle;
535 merged.basic_mle_len = m_elems.basic_mle_len;
536 }
537 if (m_elems.rsn_ie) {
538 merged.rsn_ie = m_elems.rsn_ie;
539 merged.rsn_ie_len = m_elems.rsn_ie_len;
540 }
541 if (m_elems.rsnxe) {
542 merged.rsnxe = m_elems.rsnxe;
543 merged.rsnxe_len = m_elems.rsnxe_len;
544 }
545 if (m_elems.rsnxe_override) {
546 merged.rsnxe_override = m_elems.rsnxe_override;
547 merged.rsnxe_override_len =
548 m_elems.rsnxe_override_len;
549 }
550
551 if (merged.rsnxe) {
552 os_memcpy(m_bss->rsnxe, merged.rsnxe,
553 merged.rsnxe_len);
554 m_bss->rsnxe_len = merged.rsnxe_len;
555 } else {
556 m_bss->rsnxe_len = 0;
557 }
558
559 if (merged.rsnxe_override) {
560 os_memcpy(m_bss->rsnxoe,
561 merged.rsnxe_override + 4,
562 merged.rsnxe_override_len - 4);
563 m_bss->rsnxoe_len =
564 merged.rsnxe_override_len - 4;
565 } else {
566 m_bss->rsnxoe_len = 0;
567 }
568
569 if (!m_bss->proberesp_seen)
570 bss_update(wt, m_bss, &merged, 1);
571 }
572 }
573
574 mme = get_ie(mgmt->u.beacon.variable, len - offset, WLAN_EID_MMIE);
575 if (!mme) {
576 if (bss->bigtk_idx) {
577 add_note(wt, MSG_INFO,
578 "Unexpected unprotected Beacon frame from "
579 MACSTR, MAC2STR(mgmt->sa));
580 bss->counters[WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE]++;
581 }
582 return;
583 }
584
585 mic_len = bss->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC ? 8 : 16;
586 if (len < 24 + 10 + mic_len ||
587 data[len - (10 + mic_len)] != WLAN_EID_MMIE ||
588 data[len - (10 + mic_len - 1)] != 8 + mic_len) {
589 add_note(wt, MSG_INFO, "Invalid MME in a Beacon frame from "
590 MACSTR, MAC2STR(mgmt->sa));
591 return;
592 }
593
594 mme += 2;
595 keyid = WPA_GET_LE16(mme);
596 if (keyid < 6 || keyid > 7) {
597 add_note(wt, MSG_INFO, "Unexpected MME KeyID %u from " MACSTR,
598 keyid, MAC2STR(mgmt->sa));
599 bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
600 return;
601 }
602
603 wpa_printf(MSG_DEBUG, "Beacon frame MME KeyID %u", keyid);
604 wpa_hexdump(MSG_MSGDUMP, "MME IPN", mme + 2, 6);
605 wpa_hexdump(MSG_MSGDUMP, "MME MIC", mme + 8, mic_len);
606
607 if (!bss->igtk_len[keyid]) {
608 add_note(wt, MSG_DEBUG,
609 "No BIGTK known to validate BIP frame from " MACSTR,
610 MAC2STR(mgmt->sa));
611 return;
612 }
613
614 if (os_memcmp(mme + 2, bss->ipn[keyid], 6) <= 0) {
615 add_note(wt, MSG_INFO, "BIP replay detected: SA=" MACSTR,
616 MAC2STR(mgmt->sa));
617 wpa_hexdump(MSG_INFO, "RX IPN", mme + 2, 6);
618 wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6);
619 }
620
621 if (check_mmie_mic(bss->mgmt_group_cipher, bss->igtk[keyid],
622 bss->igtk_len[keyid], data, len) < 0) {
623 add_note(wt, MSG_INFO, "Invalid MME MIC in a Beacon frame from "
624 MACSTR, MAC2STR(mgmt->sa));
625 bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
626 return;
627 }
628
629 add_note(wt, MSG_DEBUG, "Valid MME MIC in Beacon frame");
630 os_memcpy(bss->ipn[keyid], mme + 2, 6);
631 }
632
633
rx_mgmt_probe_resp(struct wlantest * wt,const u8 * data,size_t len)634 static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len)
635 {
636 const struct ieee80211_mgmt *mgmt;
637 struct wlantest_bss *bss;
638 struct ieee802_11_elems elems;
639 size_t offset;
640
641 mgmt = (const struct ieee80211_mgmt *) data;
642 offset = mgmt->u.probe_resp.variable - data;
643 if (len < offset)
644 return;
645 bss = bss_get(wt, mgmt->bssid);
646 if (bss == NULL)
647 return;
648
649 bss->counters[WLANTEST_BSS_COUNTER_PROBE_RESPONSE]++;
650 bss->capab_info = le_to_host16(mgmt->u.probe_resp.capab_info);
651 if (ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - offset,
652 &elems, 0) == ParseFailed) {
653 if (bss->parse_error_reported)
654 return;
655 add_note(wt, MSG_INFO, "Invalid IEs in a Probe Response frame "
656 "from " MACSTR, MAC2STR(mgmt->sa));
657 bss->parse_error_reported = 1;
658 return;
659 }
660
661 bss_update(wt, bss, &elems, 2);
662 }
663
664
process_fils_auth(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const struct ieee80211_mgmt * mgmt,size_t len)665 static void process_fils_auth(struct wlantest *wt, struct wlantest_bss *bss,
666 struct wlantest_sta *sta,
667 const struct ieee80211_mgmt *mgmt, size_t len)
668 {
669 struct ieee802_11_elems elems;
670 u16 trans;
671 struct wpa_ie_data data;
672
673 if (sta->auth_alg != WLAN_AUTH_FILS_SK ||
674 len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth))
675 return;
676
677 trans = le_to_host16(mgmt->u.auth.auth_transaction);
678
679 if (ieee802_11_parse_elems(mgmt->u.auth.variable,
680 len - IEEE80211_HDRLEN -
681 sizeof(mgmt->u.auth), &elems, 0) ==
682 ParseFailed)
683 return;
684
685 if (trans == 1) {
686 if (!elems.rsn_ie) {
687 add_note(wt, MSG_INFO,
688 "FILS Authentication frame missing RSNE");
689 return;
690 }
691 if (wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2,
692 elems.rsn_ie_len + 2, &data) < 0) {
693 add_note(wt, MSG_INFO,
694 "Invalid RSNE in FILS Authentication frame");
695 return;
696 }
697 sta->key_mgmt = data.key_mgmt;
698 sta->pairwise_cipher = data.pairwise_cipher;
699 }
700
701 if (!elems.fils_nonce) {
702 add_note(wt, MSG_INFO,
703 "FILS Authentication frame missing nonce");
704 return;
705 }
706
707 if (ether_addr_equal(mgmt->sa, mgmt->bssid))
708 os_memcpy(sta->anonce, elems.fils_nonce, FILS_NONCE_LEN);
709 else
710 os_memcpy(sta->snonce, elems.fils_nonce, FILS_NONCE_LEN);
711 }
712
713
process_ft_auth(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const struct ieee80211_mgmt * mgmt,size_t len)714 static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss,
715 struct wlantest_sta *sta,
716 const struct ieee80211_mgmt *mgmt, size_t len)
717 {
718 u16 trans;
719 struct wpa_ft_ies parse;
720 struct wpa_ptk ptk;
721 u8 ptk_name[WPA_PMK_NAME_LEN];
722 struct wlantest_bss *old_bss;
723 struct wlantest_sta *old_sta = NULL;
724 const u8 *spa, *aa;
725 struct ieee802_11_elems elems;
726 const u8 *ie;
727 size_t ie_len;
728 const u8 *rsnxe;
729 size_t rsnxe_len;
730
731 if (sta->auth_alg != WLAN_AUTH_FT ||
732 len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth))
733 return;
734
735 trans = le_to_host16(mgmt->u.auth.auth_transaction);
736
737 ie = mgmt->u.auth.variable;
738 ie_len = len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth);
739 if (wpa_ft_parse_ies(ie, ie_len, &parse, 0, false)) {
740 add_note(wt, MSG_INFO,
741 "Could not parse FT Authentication Response frame");
742 return;
743 }
744
745 if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed)
746 wpa_printf(MSG_INFO,
747 "FT: Failed to parse IEs in FT Authentication frame");
748
749 if (trans == 1) {
750 if (elems.basic_mle)
751 parse_basic_ml_elems(&elems, false, sta, 6);
752 sta->key_mgmt = parse.key_mgmt;
753 sta->pairwise_cipher = parse.pairwise_cipher;
754 if (parse.fte_snonce)
755 os_memcpy(sta->snonce, parse.fte_snonce, WPA_NONCE_LEN);
756 goto out;
757 }
758
759 if (trans != 2)
760 goto out;
761
762 spa = elems.basic_mle ? sta->mld_mac_addr : sta->addr;
763 aa = elems.basic_mle ? bss->mld_mac_addr : bss->bssid;
764
765 if (!parse.fte_snonce ||
766 os_memcmp(sta->snonce, parse.fte_snonce, WPA_NONCE_LEN) != 0) {
767 add_note(wt, MSG_INFO, "FT: SNonce mismatch in FTE");
768 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
769 parse.fte_snonce, WPA_NONCE_LEN);
770 wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
771 sta->snonce, WPA_NONCE_LEN);
772 }
773
774 if (parse.fte_anonce)
775 os_memcpy(sta->anonce, parse.fte_anonce, WPA_NONCE_LEN);
776
777 /* TODO: Should find the latest updated PMK-R0 value here instead
778 * copying the one from the first found matching old STA entry. */
779 dl_list_for_each(old_bss, &wt->bss, struct wlantest_bss, list) {
780 if (old_bss == bss)
781 continue;
782 old_sta = sta_find(old_bss, sta->addr);
783 if (old_sta)
784 break;
785 }
786 if (!old_sta)
787 goto out;
788
789 os_memcpy(sta->pmk_r0, old_sta->pmk_r0, old_sta->pmk_r0_len);
790 sta->pmk_r0_len = old_sta->pmk_r0_len;
791 os_memcpy(sta->pmk_r0_name, old_sta->pmk_r0_name,
792 sizeof(sta->pmk_r0_name));
793
794 if (parse.r1kh_id)
795 os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
796
797 if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name,
798 bss->r1kh_id, spa, sta->pmk_r1,
799 sta->pmk_r1_name) < 0)
800 goto out;
801 sta->pmk_r1_len = sta->pmk_r0_len;
802
803 if ((sta->rsn_selection == RSN_SELECTION_RSNE_OVERRIDE ||
804 sta->rsn_selection == RSN_SELECTION_RSNE_OVERRIDE_2) &&
805 bss->rsnxoe_len) {
806 rsnxe = bss->rsnxoe;
807 rsnxe_len = bss->rsnxoe_len;
808 } else {
809 rsnxe = bss->rsnxe;
810 rsnxe_len = bss->rsnxe_len;
811 }
812
813 if (!parse.fte_anonce || !parse.fte_snonce ||
814 wpa_pmk_r1_to_ptk(sta->pmk_r1, sta->pmk_r1_len, parse.fte_snonce,
815 parse.fte_anonce, spa, aa,
816 sta->pmk_r1_name, &ptk, ptk_name, sta->key_mgmt,
817 sta->pairwise_cipher, 0) < 0)
818 goto out;
819
820 sta_new_ptk(wt, sta, &ptk);
821 out:
822 wpa_ft_parse_ies_free(&parse);
823 }
824
825
process_sae_auth(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const struct ieee80211_mgmt * mgmt,size_t len)826 static void process_sae_auth(struct wlantest *wt, struct wlantest_bss *bss,
827 struct wlantest_sta *sta,
828 const struct ieee80211_mgmt *mgmt, size_t len)
829 {
830 u16 trans, status, group;
831
832 if (sta->auth_alg != WLAN_AUTH_SAE ||
833 len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + 2)
834 return;
835
836 trans = le_to_host16(mgmt->u.auth.auth_transaction);
837 if (trans != 1)
838 return;
839
840 status = le_to_host16(mgmt->u.auth.status_code);
841 if (status != WLAN_STATUS_SUCCESS &&
842 status != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
843 status != WLAN_STATUS_SAE_PK)
844 return;
845
846 group = WPA_GET_LE16(mgmt->u.auth.variable);
847 wpa_printf(MSG_DEBUG, "SAE Commit using group %u", group);
848 sta->sae_group = group;
849 }
850
851
rx_mgmt_auth(struct wlantest * wt,const u8 * data,size_t len)852 static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len)
853 {
854 const struct ieee80211_mgmt *mgmt;
855 struct wlantest_bss *bss;
856 struct wlantest_sta *sta;
857 u16 alg, trans, status;
858 bool from_ap;
859
860 mgmt = (const struct ieee80211_mgmt *) data;
861 bss = bss_get(wt, mgmt->bssid);
862 if (bss == NULL)
863 return;
864 from_ap = ether_addr_equal(mgmt->sa, mgmt->bssid);
865 if (from_ap)
866 sta = sta_get(bss, mgmt->da);
867 else
868 sta = sta_get(bss, mgmt->sa);
869 if (sta == NULL)
870 return;
871
872 if (len < 24 + 6) {
873 add_note(wt, MSG_INFO, "Too short Authentication frame from "
874 MACSTR, MAC2STR(mgmt->sa));
875 return;
876 }
877
878 alg = le_to_host16(mgmt->u.auth.auth_alg);
879 sta->auth_alg = alg;
880 trans = le_to_host16(mgmt->u.auth.auth_transaction);
881 status = le_to_host16(mgmt->u.auth.status_code);
882
883 wpa_printf(MSG_DEBUG, "AUTH " MACSTR " -> " MACSTR
884 " (alg=%u trans=%u status=%u)",
885 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), alg, trans, status);
886
887 if (status == WLAN_STATUS_SUCCESS &&
888 ((alg == WLAN_AUTH_OPEN && trans == 2) ||
889 (alg == WLAN_AUTH_SAE && trans == 2 && from_ap))) {
890 if (sta->state == STATE1) {
891 add_note(wt, MSG_DEBUG, "STA " MACSTR
892 " moved to State 2 with " MACSTR,
893 MAC2STR(sta->addr), MAC2STR(bss->bssid));
894 sta->state = STATE2;
895 }
896 }
897
898 if (ether_addr_equal(mgmt->sa, mgmt->bssid))
899 sta->counters[WLANTEST_STA_COUNTER_AUTH_RX]++;
900 else
901 sta->counters[WLANTEST_STA_COUNTER_AUTH_TX]++;
902
903 process_fils_auth(wt, bss, sta, mgmt, len);
904 process_ft_auth(wt, bss, sta, mgmt, len);
905 process_sae_auth(wt, bss, sta, mgmt, len);
906 }
907
908
deauth_all_stas(struct wlantest * wt,struct wlantest_bss * bss)909 static void deauth_all_stas(struct wlantest *wt, struct wlantest_bss *bss)
910 {
911 struct wlantest_sta *sta;
912 dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) {
913 if (sta->state == STATE1)
914 continue;
915 add_note(wt, MSG_DEBUG, "STA " MACSTR
916 " moved to State 1 with " MACSTR,
917 MAC2STR(sta->addr), MAC2STR(bss->bssid));
918 sta->state = STATE1;
919 }
920 }
921
922
tdls_link_down(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta)923 static void tdls_link_down(struct wlantest *wt, struct wlantest_bss *bss,
924 struct wlantest_sta *sta)
925 {
926 struct wlantest_tdls *tdls;
927 dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) {
928 if ((tdls->init == sta || tdls->resp == sta) && tdls->link_up)
929 {
930 add_note(wt, MSG_DEBUG, "TDLS: Set link down based on "
931 "STA deauth/disassoc");
932 tdls->link_up = 0;
933 }
934 }
935 }
936
937
rx_mgmt_deauth(struct wlantest * wt,const u8 * data,size_t len,int valid)938 static void rx_mgmt_deauth(struct wlantest *wt, const u8 *data, size_t len,
939 int valid)
940 {
941 const struct ieee80211_mgmt *mgmt;
942 struct wlantest_bss *bss;
943 struct wlantest_sta *sta;
944 u16 fc, reason;
945
946 mgmt = (const struct ieee80211_mgmt *) data;
947 bss = bss_get(wt, mgmt->bssid);
948 if (bss == NULL)
949 return;
950 if (ether_addr_equal(mgmt->sa, mgmt->bssid))
951 sta = sta_get(bss, mgmt->da);
952 else
953 sta = sta_get(bss, mgmt->sa);
954
955 if (len < 24 + 2) {
956 add_note(wt, MSG_INFO, "Too short Deauthentication frame from "
957 MACSTR, MAC2STR(mgmt->sa));
958 return;
959 }
960
961 reason = le_to_host16(mgmt->u.deauth.reason_code);
962 wpa_printf(MSG_DEBUG, "DEAUTH " MACSTR " -> " MACSTR
963 " (reason=%u) (valid=%d)",
964 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
965 reason, valid);
966 wpa_hexdump(MSG_MSGDUMP, "DEAUTH payload", data + 24, len - 24);
967
968 if (sta == NULL) {
969 if (valid && mgmt->da[0] == 0xff)
970 deauth_all_stas(wt, bss);
971 return;
972 }
973
974 if (ether_addr_equal(mgmt->sa, mgmt->bssid)) {
975 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_RX :
976 WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX]++;
977 if (sta->pwrmgt && !sta->pspoll)
978 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP]++;
979 else
980 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE]++;
981
982 fc = le_to_host16(mgmt->frame_control);
983 if (!(fc & WLAN_FC_ISWEP) && reason == 6)
984 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_RC6]++;
985 else if (!(fc & WLAN_FC_ISWEP) && reason == 7)
986 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_RC7]++;
987 } else
988 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_TX :
989 WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX]++;
990
991 if (!valid) {
992 add_note(wt, MSG_INFO, "Do not change STA " MACSTR " State "
993 "since Disassociation frame was not protected "
994 "correctly", MAC2STR(sta->addr));
995 return;
996 }
997
998 if (sta->state != STATE1) {
999 add_note(wt, MSG_DEBUG, "STA " MACSTR
1000 " moved to State 1 with " MACSTR,
1001 MAC2STR(sta->addr), MAC2STR(bss->bssid));
1002 sta->state = STATE1;
1003 }
1004 tdls_link_down(wt, bss, sta);
1005 }
1006
1007
get_fils_session(const u8 * ies,size_t ies_len)1008 static const u8 * get_fils_session(const u8 *ies, size_t ies_len)
1009 {
1010 const u8 *ie, *end;
1011
1012 ie = ies;
1013 end = ((const u8 *) ie) + ies_len;
1014 while (ie + 1 < end) {
1015 if (ie + 2 + ie[1] > end)
1016 break;
1017 if (ie[0] == WLAN_EID_EXTENSION &&
1018 ie[1] >= 1 + FILS_SESSION_LEN &&
1019 ie[2] == WLAN_EID_EXT_FILS_SESSION)
1020 return ie;
1021 ie += 2 + ie[1];
1022 }
1023 return NULL;
1024 }
1025
1026
try_rmsk(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,struct wlantest_pmk * pmk,const u8 * frame_start,const u8 * frame_ad,const u8 * frame_ad_end,const u8 * encr_end)1027 static int try_rmsk(struct wlantest *wt, struct wlantest_bss *bss,
1028 struct wlantest_sta *sta, struct wlantest_pmk *pmk,
1029 const u8 *frame_start, const u8 *frame_ad,
1030 const u8 *frame_ad_end, const u8 *encr_end)
1031 {
1032 size_t pmk_len = 0;
1033 u8 pmk_buf[PMK_LEN_MAX];
1034 struct wpa_ptk ptk;
1035 u8 ick[FILS_ICK_MAX_LEN];
1036 size_t ick_len;
1037 const u8 *aad[5];
1038 size_t aad_len[5];
1039 u8 buf[2000];
1040
1041 if (fils_rmsk_to_pmk(sta->key_mgmt, pmk->pmk, pmk->pmk_len,
1042 sta->snonce, sta->anonce, NULL, 0,
1043 pmk_buf, &pmk_len) < 0)
1044 return -1;
1045
1046 if (fils_pmk_to_ptk(pmk_buf, pmk_len, sta->addr, bss->bssid,
1047 sta->snonce, sta->anonce, NULL, 0,
1048 &ptk, ick, &ick_len,
1049 sta->key_mgmt, sta->pairwise_cipher,
1050 NULL, NULL, 0) < 0)
1051 return -1;
1052
1053 /* Check AES-SIV decryption with the derived key */
1054
1055 /* AES-SIV AAD vectors */
1056
1057 /* The STA's MAC address */
1058 aad[0] = sta->addr;
1059 aad_len[0] = ETH_ALEN;
1060 /* The AP's BSSID */
1061 aad[1] = bss->bssid;
1062 aad_len[1] = ETH_ALEN;
1063 /* The STA's nonce */
1064 aad[2] = sta->snonce;
1065 aad_len[2] = FILS_NONCE_LEN;
1066 /* The AP's nonce */
1067 aad[3] = sta->anonce;
1068 aad_len[3] = FILS_NONCE_LEN;
1069 /*
1070 * The (Re)Association Request frame from the Capability Information
1071 * field to the FILS Session element (both inclusive).
1072 */
1073 aad[4] = frame_ad;
1074 aad_len[4] = frame_ad_end - frame_ad;
1075
1076 if (encr_end - frame_ad_end < AES_BLOCK_SIZE ||
1077 encr_end - frame_ad_end > sizeof(buf))
1078 return -1;
1079 if (aes_siv_decrypt(ptk.kek, ptk.kek_len,
1080 frame_ad_end, encr_end - frame_ad_end,
1081 5, aad, aad_len, buf) < 0) {
1082 wpa_printf(MSG_DEBUG,
1083 "FILS: Derived PTK did not match AES-SIV data");
1084 return -1;
1085 }
1086
1087 add_note(wt, MSG_DEBUG, "Derived FILS PTK");
1088 os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
1089 sta->ptk_set = 1;
1090 sta->counters[WLANTEST_STA_COUNTER_PTK_LEARNED]++;
1091 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
1092 buf, encr_end - frame_ad_end - AES_BLOCK_SIZE);
1093
1094 if (wt->write_pcap_dumper || wt->pcapng) {
1095 write_pcap_decrypted(wt, frame_start,
1096 frame_ad_end - frame_start,
1097 buf,
1098 encr_end - frame_ad_end - AES_BLOCK_SIZE);
1099 }
1100
1101 return 0;
1102 }
1103
1104
derive_fils_keys(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const u8 * frame_start,const u8 * frame_ad,const u8 * frame_ad_end,const u8 * encr_end)1105 static void derive_fils_keys(struct wlantest *wt, struct wlantest_bss *bss,
1106 struct wlantest_sta *sta, const u8 *frame_start,
1107 const u8 *frame_ad, const u8 *frame_ad_end,
1108 const u8 *encr_end)
1109 {
1110 struct wlantest_pmk *pmk;
1111
1112 wpa_printf(MSG_DEBUG, "Trying to derive PTK for " MACSTR
1113 " from FILS rMSK", MAC2STR(sta->addr));
1114
1115 dl_list_for_each(pmk, &bss->pmk, struct wlantest_pmk,
1116 list) {
1117 wpa_printf(MSG_DEBUG, "Try per-BSS PMK");
1118 if (try_rmsk(wt, bss, sta, pmk, frame_start, frame_ad,
1119 frame_ad_end, encr_end) == 0)
1120 return;
1121 }
1122
1123 dl_list_for_each(pmk, &wt->pmk, struct wlantest_pmk, list) {
1124 wpa_printf(MSG_DEBUG, "Try global PMK");
1125 if (try_rmsk(wt, bss, sta, pmk, frame_start, frame_ad,
1126 frame_ad_end, encr_end) == 0)
1127 return;
1128 }
1129 }
1130
1131
dump_mld_info(struct wlantest * wt,struct wlantest_sta * sta)1132 static void dump_mld_info(struct wlantest *wt, struct wlantest_sta *sta)
1133 {
1134 int link_id;
1135 struct wlantest_bss *bss;
1136 u8 zero[ETH_ALEN];
1137 const u8 *bssid;
1138
1139 wpa_printf(MSG_INFO, "MLO association - AP MLD: " MACSTR
1140 " STA MLD: " MACSTR,
1141 MAC2STR(sta->bss->mld_mac_addr), MAC2STR(sta->mld_mac_addr));
1142
1143 os_memset(zero, 0, ETH_ALEN);
1144
1145 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
1146 bss = bss_find_mld(wt, sta->bss->mld_mac_addr, link_id);
1147 if (!bss &&
1148 is_zero_ether_addr(sta->link_addr[link_id]))
1149 continue;
1150 if (bss)
1151 bssid = bss->bssid;
1152 else
1153 bssid = zero;
1154 wpa_printf(MSG_INFO, " Link %u - AP: " MACSTR " STA: " MACSTR,
1155 link_id, MAC2STR(bssid),
1156 MAC2STR(sta->link_addr[link_id]));
1157 }
1158 }
1159
1160
rx_mgmt_assoc_req(struct wlantest * wt,const u8 * data,size_t len)1161 static void rx_mgmt_assoc_req(struct wlantest *wt, const u8 *data, size_t len)
1162 {
1163 const struct ieee80211_mgmt *mgmt;
1164 struct wlantest_bss *bss;
1165 struct wlantest_sta *sta;
1166 struct ieee802_11_elems elems;
1167 const u8 *ie;
1168 size_t ie_len;
1169
1170 mgmt = (const struct ieee80211_mgmt *) data;
1171 bss = bss_get(wt, mgmt->bssid);
1172 if (bss == NULL)
1173 return;
1174 sta = sta_get(bss, mgmt->sa);
1175 if (sta == NULL)
1176 return;
1177
1178 if (len < 24 + 4) {
1179 add_note(wt, MSG_INFO, "Too short Association Request frame "
1180 "from " MACSTR, MAC2STR(mgmt->sa));
1181 return;
1182 }
1183
1184 wpa_printf(MSG_DEBUG, "ASSOCREQ " MACSTR " -> " MACSTR
1185 " (capab=0x%x listen_int=%u)",
1186 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
1187 le_to_host16(mgmt->u.assoc_req.capab_info),
1188 le_to_host16(mgmt->u.assoc_req.listen_interval));
1189
1190 sta->counters[WLANTEST_STA_COUNTER_ASSOCREQ_TX]++;
1191
1192 ie = mgmt->u.assoc_req.variable;
1193 ie_len = len - (mgmt->u.assoc_req.variable - data);
1194
1195 if (sta->auth_alg == WLAN_AUTH_FILS_SK) {
1196 const u8 *session, *frame_ad, *frame_ad_end, *encr_end;
1197
1198 session = get_fils_session(ie, ie_len);
1199 if (session) {
1200 frame_ad = (const u8 *) &mgmt->u.assoc_req.capab_info;
1201 frame_ad_end = session + 2 + session[1];
1202 encr_end = data + len;
1203 derive_fils_keys(wt, bss, sta, data, frame_ad,
1204 frame_ad_end, encr_end);
1205 ie_len = session - ie;
1206 }
1207 }
1208
1209 if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
1210 add_note(wt, MSG_INFO, "Invalid IEs in Association Request "
1211 "frame from " MACSTR, MAC2STR(mgmt->sa));
1212 return;
1213 }
1214
1215 if (elems.rsn_selection) {
1216 sta->rsn_selection = elems.rsn_selection[0];
1217 wpa_printf(MSG_DEBUG, "RSNO: RSN Selection %u",
1218 sta->rsn_selection);
1219 } else {
1220 sta->rsn_selection = RSN_SELECTION_RSNE;
1221 }
1222
1223 if (elems.rsnxe) {
1224 os_memcpy(sta->rsnxe, elems.rsnxe, elems.rsnxe_len);
1225 sta->rsnxe_len = elems.rsnxe_len;
1226 }
1227
1228 if (elems.owe_dh && elems.owe_dh_len >= 2) {
1229 sta->owe_group = WPA_GET_LE16(elems.owe_dh);
1230 wpa_printf(MSG_DEBUG, "OWE using group %u", sta->owe_group);
1231 }
1232
1233 sta->assocreq_capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
1234 sta->assocreq_listen_int =
1235 le_to_host16(mgmt->u.assoc_req.listen_interval);
1236 os_free(sta->assocreq_ies);
1237 sta->assocreq_ies_len = len - (mgmt->u.assoc_req.variable - data);
1238 sta->assocreq_ies = os_malloc(sta->assocreq_ies_len);
1239 if (sta->assocreq_ies)
1240 os_memcpy(sta->assocreq_ies, mgmt->u.assoc_req.variable,
1241 sta->assocreq_ies_len);
1242
1243 sta->assocreq_seen = 1;
1244 sta_update_assoc(sta, &elems);
1245 if (elems.basic_mle) {
1246 if (bss->link_id_set) {
1247 os_memcpy(sta->link_addr[bss->link_id], mgmt->sa,
1248 ETH_ALEN);
1249 wpa_printf(MSG_DEBUG,
1250 "Learned Link ID %u MAC address "
1251 MACSTR
1252 " from Association Request (assoc link)",
1253 bss->link_id, MAC2STR(mgmt->sa));
1254 }
1255 parse_basic_ml_elems(&elems, false, sta, 2);
1256 dump_mld_info(wt, sta);
1257 }
1258 }
1259
1260
decrypt_fils_assoc_resp(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const u8 * frame_start,const u8 * frame_ad,const u8 * frame_ad_end,const u8 * encr_end)1261 static void decrypt_fils_assoc_resp(struct wlantest *wt,
1262 struct wlantest_bss *bss,
1263 struct wlantest_sta *sta,
1264 const u8 *frame_start, const u8 *frame_ad,
1265 const u8 *frame_ad_end, const u8 *encr_end)
1266 {
1267 const u8 *aad[5];
1268 size_t aad_len[5];
1269 u8 buf[2000];
1270
1271 if (!sta->ptk_set)
1272 return;
1273
1274 /* Check AES-SIV decryption with the derived key */
1275
1276 /* AES-SIV AAD vectors */
1277
1278 /* The AP's BSSID */
1279 aad[0] = bss->bssid;
1280 aad_len[0] = ETH_ALEN;
1281 /* The STA's MAC address */
1282 aad[1] = sta->addr;
1283 aad_len[1] = ETH_ALEN;
1284 /* The AP's nonce */
1285 aad[2] = sta->anonce;
1286 aad_len[2] = FILS_NONCE_LEN;
1287 /* The STA's nonce */
1288 aad[3] = sta->snonce;
1289 aad_len[3] = FILS_NONCE_LEN;
1290 /*
1291 * The (Re)Association Response frame from the Capability Information
1292 * field to the FILS Session element (both inclusive).
1293 */
1294 aad[4] = frame_ad;
1295 aad_len[4] = frame_ad_end - frame_ad;
1296
1297 if (encr_end - frame_ad_end < AES_BLOCK_SIZE ||
1298 encr_end - frame_ad_end > sizeof(buf))
1299 return;
1300 if (aes_siv_decrypt(sta->ptk.kek, sta->ptk.kek_len,
1301 frame_ad_end, encr_end - frame_ad_end,
1302 5, aad, aad_len, buf) < 0) {
1303 wpa_printf(MSG_DEBUG,
1304 "FILS: Derived PTK did not match AES-SIV data");
1305 return;
1306 }
1307
1308 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Response elements",
1309 buf, encr_end - frame_ad_end - AES_BLOCK_SIZE);
1310
1311 if (wt->write_pcap_dumper || wt->pcapng) {
1312 write_pcap_decrypted(wt, frame_start,
1313 frame_ad_end - frame_start,
1314 buf,
1315 encr_end - frame_ad_end - AES_BLOCK_SIZE);
1316 }
1317 }
1318
1319
rx_mgmt_assoc_resp(struct wlantest * wt,const u8 * data,size_t len)1320 static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len)
1321 {
1322 const struct ieee80211_mgmt *mgmt;
1323 struct wlantest_bss *bss;
1324 struct wlantest_sta *sta;
1325 u16 capab, status, aid;
1326 struct ieee802_11_elems elems;
1327 const u8 *ies;
1328 size_t ies_len;
1329 struct wpa_ft_ies parse;
1330 const u8 *ml;
1331
1332 mgmt = (const struct ieee80211_mgmt *) data;
1333 bss = bss_get(wt, mgmt->bssid);
1334 if (bss == NULL)
1335 return;
1336 sta = sta_get(bss, mgmt->da);
1337 if (sta == NULL)
1338 return;
1339
1340 if (len < 24 + 6) {
1341 add_note(wt, MSG_INFO, "Too short Association Response frame "
1342 "from " MACSTR, MAC2STR(mgmt->sa));
1343 return;
1344 }
1345
1346 ies = mgmt->u.assoc_resp.variable;
1347 ies_len = len - (mgmt->u.assoc_resp.variable - data);
1348
1349 capab = le_to_host16(mgmt->u.assoc_resp.capab_info);
1350 status = le_to_host16(mgmt->u.assoc_resp.status_code);
1351 aid = le_to_host16(mgmt->u.assoc_resp.aid);
1352
1353 wpa_printf(MSG_DEBUG, "ASSOCRESP " MACSTR " -> " MACSTR
1354 " (capab=0x%x status=%u aid=%u)",
1355 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
1356 aid & 0x3fff);
1357
1358 ml = get_ml_ie(ies, ies_len, MULTI_LINK_CONTROL_TYPE_BASIC);
1359 if (ml &&
1360 ieee802_11_parse_elems(ies, ies_len, &elems, 0) != ParseFailed)
1361 parse_basic_ml_elems(&elems, true, NULL, 4);
1362
1363 if (sta->auth_alg == WLAN_AUTH_FILS_SK) {
1364 const u8 *session, *frame_ad, *frame_ad_end, *encr_end;
1365
1366 session = get_fils_session(ies, ies_len);
1367 if (session) {
1368 frame_ad = (const u8 *) &mgmt->u.assoc_resp.capab_info;
1369 frame_ad_end = session + 2 + session[1];
1370 encr_end = data + len;
1371 decrypt_fils_assoc_resp(wt, bss, sta, data, frame_ad,
1372 frame_ad_end, encr_end);
1373 ies_len = session - ies;
1374 }
1375 }
1376
1377 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed) {
1378 add_note(wt, MSG_INFO,
1379 "Failed to parse IEs in AssocResp from " MACSTR,
1380 MAC2STR(mgmt->sa));
1381 }
1382
1383 if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
1384 if (!elems.timeout_int ||
1385 elems.timeout_int[0] != WLAN_TIMEOUT_ASSOC_COMEBACK) {
1386 add_note(wt, MSG_INFO, "No valid Timeout Interval IE "
1387 "with Assoc Comeback time in AssocResp "
1388 "(status=30) from " MACSTR,
1389 MAC2STR(mgmt->sa));
1390 } else {
1391 sta->counters[
1392 WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK]++;
1393 }
1394 }
1395
1396 if (status)
1397 return;
1398
1399 if ((aid & 0xc000) != 0xc000) {
1400 add_note(wt, MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
1401 "in Association Response from " MACSTR,
1402 MAC2STR(mgmt->sa));
1403 }
1404 sta->aid = aid & 0xc000;
1405
1406 if (sta->state < STATE2) {
1407 add_note(wt, MSG_DEBUG,
1408 "STA " MACSTR " was not in State 2 when "
1409 "getting associated", MAC2STR(sta->addr));
1410 }
1411
1412 if (sta->state < STATE3) {
1413 add_note(wt, MSG_DEBUG, "STA " MACSTR
1414 " moved to State 3 with " MACSTR,
1415 MAC2STR(sta->addr), MAC2STR(bss->bssid));
1416 sta->state = STATE3;
1417 }
1418
1419 if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, false) == 0) {
1420 if (parse.r0kh_id) {
1421 os_memcpy(bss->r0kh_id, parse.r0kh_id,
1422 parse.r0kh_id_len);
1423 bss->r0kh_id_len = parse.r0kh_id_len;
1424 }
1425 if (parse.r1kh_id)
1426 os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
1427 wpa_ft_parse_ies_free(&parse);
1428 }
1429
1430 if (elems.owe_dh && elems.owe_dh_len >= 2) {
1431 sta->owe_group = WPA_GET_LE16(elems.owe_dh);
1432 wpa_printf(MSG_DEBUG, "OWE using group %u", sta->owe_group);
1433 }
1434 }
1435
1436
rx_mgmt_reassoc_req(struct wlantest * wt,const u8 * data,size_t len)1437 static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data,
1438 size_t len)
1439 {
1440 const struct ieee80211_mgmt *mgmt;
1441 struct wlantest_bss *bss;
1442 struct wlantest_sta *sta;
1443 struct ieee802_11_elems elems;
1444 const u8 *ie;
1445 size_t ie_len;
1446
1447 mgmt = (const struct ieee80211_mgmt *) data;
1448 bss = bss_get(wt, mgmt->bssid);
1449 if (bss == NULL)
1450 return;
1451
1452 if (len < 24 + 4 + ETH_ALEN) {
1453 add_note(wt, MSG_INFO, "Too short Reassociation Request frame "
1454 "from " MACSTR, MAC2STR(mgmt->sa));
1455 return;
1456 }
1457
1458 wpa_printf(MSG_DEBUG, "REASSOCREQ " MACSTR " -> " MACSTR
1459 " (capab=0x%x listen_int=%u current_ap=" MACSTR ")",
1460 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
1461 le_to_host16(mgmt->u.reassoc_req.capab_info),
1462 le_to_host16(mgmt->u.reassoc_req.listen_interval),
1463 MAC2STR(mgmt->u.reassoc_req.current_ap));
1464
1465 ie = mgmt->u.reassoc_req.variable;
1466 ie_len = len - (mgmt->u.reassoc_req.variable - data);
1467
1468 if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
1469 add_note(wt, MSG_INFO,
1470 "Invalid IEs in Reassociation Request frame from "
1471 MACSTR, MAC2STR(mgmt->sa));
1472 return;
1473 }
1474
1475 sta = sta_find_mlo(wt, bss, mgmt->sa);
1476 /*
1477 * In the case of FT over-the-DS roaming, STA entry was created with the
1478 * MLD MAC address and attached to one of the BSSs affiliated with the
1479 * AP MLD but that BSS might not be in the STA's requested reassociation
1480 * links, so move it to reassociation link BSS and update STA link
1481 * address.
1482 */
1483 if (!sta && elems.basic_mle) {
1484 const u8 *mld_addr;
1485 struct wlantest_sta *sta1;
1486
1487 mld_addr = get_basic_mle_mld_addr(elems.basic_mle,
1488 elems.basic_mle_len);
1489 if (!mld_addr)
1490 return;
1491
1492 sta1 = sta_find_mlo(wt, bss, mld_addr);
1493 if (sta1 && sta1->ft_over_ds) {
1494 dl_list_del(&sta1->list);
1495 dl_list_add(&bss->sta, &sta1->list);
1496 wpa_printf(MSG_DEBUG,
1497 "Move existing STA entry from another affiliated BSS to the reassociation BSS (addr "
1498 MACSTR " -> " MACSTR ")",
1499 MAC2STR(sta1->addr), MAC2STR(mgmt->sa));
1500 os_memcpy(sta1->addr, mgmt->sa, ETH_ALEN);
1501 sta = sta1;
1502 }
1503 }
1504 if (!sta)
1505 sta = sta_get(bss, mgmt->sa);
1506 if (!sta)
1507 return;
1508
1509 sta->counters[WLANTEST_STA_COUNTER_REASSOCREQ_TX]++;
1510
1511 if (sta->auth_alg == WLAN_AUTH_FILS_SK) {
1512 const u8 *session, *frame_ad, *frame_ad_end, *encr_end;
1513
1514 session = get_fils_session(ie, ie_len);
1515 if (session) {
1516 frame_ad = (const u8 *) &mgmt->u.reassoc_req.capab_info;
1517 frame_ad_end = session + 2 + session[1];
1518 encr_end = data + len;
1519 derive_fils_keys(wt, bss, sta, data, frame_ad,
1520 frame_ad_end, encr_end);
1521 ie_len = session - ie;
1522 }
1523 }
1524
1525 if (elems.rsnxe) {
1526 os_memcpy(sta->rsnxe, elems.rsnxe, elems.rsnxe_len);
1527 sta->rsnxe_len = elems.rsnxe_len;
1528 }
1529
1530 if (elems.owe_dh && elems.owe_dh_len >= 2) {
1531 sta->owe_group = WPA_GET_LE16(elems.owe_dh);
1532 wpa_printf(MSG_DEBUG, "OWE using group %u", sta->owe_group);
1533 }
1534
1535 sta->assocreq_capab_info =
1536 le_to_host16(mgmt->u.reassoc_req.capab_info);
1537 sta->assocreq_listen_int =
1538 le_to_host16(mgmt->u.reassoc_req.listen_interval);
1539 os_free(sta->assocreq_ies);
1540 sta->assocreq_ies_len = len - (mgmt->u.reassoc_req.variable - data);
1541 sta->assocreq_ies = os_malloc(sta->assocreq_ies_len);
1542 if (sta->assocreq_ies)
1543 os_memcpy(sta->assocreq_ies, mgmt->u.reassoc_req.variable,
1544 sta->assocreq_ies_len);
1545
1546 sta->assocreq_seen = 1;
1547 sta_update_assoc(sta, &elems);
1548 if (elems.basic_mle) {
1549 os_memset(sta->link_addr, 0, sizeof(sta->link_addr));
1550 if (bss->link_id_set) {
1551 os_memcpy(sta->link_addr[bss->link_id], mgmt->sa,
1552 ETH_ALEN);
1553 wpa_printf(MSG_DEBUG,
1554 "Learned Link ID %u MAC address "
1555 MACSTR
1556 " from Reassociation Request (assoc link)",
1557 bss->link_id, MAC2STR(mgmt->sa));
1558 }
1559 parse_basic_ml_elems(&elems, false, sta, 2);
1560 dump_mld_info(wt, sta);
1561 }
1562
1563 if (elems.ftie) {
1564 struct wpa_ft_ies parse;
1565 int use_sha384;
1566 struct rsn_mdie *mde;
1567 const u8 *anonce, *snonce, *fte_mic;
1568 u8 fte_elem_count;
1569 unsigned int count;
1570 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
1571 size_t mic_len = 16;
1572 const u8 *kck;
1573 size_t kck_len;
1574 const u8 *aa, *spa;
1575 struct wpabuf *extra = NULL;
1576
1577 if (elems.basic_mle) {
1578 aa = bss->mld_mac_addr;
1579 spa = sta->mld_mac_addr;
1580 } else {
1581 aa = bss->bssid;
1582 spa = sta->addr;
1583 }
1584
1585 use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt);
1586
1587 if (wpa_ft_parse_ies(ie, ie_len, &parse, sta->key_mgmt,
1588 false) < 0) {
1589 add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs");
1590 return;
1591 }
1592
1593 if (!parse.rsn) {
1594 add_note(wt, MSG_INFO, "FT: No RSNE in Reassoc Req");
1595 goto out;
1596 }
1597
1598 if (!parse.rsn_pmkid) {
1599 add_note(wt, MSG_INFO, "FT: No PMKID in RSNE");
1600 goto out;
1601 }
1602
1603 if (os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name,
1604 WPA_PMK_NAME_LEN) != 0) {
1605 add_note(wt, MSG_INFO,
1606 "FT: PMKID in Reassoc Req did not match PMKR1Name");
1607 wpa_hexdump(MSG_DEBUG,
1608 "FT: Received RSNE[PMKR1Name]",
1609 parse.rsn_pmkid, WPA_PMK_NAME_LEN);
1610 wpa_hexdump(MSG_DEBUG,
1611 "FT: Previously derived PMKR1Name",
1612 sta->pmk_r1_name, WPA_PMK_NAME_LEN);
1613 goto out;
1614 }
1615
1616 mde = (struct rsn_mdie *) parse.mdie;
1617 if (!mde || parse.mdie_len < sizeof(*mde) ||
1618 os_memcmp(mde->mobility_domain, bss->mdid,
1619 MOBILITY_DOMAIN_ID_LEN) != 0) {
1620 add_note(wt, MSG_INFO, "FT: Invalid MDE");
1621 }
1622
1623 if (use_sha384) {
1624 struct rsn_ftie_sha384 *fte;
1625
1626 fte = (struct rsn_ftie_sha384 *) parse.ftie;
1627 if (!fte || parse.ftie_len < sizeof(*fte)) {
1628 add_note(wt, MSG_INFO, "FT: Invalid FTE");
1629 goto out;
1630 }
1631
1632 anonce = fte->anonce;
1633 snonce = fte->snonce;
1634 fte_elem_count = fte->mic_control[1];
1635 fte_mic = fte->mic;
1636 } else {
1637 struct rsn_ftie *fte;
1638
1639 fte = (struct rsn_ftie *) parse.ftie;
1640 if (!fte || parse.ftie_len < sizeof(*fte)) {
1641 add_note(wt, MSG_INFO, "FT: Invalid FTIE");
1642 goto out;
1643 }
1644
1645 anonce = fte->anonce;
1646 snonce = fte->snonce;
1647 fte_elem_count = fte->mic_control[1];
1648 fte_mic = fte->mic;
1649 }
1650
1651 if (os_memcmp(snonce, sta->snonce, WPA_NONCE_LEN) != 0) {
1652 add_note(wt, MSG_INFO, "FT: SNonce mismatch in FTIE");
1653 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
1654 snonce, WPA_NONCE_LEN);
1655 wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
1656 sta->snonce, WPA_NONCE_LEN);
1657 goto out;
1658 }
1659
1660 if (os_memcmp(anonce, sta->anonce, WPA_NONCE_LEN) != 0) {
1661 add_note(wt, MSG_INFO, "FT: ANonce mismatch in FTIE");
1662 wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
1663 anonce, WPA_NONCE_LEN);
1664 wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
1665 sta->anonce, WPA_NONCE_LEN);
1666 goto out;
1667 }
1668
1669 if (!parse.r0kh_id) {
1670 add_note(wt, MSG_INFO, "FT: No R0KH-ID subelem in FTE");
1671 goto out;
1672 }
1673 os_memcpy(bss->r0kh_id, parse.r0kh_id, parse.r0kh_id_len);
1674 bss->r0kh_id_len = parse.r0kh_id_len;
1675
1676 if (!parse.r1kh_id) {
1677 add_note(wt, MSG_INFO, "FT: No R1KH-ID subelem in FTE");
1678 goto out;
1679 }
1680
1681 os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
1682
1683 if (!parse.rsn_pmkid ||
1684 os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name,
1685 WPA_PMK_NAME_LEN)) {
1686 add_note(wt, MSG_INFO,
1687 "FT: No matching PMKR1Name (PMKID) in RSNE (pmkid=%d)",
1688 !!parse.rsn_pmkid);
1689 goto out;
1690 }
1691
1692 count = 3;
1693 if (parse.ric)
1694 count += ieee802_11_ie_count(parse.ric, parse.ric_len);
1695 if (parse.rsnxe)
1696 count++;
1697 if (fte_elem_count != count) {
1698 add_note(wt, MSG_INFO,
1699 "FT: Unexpected IE count in MIC Control: received %u expected %u",
1700 fte_elem_count, count);
1701 goto out;
1702 }
1703
1704 if (wpa_key_mgmt_fils(sta->key_mgmt)) {
1705 kck = sta->ptk.kck2;
1706 kck_len = sta->ptk.kck2_len;
1707 } else {
1708 kck = sta->ptk.kck;
1709 kck_len = sta->ptk.kck_len;
1710 }
1711
1712 if (elems.basic_mle) {
1713 int i;
1714
1715 extra = wpabuf_alloc(MAX_NUM_MLD_LINKS * ETH_ALEN);
1716 if (!extra)
1717 goto out;
1718 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
1719 if (!is_zero_ether_addr(sta->link_addr[i]))
1720 wpabuf_put_data(extra,
1721 sta->link_addr[i],
1722 ETH_ALEN);
1723 }
1724 }
1725
1726 if (wpa_ft_mic(sta->key_mgmt, kck, kck_len,
1727 spa, aa, 5,
1728 parse.mdie - 2, parse.mdie_len + 2,
1729 parse.ftie - 2, parse.ftie_len + 2,
1730 parse.rsn - 2, parse.rsn_len + 2,
1731 parse.ric, parse.ric_len,
1732 parse.rsnxe ? parse.rsnxe - 2 : NULL,
1733 parse.rsnxe ? parse.rsnxe_len + 2 : 0,
1734 extra,
1735 mic) < 0) {
1736 wpabuf_free(extra);
1737 add_note(wt, MSG_INFO, "FT: Failed to calculate MIC");
1738 goto out;
1739 }
1740 wpabuf_free(extra);
1741
1742 if (os_memcmp_const(mic, fte_mic, mic_len) != 0) {
1743 int link_id;
1744
1745 add_note(wt, MSG_INFO, "FT: Invalid MIC in FTE");
1746 wpa_printf(MSG_DEBUG,
1747 "FT: addr=" MACSTR " auth_addr=" MACSTR,
1748 MAC2STR(spa), MAC2STR(aa));
1749 wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC",
1750 fte_mic, mic_len);
1751 wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC",
1752 mic, mic_len);
1753 wpa_hexdump(MSG_MSGDUMP, "FT: MDE",
1754 parse.mdie - 2, parse.mdie_len + 2);
1755 wpa_hexdump(MSG_MSGDUMP, "FT: FTE",
1756 parse.ftie - 2, parse.ftie_len + 2);
1757 wpa_hexdump(MSG_MSGDUMP, "FT: RSN",
1758 parse.rsn - 2, parse.rsn_len + 2);
1759 wpa_hexdump(MSG_MSGDUMP, "FT: RSNXE",
1760 parse.rsnxe ? parse.rsnxe - 2 : NULL,
1761 parse.rsnxe ? parse.rsnxe_len + 2 : 0);
1762 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS;
1763 link_id++) {
1764 if (is_zero_ether_addr(sta->link_addr[link_id]))
1765 continue;
1766 wpa_printf(MSG_DEBUG,
1767 "FT: STA link %d address: " MACSTR,
1768 link_id,
1769 MAC2STR(sta->link_addr[link_id]));
1770 }
1771 goto out;
1772 }
1773
1774 add_note(wt, MSG_INFO, "FT: Valid FTE MIC");
1775 out:
1776 wpa_ft_parse_ies_free(&parse);
1777 }
1778 }
1779
1780
process_gtk_subelem(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const u8 * kek,size_t kek_len,const u8 * gtk_elem,size_t gtk_elem_len,bool mlo)1781 static void process_gtk_subelem(struct wlantest *wt, struct wlantest_bss *bss,
1782 struct wlantest_sta *sta,
1783 const u8 *kek, size_t kek_len,
1784 const u8 *gtk_elem,
1785 size_t gtk_elem_len, bool mlo)
1786 {
1787 u8 gtk[32];
1788 int keyidx;
1789 enum wpa_alg alg;
1790 size_t gtk_len, keylen;
1791 const u8 *rsc;
1792 size_t hlen;
1793
1794 if (!gtk_elem) {
1795 add_note(wt, MSG_INFO, "FT: No GTK included in FTE");
1796 return;
1797 }
1798
1799 wpa_hexdump(MSG_DEBUG, "FT: Received GTK in Reassoc Resp",
1800 gtk_elem, gtk_elem_len);
1801
1802 hlen = 2 + 1 + 8;
1803 if (mlo)
1804 hlen++;
1805 if (gtk_elem_len < hlen + 24 || (gtk_elem_len - hlen) % 8 ||
1806 gtk_elem_len - (hlen + 8) > sizeof(gtk)) {
1807 add_note(wt, MSG_INFO, "FT: Invalid GTK sub-elem length %zu",
1808 gtk_elem_len);
1809 return;
1810 }
1811 gtk_len = gtk_elem_len - (hlen + 8);
1812 if (aes_unwrap(kek, kek_len, gtk_len / 8, gtk_elem + hlen, gtk)) {
1813 add_note(wt, MSG_INFO,
1814 "FT: AES unwrap failed - could not decrypt GTK");
1815 return;
1816 }
1817
1818 keylen = wpa_cipher_key_len(bss->group_cipher);
1819 alg = wpa_cipher_to_alg(bss->group_cipher);
1820 if (alg == WPA_ALG_NONE) {
1821 add_note(wt, MSG_INFO, "FT: Unsupported Group Cipher %d",
1822 bss->group_cipher);
1823 return;
1824 }
1825
1826 if (gtk_len < keylen) {
1827 add_note(wt, MSG_INFO, "FT: Too short GTK in FTE");
1828 return;
1829 }
1830
1831 /* Key Info[2] | [Link ID Info[1] | Key Length[1] | RSC[8] |
1832 * Key[5..32]. */
1833
1834 keyidx = WPA_GET_LE16(gtk_elem) & 0x03;
1835
1836 if (gtk_elem[hlen - 8 - 1] != keylen) {
1837 add_note(wt, MSG_INFO,
1838 "FT: GTK length mismatch: received %u negotiated %zu",
1839 gtk_elem[hlen - 8 - 1], keylen);
1840 return;
1841 }
1842
1843 add_note(wt, MSG_DEBUG, "GTK KeyID=%u", keyidx);
1844 wpa_hexdump(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen);
1845 if (bss->group_cipher == WPA_CIPHER_TKIP) {
1846 /* Swap Tx/Rx keys for Michael MIC */
1847 u8 tmp[8];
1848
1849 os_memcpy(tmp, gtk + 16, 8);
1850 os_memcpy(gtk + 16, gtk + 24, 8);
1851 os_memcpy(gtk + 24, tmp, 8);
1852 }
1853
1854 bss->gtk_len[keyidx] = gtk_len;
1855 if (sta)
1856 sta->gtk_len = gtk_len;
1857 os_memcpy(bss->gtk[keyidx], gtk, gtk_len);
1858 if (sta)
1859 os_memcpy(sta->gtk, gtk, gtk_len);
1860 rsc = gtk_elem + hlen - 8;
1861 bss->rsc[keyidx][0] = rsc[5];
1862 bss->rsc[keyidx][1] = rsc[4];
1863 bss->rsc[keyidx][2] = rsc[3];
1864 bss->rsc[keyidx][3] = rsc[2];
1865 bss->rsc[keyidx][4] = rsc[1];
1866 bss->rsc[keyidx][5] = rsc[0];
1867 bss->gtk_idx = keyidx;
1868 if (sta)
1869 sta->gtk_idx = keyidx;
1870 wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[keyidx], 6);
1871 }
1872
1873
process_igtk_subelem(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const u8 * kek,size_t kek_len,const u8 * igtk_elem,size_t igtk_elem_len,bool mlo)1874 static void process_igtk_subelem(struct wlantest *wt, struct wlantest_bss *bss,
1875 struct wlantest_sta *sta,
1876 const u8 *kek, size_t kek_len,
1877 const u8 *igtk_elem, size_t igtk_elem_len,
1878 bool mlo)
1879 {
1880 u8 igtk[WPA_IGTK_MAX_LEN];
1881 size_t igtk_len;
1882 u16 keyidx;
1883 const u8 *ipn;
1884 size_t hlen;
1885
1886 if (bss->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC &&
1887 bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 &&
1888 bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 &&
1889 bss->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256)
1890 return;
1891
1892 if (!igtk_elem) {
1893 add_note(wt, MSG_INFO, "FT: No IGTK included in FTE");
1894 return;
1895 }
1896
1897 wpa_hexdump(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp",
1898 igtk_elem, igtk_elem_len);
1899
1900 igtk_len = wpa_cipher_key_len(bss->mgmt_group_cipher);
1901 hlen = 2 + 6 + 1;
1902 if (mlo)
1903 hlen++;
1904 if (igtk_elem_len != hlen + igtk_len + 8) {
1905 add_note(wt, MSG_INFO, "FT: Invalid IGTK sub-elem length %zu",
1906 igtk_elem_len);
1907 return;
1908 }
1909 if (igtk_elem[hlen - 1] != igtk_len) {
1910 add_note(wt, MSG_INFO,
1911 "FT: Invalid IGTK sub-elem Key Length %d",
1912 igtk_elem[hlen - 1]);
1913 return;
1914 }
1915
1916 if (aes_unwrap(kek, kek_len, igtk_len / 8, igtk_elem + hlen, igtk)) {
1917 add_note(wt, MSG_INFO,
1918 "FT: AES unwrap failed - could not decrypt IGTK");
1919 return;
1920 }
1921
1922 /* KeyID[2] | IPN[6] | [Link ID info[1]] | Key Length[1] | Key[16+8] */
1923
1924 keyidx = WPA_GET_LE16(igtk_elem);
1925
1926 wpa_hexdump(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk, igtk_len);
1927
1928 if (keyidx < 4 || keyidx > 5) {
1929 add_note(wt, MSG_INFO, "Unexpected IGTK KeyID %u", keyidx);
1930 return;
1931 }
1932
1933 add_note(wt, MSG_DEBUG, "IGTK KeyID %u", keyidx);
1934 wpa_hexdump(MSG_DEBUG, "IPN", igtk_elem + 2, 6);
1935 wpa_hexdump(MSG_DEBUG, "IGTK", igtk, igtk_len);
1936 os_memcpy(bss->igtk[keyidx], igtk, igtk_len);
1937 bss->igtk_len[keyidx] = igtk_len;
1938 ipn = igtk_elem + 2;
1939 bss->ipn[keyidx][0] = ipn[5];
1940 bss->ipn[keyidx][1] = ipn[4];
1941 bss->ipn[keyidx][2] = ipn[3];
1942 bss->ipn[keyidx][3] = ipn[2];
1943 bss->ipn[keyidx][4] = ipn[1];
1944 bss->ipn[keyidx][5] = ipn[0];
1945 bss->igtk_idx = keyidx;
1946 }
1947
1948
process_bigtk_subelem(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const u8 * kek,size_t kek_len,const u8 * bigtk_elem,size_t bigtk_elem_len,bool mlo)1949 static void process_bigtk_subelem(struct wlantest *wt, struct wlantest_bss *bss,
1950 struct wlantest_sta *sta,
1951 const u8 *kek, size_t kek_len,
1952 const u8 *bigtk_elem, size_t bigtk_elem_len,
1953 bool mlo)
1954 {
1955 u8 bigtk[WPA_BIGTK_MAX_LEN];
1956 size_t bigtk_len;
1957 u16 keyidx;
1958 const u8 *ipn;
1959 size_t hlen;
1960
1961 if (!bigtk_elem ||
1962 (bss->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC &&
1963 bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 &&
1964 bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 &&
1965 bss->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256))
1966 return;
1967
1968 wpa_hexdump_key(MSG_DEBUG, "FT: Received BIGTK in Reassoc Resp",
1969 bigtk_elem, bigtk_elem_len);
1970
1971 bigtk_len = wpa_cipher_key_len(bss->mgmt_group_cipher);
1972 hlen = 2 + 6 + 1;
1973 if (mlo)
1974 hlen++;
1975 if (bigtk_elem_len != hlen + bigtk_len + 8) {
1976 add_note(wt, MSG_INFO,
1977 "FT: Invalid BIGTK sub-elem length %zu",
1978 bigtk_elem_len);
1979 return;
1980 }
1981 if (bigtk_elem[hlen - 1] != bigtk_len) {
1982 add_note(wt, MSG_INFO,
1983 "FT: Invalid BIGTK sub-elem Key Length %d",
1984 bigtk_elem[8]);
1985 return;
1986 }
1987
1988 if (aes_unwrap(kek, kek_len, bigtk_len / 8, bigtk_elem + hlen, bigtk)) {
1989 add_note(wt, MSG_INFO,
1990 "FT: AES unwrap failed - could not decrypt BIGTK");
1991 return;
1992 }
1993
1994 /* KeyID[2] | IPN[6] | [Link ID Info[1]] | Key Length[1] | Key[16+8] */
1995
1996 keyidx = WPA_GET_LE16(bigtk_elem);
1997
1998 wpa_hexdump(MSG_DEBUG, "FT: BIGTK from Reassoc Resp", bigtk, bigtk_len);
1999
2000 if (keyidx < 6 || keyidx > 7) {
2001 add_note(wt, MSG_INFO, "Unexpected BIGTK KeyID %u", keyidx);
2002 return;
2003 }
2004
2005 add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", keyidx);
2006 wpa_hexdump(MSG_DEBUG, "BIPN", bigtk_elem + 2, 6);
2007 wpa_hexdump(MSG_DEBUG, "BIGTK", bigtk, bigtk_len);
2008 os_memcpy(bss->igtk[keyidx], bigtk, bigtk_len);
2009 bss->igtk_len[keyidx] = bigtk_len;
2010 ipn = bigtk_elem + 2;
2011 bss->ipn[keyidx][0] = ipn[5];
2012 bss->ipn[keyidx][1] = ipn[4];
2013 bss->ipn[keyidx][2] = ipn[3];
2014 bss->ipn[keyidx][3] = ipn[2];
2015 bss->ipn[keyidx][4] = ipn[1];
2016 bss->ipn[keyidx][5] = ipn[0];
2017 bss->bigtk_idx = keyidx;
2018 }
2019
2020
process_fte_group_keys(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const u8 * kek,size_t kek_len,struct wpa_ft_ies * parse)2021 static void process_fte_group_keys(struct wlantest *wt,
2022 struct wlantest_bss *bss,
2023 struct wlantest_sta *sta,
2024 const u8 *kek, size_t kek_len,
2025 struct wpa_ft_ies *parse)
2026 {
2027 process_gtk_subelem(wt, bss, sta, kek, kek_len,
2028 parse->gtk, parse->gtk_len, false);
2029 process_igtk_subelem(wt, bss, sta, kek, kek_len,
2030 parse->igtk, parse->igtk_len, false);
2031 process_bigtk_subelem(wt, bss, sta, kek, kek_len,
2032 parse->bigtk, parse->bigtk_len, false);
2033 }
2034
2035
process_fte_group_keys_mlo(struct wlantest * wt,struct wlantest_bss * bss,struct wlantest_sta * sta,const u8 * kek,size_t kek_len,struct wpa_ft_ies * parse)2036 static void process_fte_group_keys_mlo(struct wlantest *wt,
2037 struct wlantest_bss *bss,
2038 struct wlantest_sta *sta,
2039 const u8 *kek, size_t kek_len,
2040 struct wpa_ft_ies *parse)
2041 {
2042 int link_id;
2043
2044 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS; link_id++) {
2045 struct wlantest_bss *l_bss;
2046 struct wlantest_sta *l_sta;
2047
2048 if (!(parse->valid_mlo_gtks & BIT(link_id)))
2049 continue;
2050
2051 l_bss = bss_find_mld(wt, bss->mld_mac_addr, link_id);
2052 if (!l_bss) {
2053 wpa_printf(MSG_DEBUG,
2054 "FT: No BSS entry found for AP MLD " MACSTR
2055 " link ID %u",
2056 MAC2STR(bss->mld_mac_addr),link_id);
2057 continue;
2058 }
2059
2060 wpa_printf(MSG_DEBUG,
2061 "Trying to learn group keys for Link ID %u",
2062 link_id);
2063 l_sta = bss == l_bss ? sta : NULL;
2064
2065 process_gtk_subelem(wt, l_bss, l_sta, kek, kek_len,
2066 parse->mlo_gtk[link_id],
2067 parse->mlo_gtk_len[link_id], true);
2068 process_igtk_subelem(wt, l_bss, l_sta, kek, kek_len,
2069 parse->mlo_igtk[link_id],
2070 parse->mlo_igtk_len[link_id], true);
2071 process_bigtk_subelem(wt, l_bss, l_sta, kek, kek_len,
2072 parse->mlo_bigtk[link_id],
2073 parse->mlo_bigtk_len[link_id], true);
2074 }
2075 }
2076
2077
rx_mgmt_reassoc_resp(struct wlantest * wt,const u8 * data,size_t len)2078 static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data,
2079 size_t len)
2080 {
2081 const struct ieee80211_mgmt *mgmt;
2082 struct wlantest_bss *bss;
2083 struct wlantest_sta *sta;
2084 u16 capab, status, aid;
2085 const u8 *ies;
2086 size_t ies_len;
2087 struct ieee802_11_elems elems;
2088 const u8 *ml;
2089
2090 mgmt = (const struct ieee80211_mgmt *) data;
2091 bss = bss_get(wt, mgmt->bssid);
2092 if (bss == NULL)
2093 return;
2094 sta = sta_find_mlo(wt, bss, mgmt->da);
2095 if (!sta)
2096 sta = sta_get(bss, mgmt->da);
2097 if (sta == NULL)
2098 return;
2099
2100 if (len < 24 + 6) {
2101 add_note(wt, MSG_INFO, "Too short Reassociation Response frame "
2102 "from " MACSTR, MAC2STR(mgmt->sa));
2103 return;
2104 }
2105
2106 ies = mgmt->u.reassoc_resp.variable;
2107 ies_len = len - (mgmt->u.reassoc_resp.variable - data);
2108
2109 capab = le_to_host16(mgmt->u.reassoc_resp.capab_info);
2110 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
2111 aid = le_to_host16(mgmt->u.reassoc_resp.aid);
2112
2113 wpa_printf(MSG_DEBUG, "REASSOCRESP " MACSTR " -> " MACSTR
2114 " (capab=0x%x status=%u aid=%u)",
2115 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
2116 aid & 0x3fff);
2117
2118 ml = get_ml_ie(ies, ies_len, MULTI_LINK_CONTROL_TYPE_BASIC);
2119 if (ml &&
2120 ieee802_11_parse_elems(ies, ies_len, &elems, 0) != ParseFailed)
2121 parse_basic_ml_elems(&elems, true, NULL, 4);
2122
2123 if (sta->auth_alg == WLAN_AUTH_FILS_SK) {
2124 const u8 *session, *frame_ad, *frame_ad_end, *encr_end;
2125
2126 session = get_fils_session(ies, ies_len);
2127 if (session) {
2128 frame_ad = (const u8 *)
2129 &mgmt->u.reassoc_resp.capab_info;
2130 frame_ad_end = session + 2 + session[1];
2131 encr_end = data + len;
2132 decrypt_fils_assoc_resp(wt, bss, sta, data, frame_ad,
2133 frame_ad_end, encr_end);
2134 ies_len = session - ies;
2135 }
2136 }
2137
2138 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed) {
2139 add_note(wt, MSG_INFO,
2140 "Failed to parse IEs in ReassocResp from " MACSTR,
2141 MAC2STR(mgmt->sa));
2142 }
2143
2144 if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
2145 if (!elems.timeout_int ||
2146 elems.timeout_int[0] != WLAN_TIMEOUT_ASSOC_COMEBACK) {
2147 add_note(wt, MSG_INFO, "No valid Timeout Interval IE "
2148 "with Assoc Comeback time in ReassocResp "
2149 "(status=30) from " MACSTR,
2150 MAC2STR(mgmt->sa));
2151 } else {
2152 sta->counters[
2153 WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK]++;
2154 }
2155 }
2156
2157 if (status)
2158 return;
2159
2160 if ((aid & 0xc000) != 0xc000) {
2161 add_note(wt, MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
2162 "in Reassociation Response from " MACSTR,
2163 MAC2STR(mgmt->sa));
2164 }
2165 sta->aid = aid & 0xc000;
2166
2167 if (sta->state < STATE2 && !sta->ft_over_ds) {
2168 add_note(wt, MSG_DEBUG,
2169 "STA " MACSTR " was not in State 2 when "
2170 "getting associated", MAC2STR(sta->addr));
2171 }
2172
2173 if (sta->state < STATE3) {
2174 add_note(wt, MSG_DEBUG, "STA " MACSTR
2175 " moved to State 3 with " MACSTR,
2176 MAC2STR(sta->addr), MAC2STR(bss->bssid));
2177 sta->state = STATE3;
2178 }
2179
2180 if (elems.ftie) {
2181 struct wpa_ft_ies parse;
2182 int use_sha384;
2183 struct rsn_mdie *mde;
2184 const u8 *anonce, *snonce, *fte_mic;
2185 u8 fte_elem_count;
2186 unsigned int count;
2187 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
2188 size_t mic_len = 16;
2189 const u8 *kck, *kek;
2190 size_t kck_len, kek_len;
2191 const u8 *aa, *spa;
2192 struct wpabuf *extra = NULL, *rsne = NULL, *rsnxe = NULL;
2193
2194 if (ml) {
2195 aa = bss->mld_mac_addr;
2196 spa = sta->mld_mac_addr;
2197 } else {
2198 aa = bss->bssid;
2199 spa = sta->addr;
2200 }
2201
2202 use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt);
2203
2204 if (wpa_ft_parse_ies(ies, ies_len, &parse, sta->key_mgmt,
2205 true) < 0) {
2206 add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs");
2207 return;
2208 }
2209
2210 if (!parse.rsn) {
2211 add_note(wt, MSG_INFO, "FT: No RSNE in Reassoc Resp");
2212 goto out;
2213 }
2214
2215 if (!parse.rsn_pmkid) {
2216 add_note(wt, MSG_INFO, "FT: No PMKID in RSNE");
2217 goto out;
2218 }
2219
2220 if (os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name,
2221 WPA_PMK_NAME_LEN) != 0) {
2222 add_note(wt, MSG_INFO,
2223 "FT: PMKID in Reassoc Resp did not match PMKR1Name");
2224 wpa_hexdump(MSG_DEBUG,
2225 "FT: Received RSNE[PMKR1Name]",
2226 parse.rsn_pmkid, WPA_PMK_NAME_LEN);
2227 wpa_hexdump(MSG_DEBUG,
2228 "FT: Previously derived PMKR1Name",
2229 sta->pmk_r1_name, WPA_PMK_NAME_LEN);
2230 goto out;
2231 }
2232
2233 mde = (struct rsn_mdie *) parse.mdie;
2234 if (!mde || parse.mdie_len < sizeof(*mde) ||
2235 os_memcmp(mde->mobility_domain, bss->mdid,
2236 MOBILITY_DOMAIN_ID_LEN) != 0) {
2237 add_note(wt, MSG_INFO, "FT: Invalid MDE");
2238 }
2239
2240 if (use_sha384) {
2241 struct rsn_ftie_sha384 *fte;
2242
2243 fte = (struct rsn_ftie_sha384 *) parse.ftie;
2244 if (!fte || parse.ftie_len < sizeof(*fte)) {
2245 add_note(wt, MSG_INFO, "FT: Invalid FTE");
2246 goto out;
2247 }
2248
2249 anonce = fte->anonce;
2250 snonce = fte->snonce;
2251 fte_elem_count = fte->mic_control[1];
2252 fte_mic = fte->mic;
2253 } else {
2254 struct rsn_ftie *fte;
2255
2256 fte = (struct rsn_ftie *) parse.ftie;
2257 if (!fte || parse.ftie_len < sizeof(*fte)) {
2258 add_note(wt, MSG_INFO, "FT: Invalid FTIE");
2259 goto out;
2260 }
2261
2262 anonce = fte->anonce;
2263 snonce = fte->snonce;
2264 fte_elem_count = fte->mic_control[1];
2265 fte_mic = fte->mic;
2266 }
2267
2268 if (os_memcmp(snonce, sta->snonce, WPA_NONCE_LEN) != 0) {
2269 add_note(wt, MSG_INFO, "FT: SNonce mismatch in FTIE");
2270 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
2271 snonce, WPA_NONCE_LEN);
2272 wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
2273 sta->snonce, WPA_NONCE_LEN);
2274 goto out;
2275 }
2276
2277 if (os_memcmp(anonce, sta->anonce, WPA_NONCE_LEN) != 0) {
2278 add_note(wt, MSG_INFO, "FT: ANonce mismatch in FTIE");
2279 wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
2280 anonce, WPA_NONCE_LEN);
2281 wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
2282 sta->anonce, WPA_NONCE_LEN);
2283 goto out;
2284 }
2285
2286 if (!parse.r0kh_id) {
2287 add_note(wt, MSG_INFO, "FT: No R0KH-ID subelem in FTE");
2288 goto out;
2289 }
2290
2291 if (parse.r0kh_id_len != bss->r0kh_id_len ||
2292 os_memcmp_const(parse.r0kh_id, bss->r0kh_id,
2293 parse.r0kh_id_len) != 0) {
2294 add_note(wt, MSG_INFO,
2295 "FT: R0KH-ID in FTE did not match the current R0KH-ID");
2296 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
2297 parse.r0kh_id, parse.r0kh_id_len);
2298 wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
2299 bss->r0kh_id, bss->r0kh_id_len);
2300 os_memcpy(bss->r0kh_id, parse.r0kh_id,
2301 parse.r0kh_id_len);
2302 bss->r0kh_id_len = parse.r0kh_id_len;
2303 }
2304
2305 if (!parse.r1kh_id) {
2306 add_note(wt, MSG_INFO, "FT: No R1KH-ID subelem in FTE");
2307 goto out;
2308 }
2309
2310 if (os_memcmp_const(parse.r1kh_id, bss->r1kh_id,
2311 FT_R1KH_ID_LEN) != 0) {
2312 add_note(wt, MSG_INFO,
2313 "FT: Unknown R1KH-ID used in ReassocResp");
2314 os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
2315 }
2316
2317 count = 2; /* MDE and FTE */
2318 if (ml) {
2319 int link_id;
2320 struct wlantest_bss *l_bss;
2321 u8 rsne_buf[257];
2322 size_t rsne_len;
2323
2324 extra = wpabuf_alloc(MAX_NUM_MLD_LINKS * ETH_ALEN);
2325 rsne = wpabuf_alloc(MAX_NUM_MLD_LINKS * 256);
2326 rsnxe = wpabuf_alloc(MAX_NUM_MLD_LINKS * 256);
2327 if (!extra || !rsne || !rsnxe)
2328 goto out;
2329
2330 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS;
2331 link_id++) {
2332 struct wpa_ie_data ie_data;
2333
2334 if (is_zero_ether_addr(sta->link_addr[link_id]))
2335 continue;
2336
2337 l_bss = bss_find_mld(wt, bss->mld_mac_addr,
2338 link_id);
2339 if (!l_bss) {
2340 wpa_printf(MSG_DEBUG,
2341 "FT: No BSS entry found for AP MLD "
2342 MACSTR " link ID %u",
2343 MAC2STR(bss->mld_mac_addr),
2344 link_id);
2345 continue;
2346 }
2347
2348 /* Insert PMKID=PMKR1Name into each RSNE */
2349 rsne_len = 2 + l_bss->rsnie[1];
2350 if (wpa_parse_wpa_ie_rsn(l_bss->rsnie,
2351 rsne_len, &ie_data) <
2352 0 ||
2353 rsne_len > 200) {
2354 wpa_printf(MSG_DEBUG,
2355 "FT: Could not parse AP RSNE (or too long element) for link ID %u ",
2356 link_id);
2357 continue;
2358 }
2359
2360 os_memcpy(rsne_buf, l_bss->rsnie, rsne_len);
2361 if (wpa_insert_pmkid(rsne_buf, &rsne_len,
2362 sta->pmk_r1_name,
2363 true) < 0) {
2364 wpa_printf(MSG_DEBUG,
2365 "FT: Could not insert PMKR1Name into AP RSNE for link ID %u ",
2366 link_id);
2367 continue;
2368 }
2369
2370 count++; /* RSNE */
2371 wpabuf_put_data(rsne, rsne_buf, rsne_len);
2372
2373 if (l_bss->rsnxe_len) {
2374 count++;
2375 wpabuf_put_u8(rsnxe, WLAN_EID_RSNX);
2376 wpabuf_put_u8(rsnxe, l_bss->rsnxe_len);
2377 wpabuf_put_data(rsnxe,
2378 l_bss->rsnxe,
2379 l_bss->rsnxe_len);
2380 }
2381
2382 wpabuf_put_data(extra, l_bss->bssid, ETH_ALEN);
2383 }
2384 } else {
2385 count++; /* RSNE */
2386 rsne = wpabuf_alloc_copy(parse.rsn - 2,
2387 parse.rsn_len + 2);
2388 if (!rsne)
2389 goto out;
2390 if (parse.rsnxe) {
2391 count++;
2392 rsnxe = wpabuf_alloc_copy(parse.rsnxe - 2,
2393 parse.rsnxe_len + 2);
2394 if (!rsnxe)
2395 goto out;
2396 }
2397 }
2398 if (parse.ric)
2399 count += ieee802_11_ie_count(parse.ric, parse.ric_len);
2400 if (fte_elem_count != count) {
2401 add_note(wt, MSG_INFO,
2402 "FT: Unexpected IE count in MIC Control: received %u expected %u",
2403 fte_elem_count, count);
2404 goto out;
2405 }
2406
2407 if (wpa_key_mgmt_fils(sta->key_mgmt)) {
2408 kck = sta->ptk.kck2;
2409 kck_len = sta->ptk.kck2_len;
2410 kek = sta->ptk.kek2;
2411 kek_len = sta->ptk.kek2_len;
2412 } else {
2413 kck = sta->ptk.kck;
2414 kck_len = sta->ptk.kck_len;
2415 kek = sta->ptk.kek;
2416 kek_len = sta->ptk.kek_len;
2417 }
2418
2419 /* FTE might be fragmented. If it is, the separate Fragment
2420 * elements are included in MIC calculation as full elements. */
2421 if (wpa_ft_mic(sta->key_mgmt, kck, kck_len,
2422 spa, aa, 6,
2423 parse.mdie - 2, parse.mdie_len + 2,
2424 elems.ftie - 2, elems.fte_defrag_len + 2,
2425 wpabuf_head(rsne), wpabuf_len(rsne),
2426 parse.ric, parse.ric_len,
2427 rsnxe ? wpabuf_head(rsnxe) : NULL,
2428 rsnxe ? wpabuf_len(rsnxe) : 0,
2429 extra,
2430 mic) < 0) {
2431 add_note(wt, MSG_INFO, "FT: Failed to calculate MIC");
2432 goto out;
2433 }
2434
2435 if (os_memcmp_const(mic, fte_mic, mic_len) != 0) {
2436 int link_id;
2437
2438 add_note(wt, MSG_INFO, "FT: Invalid MIC in FTE");
2439 wpa_printf(MSG_DEBUG,
2440 "FT: addr=" MACSTR " auth_addr=" MACSTR,
2441 MAC2STR(spa), MAC2STR(aa));
2442 wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC",
2443 fte_mic, mic_len);
2444 wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC",
2445 mic, mic_len);
2446 wpa_hexdump(MSG_MSGDUMP, "FT: MDE",
2447 parse.mdie - 2, parse.mdie_len + 2);
2448 wpa_hexdump(MSG_MSGDUMP, "FT: FTE",
2449 elems.ftie - 2, elems.fte_defrag_len + 2);
2450 wpa_hexdump_buf(MSG_MSGDUMP, "FT: RSNE", rsne);
2451 wpa_hexdump_buf(MSG_MSGDUMP, "FT: RSNXE", rsnxe);
2452 for (link_id = 0; link_id < MAX_NUM_MLD_LINKS;
2453 link_id++) {
2454 struct wlantest_bss *l_bss;
2455
2456 if (is_zero_ether_addr(sta->link_addr[link_id]))
2457 continue;
2458 l_bss = bss_find_mld(wt, bss->mld_mac_addr,
2459 link_id);
2460 if (l_bss)
2461 wpa_printf(MSG_DEBUG,
2462 "FT: AP link %d address: "
2463 MACSTR, link_id,
2464 MAC2STR(l_bss->bssid));
2465 }
2466 goto out;
2467 }
2468
2469 add_note(wt, MSG_INFO, "FT: Valid FTE MIC");
2470
2471 if (wpa_compare_rsn_ie(wpa_key_mgmt_ft(sta->key_mgmt),
2472 bss->rsnie, 2 + bss->rsnie[1],
2473 parse.rsn - 2, parse.rsn_len + 2)) {
2474 add_note(wt, MSG_INFO,
2475 "FT: RSNE mismatch between Beacon/ProbeResp and FT protocol Reassociation Response frame");
2476 wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp",
2477 &bss->rsnie[2], bss->rsnie[1]);
2478 wpa_hexdump(MSG_INFO,
2479 "RSNE in FT protocol Reassociation Response frame",
2480 parse.rsn ? parse.rsn - 2 : NULL,
2481 parse.rsn ? parse.rsn_len + 2 : 0);
2482 }
2483
2484 if (ml)
2485 process_fte_group_keys_mlo(wt, bss, sta, kek, kek_len,
2486 &parse);
2487 else
2488 process_fte_group_keys(wt, bss, sta, kek, kek_len,
2489 &parse);
2490
2491 out:
2492 wpa_ft_parse_ies_free(&parse);
2493 wpabuf_free(rsne);
2494 wpabuf_free(rsnxe);
2495 wpabuf_free(extra);
2496 }
2497
2498 if (elems.owe_dh && elems.owe_dh_len >= 2) {
2499 sta->owe_group = WPA_GET_LE16(elems.owe_dh);
2500 wpa_printf(MSG_DEBUG, "OWE using group %u", sta->owe_group);
2501 }
2502 }
2503
2504
disassoc_all_stas(struct wlantest * wt,struct wlantest_bss * bss)2505 static void disassoc_all_stas(struct wlantest *wt, struct wlantest_bss *bss)
2506 {
2507 struct wlantest_sta *sta;
2508 dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) {
2509 if (sta->state <= STATE2)
2510 continue;
2511 add_note(wt, MSG_DEBUG, "STA " MACSTR
2512 " moved to State 2 with " MACSTR,
2513 MAC2STR(sta->addr), MAC2STR(bss->bssid));
2514 sta->state = STATE2;
2515 }
2516 }
2517
2518
rx_mgmt_disassoc(struct wlantest * wt,const u8 * data,size_t len,int valid)2519 static void rx_mgmt_disassoc(struct wlantest *wt, const u8 *data, size_t len,
2520 int valid)
2521 {
2522 const struct ieee80211_mgmt *mgmt;
2523 struct wlantest_bss *bss;
2524 struct wlantest_sta *sta;
2525 u16 fc, reason;
2526
2527 mgmt = (const struct ieee80211_mgmt *) data;
2528 bss = bss_get(wt, mgmt->bssid);
2529 if (bss == NULL)
2530 return;
2531 if (ether_addr_equal(mgmt->sa, mgmt->bssid))
2532 sta = sta_get(bss, mgmt->da);
2533 else
2534 sta = sta_get(bss, mgmt->sa);
2535
2536 if (len < 24 + 2) {
2537 add_note(wt, MSG_INFO, "Too short Disassociation frame from "
2538 MACSTR, MAC2STR(mgmt->sa));
2539 return;
2540 }
2541
2542 reason = le_to_host16(mgmt->u.disassoc.reason_code);
2543 wpa_printf(MSG_DEBUG, "DISASSOC " MACSTR " -> " MACSTR
2544 " (reason=%u) (valid=%d)",
2545 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
2546 reason, valid);
2547 wpa_hexdump(MSG_MSGDUMP, "DISASSOC payload", data + 24, len - 24);
2548
2549 if (sta == NULL) {
2550 if (valid && mgmt->da[0] == 0xff)
2551 disassoc_all_stas(wt, bss);
2552 return;
2553 }
2554
2555 if (ether_addr_equal(mgmt->sa, mgmt->bssid)) {
2556 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_RX :
2557 WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX]++;
2558 if (sta->pwrmgt && !sta->pspoll)
2559 sta->counters[
2560 WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP]++;
2561 else
2562 sta->counters[
2563 WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE]++;
2564
2565 fc = le_to_host16(mgmt->frame_control);
2566 if (!(fc & WLAN_FC_ISWEP) && reason == 6)
2567 sta->counters[WLANTEST_STA_COUNTER_DISASSOC_RX_RC6]++;
2568 else if (!(fc & WLAN_FC_ISWEP) && reason == 7)
2569 sta->counters[WLANTEST_STA_COUNTER_DISASSOC_RX_RC7]++;
2570 } else
2571 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_TX :
2572 WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX]++;
2573
2574 if (!valid) {
2575 add_note(wt, MSG_INFO, "Do not change STA " MACSTR " State "
2576 "since Disassociation frame was not protected "
2577 "correctly", MAC2STR(sta->addr));
2578 return;
2579 }
2580
2581 if (sta->state < STATE2) {
2582 add_note(wt, MSG_DEBUG,
2583 "STA " MACSTR " was not in State 2 or 3 "
2584 "when getting disassociated", MAC2STR(sta->addr));
2585 }
2586
2587 if (sta->state > STATE2) {
2588 add_note(wt, MSG_DEBUG, "STA " MACSTR
2589 " moved to State 2 with " MACSTR,
2590 MAC2STR(sta->addr), MAC2STR(bss->bssid));
2591 sta->state = STATE2;
2592 }
2593 tdls_link_down(wt, bss, sta);
2594 }
2595
2596
rx_mgmt_action_ft_request(struct wlantest * wt,const struct ieee80211_mgmt * mgmt,size_t len)2597 static void rx_mgmt_action_ft_request(struct wlantest *wt,
2598 const struct ieee80211_mgmt *mgmt,
2599 size_t len)
2600 {
2601 const u8 *ies;
2602 size_t ies_len;
2603 struct wpa_ft_ies parse;
2604 const u8 *spa, *aa;
2605 struct wlantest_bss *bss, *bss2;
2606 struct wlantest_sta *sta;
2607
2608 if (len < 24 + 2 + 2 * ETH_ALEN) {
2609 add_note(wt, MSG_INFO, "Too short FT Request frame");
2610 return;
2611 }
2612
2613 spa = mgmt->u.action.u.ft_action_resp.sta_addr;
2614 aa = mgmt->u.action.u.ft_action_resp.target_ap_addr;
2615 wpa_printf(MSG_DEBUG, "FT Request: STA Address: " MACSTR
2616 " Target AP Address: " MACSTR,
2617 MAC2STR(spa), MAC2STR(aa));
2618 ies = mgmt->u.action.u.ft_action_req.variable;
2619 ies_len = len - (24 + 2 + 2 * ETH_ALEN);
2620 wpa_hexdump(MSG_DEBUG, "FT Request frame body", ies, ies_len);
2621
2622 if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, false)) {
2623 add_note(wt, MSG_INFO, "Could not parse FT Request frame body");
2624 return;
2625 }
2626
2627 bss = bss_find(wt, aa);
2628 bss2 = bss_find_mld(wt, aa, -1);
2629 if (!bss)
2630 bss = bss2;
2631 if (bss && bss2 && bss != bss2 && !sta_find(bss, spa))
2632 bss = bss2;
2633 if (!bss)
2634 bss = bss_get(wt, aa);
2635 if (!bss) {
2636 add_note(wt, MSG_INFO, "No BSS entry for Target AP");
2637 goto out;
2638 }
2639
2640 sta = sta_find_mlo(wt, bss, spa);
2641 if (!sta)
2642 sta = sta_get(bss, spa);
2643 if (!sta)
2644 goto out;
2645
2646 sta->ft_over_ds = true;
2647 sta->key_mgmt = parse.key_mgmt;
2648 sta->pairwise_cipher = parse.pairwise_cipher;
2649 out:
2650 wpa_ft_parse_ies_free(&parse);
2651 }
2652
2653
rx_mgmt_action_ft_response(struct wlantest * wt,struct wlantest_sta * sta,const struct ieee80211_mgmt * mgmt,size_t len)2654 static void rx_mgmt_action_ft_response(struct wlantest *wt,
2655 struct wlantest_sta *sta,
2656 const struct ieee80211_mgmt *mgmt,
2657 size_t len)
2658 {
2659 struct wlantest_bss *bss, *bss2;
2660 struct wlantest_sta *new_sta;
2661 const u8 *spa, *aa;
2662 const u8 *ies;
2663 size_t ies_len;
2664 struct wpa_ft_ies parse;
2665 struct wpa_ptk ptk;
2666 u8 ptk_name[WPA_PMK_NAME_LEN];
2667 const u8 *rsnxe;
2668 size_t rsnxe_len;
2669
2670 if (len < 24 + 2 + 2 * ETH_ALEN + 2) {
2671 add_note(wt, MSG_INFO, "Too short FT Response frame from "
2672 MACSTR, MAC2STR(mgmt->sa));
2673 return;
2674 }
2675
2676 spa = mgmt->u.action.u.ft_action_resp.sta_addr;
2677 aa = mgmt->u.action.u.ft_action_resp.target_ap_addr;
2678 wpa_printf(MSG_DEBUG, "FT Response: STA Address: " MACSTR
2679 " Target AP Address: " MACSTR " Status Code: %u",
2680 MAC2STR(spa), MAC2STR(aa),
2681 le_to_host16(mgmt->u.action.u.ft_action_resp.status_code));
2682 ies = mgmt->u.action.u.ft_action_req.variable;
2683 ies_len = len - (24 + 2 + 2 * ETH_ALEN);
2684 wpa_hexdump(MSG_DEBUG, "FT Response frame body", ies, ies_len);
2685
2686 if (wpa_ft_parse_ies(ies, ies_len, &parse, 0, false)) {
2687 add_note(wt, MSG_INFO,
2688 "Could not parse FT Response frame body");
2689 return;
2690 }
2691
2692 bss = bss_find(wt, aa);
2693 bss2 = bss_find_mld(wt, aa, -1);
2694 if (!bss)
2695 bss = bss2;
2696 if (bss && bss2 && bss != bss2 && !sta_find(bss, spa))
2697 bss = bss2;
2698 if (!bss)
2699 bss = bss_get(wt, aa);
2700
2701 if (!bss) {
2702 add_note(wt, MSG_INFO, "No BSS entry for Target AP");
2703 goto out;
2704 }
2705
2706 if (parse.r1kh_id)
2707 os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
2708
2709 if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name,
2710 bss->r1kh_id, spa, sta->pmk_r1,
2711 sta->pmk_r1_name) < 0)
2712 goto out;
2713 sta->pmk_r1_len = sta->pmk_r0_len;
2714
2715 new_sta = sta_find_mlo(wt, bss, spa);
2716 if (!new_sta)
2717 new_sta = sta_get(bss, spa);
2718 if (!new_sta)
2719 goto out;
2720 os_memcpy(new_sta->pmk_r0, sta->pmk_r0, sta->pmk_r0_len);
2721 new_sta->pmk_r0_len = sta->pmk_r0_len;
2722 os_memcpy(new_sta->pmk_r0_name, sta->pmk_r0_name,
2723 sizeof(sta->pmk_r0_name));
2724 os_memcpy(new_sta->pmk_r1, sta->pmk_r1, sta->pmk_r1_len);
2725 new_sta->pmk_r1_len = sta->pmk_r1_len;
2726 os_memcpy(new_sta->pmk_r1_name, sta->pmk_r1_name,
2727 sizeof(sta->pmk_r1_name));
2728
2729 if ((sta->rsn_selection == RSN_SELECTION_RSNE_OVERRIDE ||
2730 sta->rsn_selection == RSN_SELECTION_RSNE_OVERRIDE_2) &&
2731 bss->rsnxoe_len) {
2732 rsnxe = bss->rsnxoe;
2733 rsnxe_len = bss->rsnxoe_len;
2734 } else {
2735 rsnxe = bss->rsnxe;
2736 rsnxe_len = bss->rsnxe_len;
2737 }
2738
2739 if (!parse.fte_anonce || !parse.fte_snonce ||
2740 wpa_pmk_r1_to_ptk(sta->pmk_r1, sta->pmk_r1_len, parse.fte_snonce,
2741 parse.fte_anonce, spa, aa,
2742 sta->pmk_r1_name, &ptk, ptk_name,
2743 new_sta->key_mgmt, new_sta->pairwise_cipher,
2744 0) < 0)
2745 goto out;
2746
2747 sta_new_ptk(wt, new_sta, &ptk);
2748 os_memcpy(new_sta->snonce, parse.fte_snonce, WPA_NONCE_LEN);
2749 os_memcpy(new_sta->anonce, parse.fte_anonce, WPA_NONCE_LEN);
2750 out:
2751 wpa_ft_parse_ies_free(&parse);
2752 }
2753
2754
rx_mgmt_action_ft(struct wlantest * wt,struct wlantest_sta * sta,const struct ieee80211_mgmt * mgmt,size_t len,int valid)2755 static void rx_mgmt_action_ft(struct wlantest *wt, struct wlantest_sta *sta,
2756 const struct ieee80211_mgmt *mgmt,
2757 size_t len, int valid)
2758 {
2759 if (len < 24 + 2) {
2760 add_note(wt, MSG_INFO, "Too short FT Action frame from " MACSTR,
2761 MAC2STR(mgmt->sa));
2762 return;
2763 }
2764
2765 switch (mgmt->u.action.u.ft_action_req.action) {
2766 case 1:
2767 rx_mgmt_action_ft_request(wt, mgmt, len);
2768 break;
2769 case 2:
2770 rx_mgmt_action_ft_response(wt, sta, mgmt, len);
2771 break;
2772 default:
2773 add_note(wt, MSG_INFO, "Unsupported FT action value %u from "
2774 MACSTR, mgmt->u.action.u.ft_action_req.action,
2775 MAC2STR(mgmt->sa));
2776 }
2777 }
2778
2779
rx_mgmt_action_sa_query_req(struct wlantest * wt,struct wlantest_sta * sta,const struct ieee80211_mgmt * mgmt,size_t len,int valid)2780 static void rx_mgmt_action_sa_query_req(struct wlantest *wt,
2781 struct wlantest_sta *sta,
2782 const struct ieee80211_mgmt *mgmt,
2783 size_t len, int valid)
2784 {
2785 const u8 *rx_id;
2786 u8 *id;
2787
2788 rx_id = (const u8 *) mgmt->u.action.u.sa_query_req.trans_id;
2789 if (ether_addr_equal(mgmt->sa, mgmt->bssid))
2790 id = sta->ap_sa_query_tr;
2791 else
2792 id = sta->sta_sa_query_tr;
2793 add_note(wt, MSG_INFO, "SA Query Request " MACSTR " -> " MACSTR
2794 " (trans_id=%02x%02x)%s",
2795 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1],
2796 valid ? "" : " (invalid protection)");
2797 os_memcpy(id, mgmt->u.action.u.sa_query_req.trans_id, 2);
2798 if (ether_addr_equal(mgmt->sa, sta->addr))
2799 sta->counters[valid ?
2800 WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX :
2801 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX]++;
2802 else
2803 sta->counters[valid ?
2804 WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX :
2805 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX]++;
2806 }
2807
2808
rx_mgmt_action_sa_query_resp(struct wlantest * wt,struct wlantest_sta * sta,const struct ieee80211_mgmt * mgmt,size_t len,int valid)2809 static void rx_mgmt_action_sa_query_resp(struct wlantest *wt,
2810 struct wlantest_sta *sta,
2811 const struct ieee80211_mgmt *mgmt,
2812 size_t len, int valid)
2813 {
2814 const u8 *rx_id;
2815 u8 *id;
2816 int match;
2817
2818 rx_id = (const u8 *) mgmt->u.action.u.sa_query_resp.trans_id;
2819 if (ether_addr_equal(mgmt->sa, mgmt->bssid))
2820 id = sta->sta_sa_query_tr;
2821 else
2822 id = sta->ap_sa_query_tr;
2823 match = os_memcmp(rx_id, id, 2) == 0;
2824 add_note(wt, MSG_INFO, "SA Query Response " MACSTR " -> " MACSTR
2825 " (trans_id=%02x%02x; %s)%s",
2826 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1],
2827 match ? "match" : "mismatch",
2828 valid ? "" : " (invalid protection)");
2829 if (ether_addr_equal(mgmt->sa, sta->addr))
2830 sta->counters[(valid && match) ?
2831 WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX :
2832 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX]++;
2833 else
2834 sta->counters[(valid && match) ?
2835 WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX :
2836 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX]++;
2837 }
2838
2839
rx_mgmt_action_sa_query(struct wlantest * wt,struct wlantest_sta * sta,const struct ieee80211_mgmt * mgmt,size_t len,int valid)2840 static void rx_mgmt_action_sa_query(struct wlantest *wt,
2841 struct wlantest_sta *sta,
2842 const struct ieee80211_mgmt *mgmt,
2843 size_t len, int valid)
2844 {
2845 if (len < 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) {
2846 add_note(wt, MSG_INFO, "Too short SA Query frame from " MACSTR,
2847 MAC2STR(mgmt->sa));
2848 return;
2849 }
2850
2851 if (len > 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) {
2852 size_t elen = len - (24 + 2 + WLAN_SA_QUERY_TR_ID_LEN);
2853 add_note(wt, MSG_INFO, "Unexpected %u octets of extra data at "
2854 "the end of SA Query frame from " MACSTR,
2855 (unsigned) elen, MAC2STR(mgmt->sa));
2856 wpa_hexdump(MSG_INFO, "SA Query extra data",
2857 ((const u8 *) mgmt) + len - elen, elen);
2858 }
2859
2860 switch (mgmt->u.action.u.sa_query_req.action) {
2861 case WLAN_SA_QUERY_REQUEST:
2862 rx_mgmt_action_sa_query_req(wt, sta, mgmt, len, valid);
2863 break;
2864 case WLAN_SA_QUERY_RESPONSE:
2865 rx_mgmt_action_sa_query_resp(wt, sta, mgmt, len, valid);
2866 break;
2867 default:
2868 add_note(wt, MSG_INFO, "Unexpected SA Query action value %u "
2869 "from " MACSTR,
2870 mgmt->u.action.u.sa_query_req.action,
2871 MAC2STR(mgmt->sa));
2872 }
2873 }
2874
2875
2876 static void
rx_mgmt_location_measurement_report(struct wlantest * wt,const struct ieee80211_mgmt * mgmt,size_t len,bool no_ack)2877 rx_mgmt_location_measurement_report(struct wlantest *wt,
2878 const struct ieee80211_mgmt *mgmt,
2879 size_t len, bool no_ack)
2880 {
2881 const u8 *pos = mgmt->u.action.u.public_action.variable;
2882 const u8 *end = ((const u8 *) mgmt) + len;
2883
2884 if (end - pos < 1) {
2885 add_note(wt, MSG_INFO,
2886 "Too short Location Measurement Report frame from "
2887 MACSTR, MAC2STR(mgmt->sa));
2888 return;
2889 }
2890
2891 wpa_printf(MSG_DEBUG, "Location Measurement Report " MACSTR " --> "
2892 MACSTR " (dialog token %u)",
2893 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), *pos);
2894 pos++;
2895
2896 if (!no_ack)
2897 add_note(wt, MSG_INFO,
2898 "Protected Fine Timing Measurement Report incorrectly as an Action frame from "
2899 MACSTR, MAC2STR(mgmt->sa));
2900
2901 wpa_hexdump(MSG_MSGDUMP, "Location Measurement Report contents",
2902 pos, end - pos);
2903 }
2904
2905
rx_mgmt_action_no_bss_public(struct wlantest * wt,const struct ieee80211_mgmt * mgmt,size_t len,bool no_ack)2906 static void rx_mgmt_action_no_bss_public(struct wlantest *wt,
2907 const struct ieee80211_mgmt *mgmt,
2908 size_t len, bool no_ack)
2909 {
2910 switch (mgmt->u.action.u.public_action.action) {
2911 case WLAN_PA_LOCATION_MEASUREMENT_REPORT:
2912 rx_mgmt_location_measurement_report(wt, mgmt, len, no_ack);
2913 break;
2914 }
2915 }
2916
2917
rx_mgmt_prot_ftm_request(struct wlantest * wt,const struct ieee80211_mgmt * mgmt,size_t len,bool no_ack)2918 static void rx_mgmt_prot_ftm_request(struct wlantest *wt,
2919 const struct ieee80211_mgmt *mgmt,
2920 size_t len, bool no_ack)
2921 {
2922 wpa_printf(MSG_DEBUG, "Protected Fine Timing Measurement Request "
2923 MACSTR " --> " MACSTR,
2924 MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
2925 if (no_ack)
2926 add_note(wt, MSG_INFO,
2927 "Protected Fine Timing Measurement Request incorrectly as an Action No Ack frame from "
2928 MACSTR, MAC2STR(mgmt->sa));
2929 }
2930
2931
rx_mgmt_prot_ftm(struct wlantest * wt,const struct ieee80211_mgmt * mgmt,size_t len,bool no_ack)2932 static void rx_mgmt_prot_ftm(struct wlantest *wt,
2933 const struct ieee80211_mgmt *mgmt,
2934 size_t len, bool no_ack)
2935 {
2936 wpa_printf(MSG_DEBUG, "Protected Fine Timing Measurement "
2937 MACSTR " --> " MACSTR,
2938 MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
2939 if (no_ack)
2940 add_note(wt, MSG_INFO,
2941 "Protected Fine Timing Measurement incorrectly as an Action No Ack frame from "
2942 MACSTR, MAC2STR(mgmt->sa));
2943 }
2944
2945
rx_mgmt_prot_ftm_report(struct wlantest * wt,const struct ieee80211_mgmt * mgmt,size_t len,bool no_ack)2946 static void rx_mgmt_prot_ftm_report(struct wlantest *wt,
2947 const struct ieee80211_mgmt *mgmt,
2948 size_t len, bool no_ack)
2949 {
2950 wpa_printf(MSG_DEBUG, "Protected Fine Timing Measurement Report "
2951 MACSTR " --> " MACSTR,
2952 MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
2953 if (!no_ack)
2954 add_note(wt, MSG_INFO,
2955 "Protected Fine Timing Measurement Report incorrectly as an Action frame from "
2956 MACSTR, MAC2STR(mgmt->sa));
2957 }
2958
2959
2960 static void
rx_mgmt_action_no_bss_protected_ftm(struct wlantest * wt,const struct ieee80211_mgmt * mgmt,size_t len,bool no_ack)2961 rx_mgmt_action_no_bss_protected_ftm(struct wlantest *wt,
2962 const struct ieee80211_mgmt *mgmt,
2963 size_t len, bool no_ack)
2964 {
2965 switch (mgmt->u.action.u.public_action.action) {
2966 case WLAN_PROT_FTM_REQUEST:
2967 rx_mgmt_prot_ftm_request(wt, mgmt, len, no_ack);
2968 break;
2969 case WLAN_PROT_FTM:
2970 rx_mgmt_prot_ftm(wt, mgmt, len, no_ack);
2971 break;
2972 case WLAN_PROT_FTM_REPORT:
2973 rx_mgmt_prot_ftm_report(wt, mgmt, len, no_ack);
2974 break;
2975 }
2976 }
2977
2978
rx_mgmt_action_no_bss(struct wlantest * wt,const struct ieee80211_mgmt * mgmt,size_t len,bool no_ack)2979 static void rx_mgmt_action_no_bss(struct wlantest *wt,
2980 const struct ieee80211_mgmt *mgmt, size_t len,
2981 bool no_ack)
2982 {
2983 switch (mgmt->u.action.category) {
2984 case WLAN_ACTION_PUBLIC:
2985 rx_mgmt_action_no_bss_public(wt, mgmt, len, no_ack);
2986 break;
2987 case WLAN_ACTION_PROTECTED_FTM:
2988 rx_mgmt_action_no_bss_protected_ftm(wt, mgmt, len, no_ack);
2989 break;
2990 }
2991 }
2992
2993
rx_mgmt_action(struct wlantest * wt,const u8 * data,size_t len,int valid,bool no_ack)2994 static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len,
2995 int valid, bool no_ack)
2996 {
2997 const struct ieee80211_mgmt *mgmt;
2998 struct wlantest_bss *bss;
2999 struct wlantest_sta *sta;
3000
3001 mgmt = (const struct ieee80211_mgmt *) data;
3002 if (mgmt->da[0] & 0x01) {
3003 add_note(wt, MSG_DEBUG, "Group addressed Action frame: DA="
3004 MACSTR " SA=" MACSTR " BSSID=" MACSTR
3005 " category=%u",
3006 MAC2STR(mgmt->da), MAC2STR(mgmt->sa),
3007 MAC2STR(mgmt->bssid), mgmt->u.action.category);
3008 return; /* Ignore group addressed Action frames for now */
3009 }
3010
3011 if (len < 24 + 2) {
3012 add_note(wt, MSG_INFO, "Too short Action frame from " MACSTR,
3013 MAC2STR(mgmt->sa));
3014 return;
3015 }
3016
3017 wpa_printf(MSG_DEBUG, "ACTION%s " MACSTR " -> " MACSTR
3018 " BSSID=" MACSTR " (category=%u) (valid=%d)",
3019 no_ack ? "-NO-ACK" : "",
3020 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), MAC2STR(mgmt->bssid),
3021 mgmt->u.action.category, valid);
3022 wpa_hexdump(MSG_MSGDUMP, "ACTION payload", data + 24, len - 24);
3023
3024 if (is_broadcast_ether_addr(mgmt->bssid)) {
3025 rx_mgmt_action_no_bss(wt, mgmt, len, no_ack);
3026 return;
3027 }
3028 bss = bss_get(wt, mgmt->bssid);
3029 if (bss == NULL)
3030 return;
3031 if (ether_addr_equal(mgmt->sa, mgmt->bssid)) {
3032 sta = sta_find_mlo(wt, bss, mgmt->da);
3033 if (!sta)
3034 sta = sta_get(bss, mgmt->da);
3035 } else {
3036 sta = sta_find_mlo(wt, bss, mgmt->sa);
3037 if (!sta)
3038 sta = sta_get(bss, mgmt->sa);
3039 }
3040 if (sta == NULL)
3041 return;
3042
3043 if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
3044 sta->state < STATE3) {
3045 add_note(wt, MSG_INFO, "Action frame sent when STA is not in "
3046 "State 3 (SA=" MACSTR " DATA=" MACSTR ")",
3047 MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
3048 }
3049
3050 switch (mgmt->u.action.category) {
3051 case WLAN_ACTION_FT:
3052 rx_mgmt_action_ft(wt, sta, mgmt, len, valid);
3053 break;
3054 case WLAN_ACTION_SA_QUERY:
3055 rx_mgmt_action_sa_query(wt, sta, mgmt, len, valid);
3056 break;
3057 }
3058 }
3059
3060
check_mmie_mic(unsigned int mgmt_group_cipher,const u8 * igtk,size_t igtk_len,const u8 * data,size_t len)3061 static int check_mmie_mic(unsigned int mgmt_group_cipher,
3062 const u8 *igtk, size_t igtk_len,
3063 const u8 *data, size_t len)
3064 {
3065 u8 *buf;
3066 u8 mic[16];
3067 u16 fc;
3068 const struct ieee80211_hdr *hdr;
3069 int ret, mic_len;
3070
3071 if (!mgmt_group_cipher || igtk_len < 16)
3072 return -1;
3073 mic_len = mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC ? 8 : 16;
3074
3075 if (len < 24 || len - 24 < mic_len)
3076 return -1;
3077
3078 buf = os_malloc(len + 20 - 24);
3079 if (buf == NULL)
3080 return -1;
3081
3082 /* BIP AAD: FC(masked) A1 A2 A3 */
3083 hdr = (const struct ieee80211_hdr *) data;
3084 fc = le_to_host16(hdr->frame_control);
3085 fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA);
3086 WPA_PUT_LE16(buf, fc);
3087 os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN);
3088
3089 /* Frame body with MMIE MIC masked to zero */
3090 os_memcpy(buf + 20, data + 24, len - 24 - mic_len);
3091 os_memset(buf + 20 + len - 24 - mic_len, 0, mic_len);
3092
3093 if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) {
3094 /* Timestamp field masked to zero */
3095 os_memset(buf + 20, 0, 8);
3096 }
3097
3098 wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, len + 20 - 24);
3099 /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */
3100 if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
3101 ret = omac1_aes_128(igtk, buf, len + 20 - 24, mic);
3102 } else if (mgmt_group_cipher == WPA_CIPHER_BIP_CMAC_256) {
3103 ret = omac1_aes_256(igtk, buf, len + 20 - 24, mic);
3104 } else if (mgmt_group_cipher == WPA_CIPHER_BIP_GMAC_128 ||
3105 mgmt_group_cipher == WPA_CIPHER_BIP_GMAC_256) {
3106 u8 nonce[12], *npos;
3107 const u8 *ipn;
3108
3109 ipn = data + len - mic_len - 6;
3110
3111 /* Nonce: A2 | IPN */
3112 os_memcpy(nonce, hdr->addr2, ETH_ALEN);
3113 npos = nonce + ETH_ALEN;
3114 *npos++ = ipn[5];
3115 *npos++ = ipn[4];
3116 *npos++ = ipn[3];
3117 *npos++ = ipn[2];
3118 *npos++ = ipn[1];
3119 *npos++ = ipn[0];
3120
3121 ret = aes_gmac(igtk, igtk_len, nonce, sizeof(nonce),
3122 buf, len + 20 - 24, mic);
3123 } else {
3124 ret = -1;
3125 }
3126 if (ret < 0) {
3127 os_free(buf);
3128 return -1;
3129 }
3130
3131 os_free(buf);
3132
3133 if (os_memcmp(data + len - mic_len, mic, mic_len) != 0)
3134 return -1;
3135
3136 return 0;
3137 }
3138
3139
check_bip(struct wlantest * wt,const u8 * data,size_t len)3140 static int check_bip(struct wlantest *wt, const u8 *data, size_t len)
3141 {
3142 const struct ieee80211_mgmt *mgmt;
3143 u16 fc, stype;
3144 const u8 *mmie;
3145 u16 keyid;
3146 struct wlantest_bss *bss;
3147 size_t mic_len;
3148
3149 mgmt = (const struct ieee80211_mgmt *) data;
3150 fc = le_to_host16(mgmt->frame_control);
3151 stype = WLAN_FC_GET_STYPE(fc);
3152
3153 if (stype == WLAN_FC_STYPE_ACTION ||
3154 stype == WLAN_FC_STYPE_ACTION_NO_ACK) {
3155 if (len < 24 + 1)
3156 return 0;
3157 if (mgmt->u.action.category == WLAN_ACTION_PUBLIC)
3158 return 0; /* Not a robust management frame */
3159 }
3160
3161 bss = bss_get(wt, mgmt->bssid);
3162 if (bss == NULL)
3163 return 0; /* No key known yet */
3164
3165 mic_len = bss->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC ? 8 : 16;
3166
3167 if (len < 24 + 10 + mic_len ||
3168 data[len - (10 + mic_len)] != WLAN_EID_MMIE ||
3169 data[len - (10 + mic_len - 1)] != 8 + mic_len) {
3170 /* No MMIE */
3171 if (bss->rsn_capab & WPA_CAPABILITY_MFPC) {
3172 add_note(wt, MSG_INFO, "Robust group-addressed "
3173 "management frame sent without BIP by "
3174 MACSTR, MAC2STR(mgmt->sa));
3175 bss->counters[WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE]++;
3176 return -1;
3177 }
3178 return 0;
3179 }
3180
3181 mmie = data + len - (8 + mic_len);
3182 keyid = WPA_GET_LE16(mmie);
3183 if (keyid & 0xf000) {
3184 add_note(wt, MSG_INFO, "MMIE KeyID reserved bits not zero "
3185 "(%04x) from " MACSTR, keyid, MAC2STR(mgmt->sa));
3186 keyid &= 0x0fff;
3187 }
3188 if (keyid < 4 || keyid > 5) {
3189 add_note(wt, MSG_INFO, "Unexpected MMIE KeyID %u from " MACSTR,
3190 keyid, MAC2STR(mgmt->sa));
3191 bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
3192 return 0;
3193 }
3194 wpa_printf(MSG_DEBUG, "MMIE KeyID %u", keyid);
3195 wpa_hexdump(MSG_MSGDUMP, "MMIE IPN", mmie + 2, 6);
3196 wpa_hexdump(MSG_MSGDUMP, "MMIE MIC", mmie + 8, mic_len);
3197
3198 if (!bss->igtk_len[keyid]) {
3199 add_note(wt, MSG_DEBUG, "No IGTK known to validate BIP frame");
3200 return 0;
3201 }
3202
3203 if (os_memcmp(mmie + 2, bss->ipn[keyid], 6) <= 0) {
3204 add_note(wt, MSG_INFO, "BIP replay detected: SA=" MACSTR,
3205 MAC2STR(mgmt->sa));
3206 wpa_hexdump(MSG_INFO, "RX IPN", mmie + 2, 6);
3207 wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6);
3208 }
3209
3210 if (check_mmie_mic(bss->mgmt_group_cipher, bss->igtk[keyid],
3211 bss->igtk_len[keyid], data, len) < 0) {
3212 add_note(wt, MSG_INFO, "Invalid MMIE MIC in a frame from "
3213 MACSTR, MAC2STR(mgmt->sa));
3214 bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
3215 return -1;
3216 }
3217
3218 add_note(wt, MSG_DEBUG, "Valid MMIE MIC");
3219 os_memcpy(bss->ipn[keyid], mmie + 2, 6);
3220 bss->counters[WLANTEST_BSS_COUNTER_VALID_BIP_MMIE]++;
3221
3222 if (stype == WLAN_FC_STYPE_DEAUTH)
3223 bss->counters[WLANTEST_BSS_COUNTER_BIP_DEAUTH]++;
3224 else if (stype == WLAN_FC_STYPE_DISASSOC)
3225 bss->counters[WLANTEST_BSS_COUNTER_BIP_DISASSOC]++;
3226
3227 return 0;
3228 }
3229
3230
try_tk(struct wpa_ptk * ptk,const u8 * data,size_t len,size_t * dlen)3231 static u8 * try_tk(struct wpa_ptk *ptk,
3232 const u8 *data, size_t len, size_t *dlen)
3233 {
3234 const struct ieee80211_hdr *hdr;
3235 u8 *decrypted, *frame;
3236
3237 hdr = (const struct ieee80211_hdr *) data;
3238 if (ptk->tk_len == 16) {
3239 decrypted = ccmp_decrypt(ptk->tk, hdr, NULL, NULL, NULL,
3240 data + 24, len - 24, dlen);
3241 if (!decrypted)
3242 decrypted = gcmp_decrypt(ptk->tk, 16, hdr, NULL, NULL,
3243 NULL,
3244 data + 24, len - 24, dlen);
3245 } else if (ptk->tk_len == 32) {
3246 decrypted = ccmp_256_decrypt(ptk->tk, hdr, NULL, NULL, NULL,
3247 data + 24, len - 24, dlen);
3248 if (!decrypted)
3249 decrypted = gcmp_decrypt(ptk->tk, 32, hdr, NULL, NULL,
3250 NULL,
3251 data + 24, len - 24, dlen);
3252 } else {
3253 decrypted = NULL;
3254 }
3255 if (!decrypted)
3256 return NULL;
3257
3258 frame = os_malloc(24 + *dlen);
3259 if (frame) {
3260 os_memcpy(frame, data, 24);
3261 os_memcpy(frame + 24, decrypted, *dlen);
3262 *dlen += 24;
3263 }
3264 os_free(decrypted);
3265 return frame;
3266 }
3267
3268
mgmt_decrypt_tk(struct wlantest * wt,const u8 * data,size_t len,size_t * dlen)3269 static u8 * mgmt_decrypt_tk(struct wlantest *wt, const u8 *data, size_t len,
3270 size_t *dlen)
3271 {
3272 struct wlantest_ptk *ptk;
3273 u8 *decrypted;
3274 int prev_level = wpa_debug_level;
3275 int keyid;
3276
3277 keyid = data[24 + 3] >> 6;
3278
3279 wpa_debug_level = MSG_WARNING;
3280 dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) {
3281 decrypted = try_tk(&ptk->ptk, data, len, dlen);
3282 if (decrypted) {
3283 wpa_debug_level = prev_level;
3284 add_note(wt, MSG_DEBUG,
3285 "Found TK match from the list of all known TKs");
3286 write_decrypted_note(wt, decrypted, ptk->ptk.tk,
3287 ptk->ptk.tk_len, keyid);
3288 return decrypted;
3289 }
3290 }
3291 wpa_debug_level = prev_level;
3292
3293 return NULL;
3294 }
3295
3296
mgmt_decrypt(struct wlantest * wt,const u8 * data,size_t len,size_t * dlen)3297 static u8 * mgmt_decrypt(struct wlantest *wt, const u8 *data, size_t len,
3298 size_t *dlen)
3299 {
3300 struct wlantest_bss *bss;
3301 struct wlantest_sta *sta;
3302 const struct ieee80211_hdr *hdr;
3303 int keyid;
3304 u8 *decrypted, *frame = NULL;
3305 u8 pn[6], *rsc;
3306 u16 fc;
3307 u8 mask;
3308 size_t hdrlen = 24;
3309
3310 hdr = (const struct ieee80211_hdr *) data;
3311 fc = le_to_host16(hdr->frame_control);
3312
3313 if (fc & WLAN_FC_HTC)
3314 hdrlen += 4; /* HT Control field */
3315
3316 if (len < hdrlen + 4)
3317 return NULL;
3318
3319 if (!(data[hdrlen + 3] & 0x20)) {
3320 add_note(wt, MSG_INFO, "Expected CCMP/GCMP frame from " MACSTR
3321 " did not have ExtIV bit set to 1",
3322 MAC2STR(hdr->addr2));
3323 return NULL;
3324 }
3325
3326 mask = 0x1f;
3327 if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION ||
3328 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION_NO_ACK)
3329 mask &= ~0x10; /* FTM */
3330 if (data[hdrlen + 2] != 0 || (data[hdrlen + 3] & mask) != 0) {
3331 add_note(wt, MSG_INFO, "CCMP/GCMP mgmt frame from " MACSTR
3332 " used non-zero reserved bit", MAC2STR(hdr->addr2));
3333 }
3334
3335 keyid = data[hdrlen + 3] >> 6;
3336 if (keyid != 0) {
3337 add_note(wt, MSG_INFO, "Unexpected non-zero KeyID %d in "
3338 "individually addressed Management frame from "
3339 MACSTR, keyid, MAC2STR(hdr->addr2));
3340 }
3341
3342 bss = bss_get(wt, hdr->addr3);
3343 if (bss == NULL)
3344 return mgmt_decrypt_tk(wt, data, len, dlen);
3345 if (ether_addr_equal(hdr->addr1, hdr->addr3)) {
3346 sta = sta_find_mlo(wt, bss, hdr->addr2);
3347 if (!sta)
3348 sta = sta_get(bss, hdr->addr2);
3349 } else {
3350 sta = sta_find_mlo(wt, bss, hdr->addr1);
3351 if (!sta)
3352 sta = sta_get(bss, hdr->addr1);
3353 }
3354 if (sta == NULL || !sta->ptk_set) {
3355 decrypted = mgmt_decrypt_tk(wt, data, len, dlen);
3356 if (!decrypted)
3357 add_note(wt, MSG_MSGDUMP,
3358 "No PTK known to decrypt the frame");
3359 return decrypted;
3360 }
3361
3362 if (ether_addr_equal(hdr->addr1, hdr->addr3))
3363 rsc = sta->rsc_tods[16];
3364 else
3365 rsc = sta->rsc_fromds[16];
3366
3367 ccmp_get_pn(pn, data + hdrlen);
3368 if (os_memcmp(pn, rsc, 6) <= 0) {
3369 u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
3370 add_note(wt, MSG_INFO, "replay detected: A1=" MACSTR
3371 " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u%s",
3372 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
3373 MAC2STR(hdr->addr3),
3374 WLAN_GET_SEQ_SEQ(seq_ctrl),
3375 WLAN_GET_SEQ_FRAG(seq_ctrl),
3376 (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ?
3377 " Retry" : "");
3378 wpa_hexdump(MSG_INFO, "RX PN", pn, 6);
3379 wpa_hexdump(MSG_INFO, "RSC", rsc, 6);
3380 }
3381
3382 if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) {
3383 decrypted = ccmp_256_decrypt(sta->ptk.tk, hdr, NULL, NULL, NULL,
3384 data + hdrlen, len - hdrlen, dlen);
3385 write_decrypted_note(wt, decrypted, sta->ptk.tk, 32, keyid);
3386 } else if (sta->pairwise_cipher == WPA_CIPHER_GCMP ||
3387 sta->pairwise_cipher == WPA_CIPHER_GCMP_256) {
3388 decrypted = gcmp_decrypt(sta->ptk.tk, sta->ptk.tk_len, hdr,
3389 NULL, NULL, NULL,
3390 data + hdrlen, len - hdrlen, dlen);
3391 write_decrypted_note(wt, decrypted, sta->ptk.tk,
3392 sta->ptk.tk_len, keyid);
3393 } else {
3394 decrypted = ccmp_decrypt(sta->ptk.tk, hdr, NULL, NULL, NULL,
3395 data + hdrlen, len - hdrlen, dlen);
3396 write_decrypted_note(wt, decrypted, sta->ptk.tk, 16, keyid);
3397 }
3398 if (decrypted) {
3399 os_memcpy(rsc, pn, 6);
3400 frame = os_malloc(hdrlen + *dlen);
3401 if (frame) {
3402 os_memcpy(frame, data, hdrlen);
3403 os_memcpy(frame + hdrlen, decrypted, *dlen);
3404 *dlen += hdrlen;
3405 }
3406 } else {
3407 /* Assume the frame was corrupted and there was no FCS to check.
3408 * Allow retry of this particular frame to be processed so that
3409 * it could end up getting decrypted if it was received without
3410 * corruption. */
3411 sta->allow_duplicate = 1;
3412 }
3413
3414 os_free(decrypted);
3415
3416 return frame;
3417 }
3418
3419
is_robust_action_category(u8 category)3420 static bool is_robust_action_category(u8 category)
3421 {
3422 return category != WLAN_ACTION_PUBLIC &&
3423 category != WLAN_ACTION_HT &&
3424 category != WLAN_ACTION_UNPROTECTED_WNM &&
3425 category != WLAN_ACTION_SELF_PROTECTED &&
3426 category != WLAN_ACTION_UNPROTECTED_DMG &&
3427 category != WLAN_ACTION_VHT &&
3428 category != WLAN_ACTION_UNPROTECTED_S1G &&
3429 category != WLAN_ACTION_HE &&
3430 category != WLAN_ACTION_EHT &&
3431 category != WLAN_ACTION_VENDOR_SPECIFIC;
3432 }
3433
3434
check_mgmt_ccmp_gcmp(struct wlantest * wt,const u8 * data,size_t len)3435 static int check_mgmt_ccmp_gcmp(struct wlantest *wt, const u8 *data, size_t len)
3436 {
3437 const struct ieee80211_mgmt *mgmt;
3438 u16 fc;
3439 struct wlantest_bss *bss;
3440 struct wlantest_sta *sta;
3441 int category = -1;
3442
3443 mgmt = (const struct ieee80211_mgmt *) data;
3444 fc = le_to_host16(mgmt->frame_control);
3445
3446 if ((WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION ||
3447 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION_NO_ACK) &&
3448 len > 24) {
3449 category = mgmt->u.action.category;
3450 if (!is_robust_action_category(category))
3451 return 0; /* Not a robust management frame */
3452 }
3453
3454 bss = bss_get(wt, mgmt->bssid);
3455 if (bss == NULL)
3456 return 0;
3457 if (ether_addr_equal(mgmt->da, mgmt->bssid))
3458 sta = sta_get(bss, mgmt->sa);
3459 else
3460 sta = sta_get(bss, mgmt->da);
3461 if (sta == NULL)
3462 return 0;
3463
3464 if ((bss->rsn_capab & WPA_CAPABILITY_MFPC) &&
3465 (sta->rsn_capab & WPA_CAPABILITY_MFPC) &&
3466 (sta->state == STATE3 ||
3467 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION ||
3468 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION_NO_ACK)) {
3469 add_note(wt, MSG_INFO,
3470 "Robust individually-addressed management frame (stype=%u category=%d) sent without CCMP/GCMP by "
3471 MACSTR, WLAN_FC_GET_STYPE(fc), category,
3472 MAC2STR(mgmt->sa));
3473 return -1;
3474 }
3475
3476 return 0;
3477 }
3478
3479
rx_mgmt(struct wlantest * wt,const u8 * data,size_t len)3480 void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
3481 {
3482 const struct ieee80211_hdr *hdr;
3483 u16 fc, stype;
3484 int valid = 1;
3485 u8 *decrypted = NULL;
3486 size_t dlen;
3487
3488 if (len < 24)
3489 return;
3490
3491 hdr = (const struct ieee80211_hdr *) data;
3492 fc = le_to_host16(hdr->frame_control);
3493 wt->rx_mgmt++;
3494 stype = WLAN_FC_GET_STYPE(fc);
3495
3496 if ((hdr->addr1[0] & 0x01) &&
3497 (stype == WLAN_FC_STYPE_DEAUTH ||
3498 stype == WLAN_FC_STYPE_DISASSOC ||
3499 stype == WLAN_FC_STYPE_ACTION ||
3500 stype == WLAN_FC_STYPE_ACTION_NO_ACK)) {
3501 if (check_bip(wt, data, len) < 0)
3502 valid = 0;
3503 }
3504
3505 wpa_printf((stype == WLAN_FC_STYPE_BEACON ||
3506 stype == WLAN_FC_STYPE_PROBE_RESP ||
3507 stype == WLAN_FC_STYPE_PROBE_REQ) ?
3508 MSG_EXCESSIVE : MSG_MSGDUMP,
3509 "MGMT %s%s%s DA=" MACSTR " SA=" MACSTR " BSSID=" MACSTR,
3510 mgmt_stype(stype),
3511 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
3512 fc & WLAN_FC_ISWEP ? " Prot" : "",
3513 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
3514 MAC2STR(hdr->addr3));
3515
3516 if ((fc & WLAN_FC_ISWEP) &&
3517 !(hdr->addr1[0] & 0x01) &&
3518 (stype == WLAN_FC_STYPE_DEAUTH ||
3519 stype == WLAN_FC_STYPE_DISASSOC ||
3520 stype == WLAN_FC_STYPE_ACTION ||
3521 stype == WLAN_FC_STYPE_ACTION_NO_ACK)) {
3522 decrypted = mgmt_decrypt(wt, data, len, &dlen);
3523 if (decrypted) {
3524 write_pcap_decrypted(wt, decrypted, dlen, NULL, 0);
3525 data = decrypted;
3526 len = dlen;
3527 } else
3528 valid = 0;
3529 }
3530
3531 if (!(fc & WLAN_FC_ISWEP) &&
3532 !(hdr->addr1[0] & 0x01) &&
3533 (stype == WLAN_FC_STYPE_DEAUTH ||
3534 stype == WLAN_FC_STYPE_DISASSOC ||
3535 stype == WLAN_FC_STYPE_ACTION ||
3536 stype == WLAN_FC_STYPE_ACTION_NO_ACK)) {
3537 if (check_mgmt_ccmp_gcmp(wt, data, len) < 0)
3538 valid = 0;
3539 }
3540
3541 switch (stype) {
3542 case WLAN_FC_STYPE_BEACON:
3543 rx_mgmt_beacon(wt, data, len);
3544 break;
3545 case WLAN_FC_STYPE_PROBE_RESP:
3546 rx_mgmt_probe_resp(wt, data, len);
3547 break;
3548 case WLAN_FC_STYPE_AUTH:
3549 rx_mgmt_auth(wt, data, len);
3550 break;
3551 case WLAN_FC_STYPE_DEAUTH:
3552 rx_mgmt_deauth(wt, data, len, valid);
3553 break;
3554 case WLAN_FC_STYPE_ASSOC_REQ:
3555 rx_mgmt_assoc_req(wt, data, len);
3556 break;
3557 case WLAN_FC_STYPE_ASSOC_RESP:
3558 rx_mgmt_assoc_resp(wt, data, len);
3559 break;
3560 case WLAN_FC_STYPE_REASSOC_REQ:
3561 rx_mgmt_reassoc_req(wt, data, len);
3562 break;
3563 case WLAN_FC_STYPE_REASSOC_RESP:
3564 rx_mgmt_reassoc_resp(wt, data, len);
3565 break;
3566 case WLAN_FC_STYPE_DISASSOC:
3567 rx_mgmt_disassoc(wt, data, len, valid);
3568 break;
3569 case WLAN_FC_STYPE_ACTION:
3570 rx_mgmt_action(wt, data, len, valid, false);
3571 break;
3572 case WLAN_FC_STYPE_ACTION_NO_ACK:
3573 rx_mgmt_action(wt, data, len, valid, true);
3574 break;
3575 }
3576
3577 os_free(decrypted);
3578
3579 wt->last_mgmt_valid = valid;
3580 }
3581
3582
rx_mgmt_deauth_ack(struct wlantest * wt,const struct ieee80211_hdr * hdr)3583 static void rx_mgmt_deauth_ack(struct wlantest *wt,
3584 const struct ieee80211_hdr *hdr)
3585 {
3586 const struct ieee80211_mgmt *mgmt;
3587 struct wlantest_bss *bss;
3588 struct wlantest_sta *sta;
3589
3590 mgmt = (const struct ieee80211_mgmt *) hdr;
3591 bss = bss_get(wt, mgmt->bssid);
3592 if (bss == NULL)
3593 return;
3594 if (ether_addr_equal(mgmt->sa, mgmt->bssid))
3595 sta = sta_get(bss, mgmt->da);
3596 else
3597 sta = sta_get(bss, mgmt->sa);
3598 if (sta == NULL)
3599 return;
3600
3601 add_note(wt, MSG_DEBUG, "DEAUTH from " MACSTR " acknowledged by "
3602 MACSTR, MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
3603 if (ether_addr_equal(mgmt->sa, mgmt->bssid)) {
3604 int c;
3605 c = wt->last_mgmt_valid ?
3606 WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK :
3607 WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK;
3608 sta->counters[c]++;
3609 }
3610 }
3611
3612
rx_mgmt_disassoc_ack(struct wlantest * wt,const struct ieee80211_hdr * hdr)3613 static void rx_mgmt_disassoc_ack(struct wlantest *wt,
3614 const struct ieee80211_hdr *hdr)
3615 {
3616 const struct ieee80211_mgmt *mgmt;
3617 struct wlantest_bss *bss;
3618 struct wlantest_sta *sta;
3619
3620 mgmt = (const struct ieee80211_mgmt *) hdr;
3621 bss = bss_get(wt, mgmt->bssid);
3622 if (bss == NULL)
3623 return;
3624 if (ether_addr_equal(mgmt->sa, mgmt->bssid))
3625 sta = sta_get(bss, mgmt->da);
3626 else
3627 sta = sta_get(bss, mgmt->sa);
3628 if (sta == NULL)
3629 return;
3630
3631 add_note(wt, MSG_DEBUG, "DISASSOC from " MACSTR " acknowledged by "
3632 MACSTR, MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
3633 if (ether_addr_equal(mgmt->sa, mgmt->bssid)) {
3634 int c;
3635 c = wt->last_mgmt_valid ?
3636 WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK :
3637 WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK;
3638 sta->counters[c]++;
3639 }
3640 }
3641
3642
rx_mgmt_ack(struct wlantest * wt,const struct ieee80211_hdr * hdr)3643 void rx_mgmt_ack(struct wlantest *wt, const struct ieee80211_hdr *hdr)
3644 {
3645 u16 fc, stype;
3646 fc = le_to_host16(hdr->frame_control);
3647 stype = WLAN_FC_GET_STYPE(fc);
3648
3649 wpa_printf(MSG_MSGDUMP, "MGMT ACK: stype=%u a1=" MACSTR " a2=" MACSTR
3650 " a3=" MACSTR,
3651 stype, MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
3652 MAC2STR(hdr->addr3));
3653
3654 switch (stype) {
3655 case WLAN_FC_STYPE_DEAUTH:
3656 rx_mgmt_deauth_ack(wt, hdr);
3657 break;
3658 case WLAN_FC_STYPE_DISASSOC:
3659 rx_mgmt_disassoc_ack(wt, hdr);
3660 break;
3661 }
3662 }
3663