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