]> git.ipfire.org Git - thirdparty/hostap.git/blob - wlantest/rx_mgmt.c
c008138315d6a24476a982adae60e6cfe56e0e74
[thirdparty/hostap.git] / wlantest / rx_mgmt.c
1 /*
2 * Received Management frame processing
3 * Copyright (c) 2010-2015, 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 const char * mgmt_stype(u16 stype)
23 {
24 switch (stype) {
25 case WLAN_FC_STYPE_ASSOC_REQ:
26 return "ASSOC-REQ";
27 case WLAN_FC_STYPE_ASSOC_RESP:
28 return "ASSOC-RESP";
29 case WLAN_FC_STYPE_REASSOC_REQ:
30 return "REASSOC-REQ";
31 case WLAN_FC_STYPE_REASSOC_RESP:
32 return "REASSOC-RESP";
33 case WLAN_FC_STYPE_PROBE_REQ:
34 return "PROBE-REQ";
35 case WLAN_FC_STYPE_PROBE_RESP:
36 return "PROBE-RESP";
37 case WLAN_FC_STYPE_BEACON:
38 return "BEACON";
39 case WLAN_FC_STYPE_ATIM:
40 return "ATIM";
41 case WLAN_FC_STYPE_DISASSOC:
42 return "DISASSOC";
43 case WLAN_FC_STYPE_AUTH:
44 return "AUTH";
45 case WLAN_FC_STYPE_DEAUTH:
46 return "DEAUTH";
47 case WLAN_FC_STYPE_ACTION:
48 return "ACTION";
49 }
50 return "??";
51 }
52
53
54 static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len)
55 {
56 const struct ieee80211_mgmt *mgmt;
57 struct wlantest_bss *bss;
58 struct ieee802_11_elems elems;
59 size_t offset;
60
61 mgmt = (const struct ieee80211_mgmt *) data;
62 offset = mgmt->u.beacon.variable - data;
63 if (len < offset)
64 return;
65 bss = bss_get(wt, mgmt->bssid);
66 if (bss == NULL)
67 return;
68 if (bss->proberesp_seen)
69 return; /* do not override with Beacon data */
70 bss->capab_info = le_to_host16(mgmt->u.beacon.capab_info);
71 if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - offset,
72 &elems, 0) == ParseFailed) {
73 if (bss->parse_error_reported)
74 return;
75 add_note(wt, MSG_INFO, "Invalid IEs in a Beacon frame from "
76 MACSTR, MAC2STR(mgmt->sa));
77 bss->parse_error_reported = 1;
78 return;
79 }
80
81 bss_update(wt, bss, &elems);
82 }
83
84
85 static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len)
86 {
87 const struct ieee80211_mgmt *mgmt;
88 struct wlantest_bss *bss;
89 struct ieee802_11_elems elems;
90 size_t offset;
91
92 mgmt = (const struct ieee80211_mgmt *) data;
93 offset = mgmt->u.probe_resp.variable - data;
94 if (len < offset)
95 return;
96 bss = bss_get(wt, mgmt->bssid);
97 if (bss == NULL)
98 return;
99
100 bss->counters[WLANTEST_BSS_COUNTER_PROBE_RESPONSE]++;
101 bss->capab_info = le_to_host16(mgmt->u.probe_resp.capab_info);
102 if (ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - offset,
103 &elems, 0) == ParseFailed) {
104 if (bss->parse_error_reported)
105 return;
106 add_note(wt, MSG_INFO, "Invalid IEs in a Probe Response frame "
107 "from " MACSTR, MAC2STR(mgmt->sa));
108 bss->parse_error_reported = 1;
109 return;
110 }
111
112 bss_update(wt, bss, &elems);
113 }
114
115
116 static void process_fils_auth(struct wlantest *wt, struct wlantest_bss *bss,
117 struct wlantest_sta *sta,
118 const struct ieee80211_mgmt *mgmt, size_t len)
119 {
120 struct ieee802_11_elems elems;
121 u16 trans;
122 struct wpa_ie_data data;
123
124 if (sta->auth_alg != WLAN_AUTH_FILS_SK ||
125 len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth))
126 return;
127
128 trans = le_to_host16(mgmt->u.auth.auth_transaction);
129
130 if (ieee802_11_parse_elems(mgmt->u.auth.variable,
131 len - IEEE80211_HDRLEN -
132 sizeof(mgmt->u.auth), &elems, 0) ==
133 ParseFailed)
134 return;
135
136 if (trans == 1) {
137 if (!elems.rsn_ie) {
138 add_note(wt, MSG_INFO,
139 "FILS Authentication frame missing RSNE");
140 return;
141 }
142 if (wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2,
143 elems.rsn_ie_len + 2, &data) < 0) {
144 add_note(wt, MSG_INFO,
145 "Invalid RSNE in FILS Authentication frame");
146 return;
147 }
148 sta->key_mgmt = data.key_mgmt;
149 sta->pairwise_cipher = data.pairwise_cipher;
150 }
151
152 if (!elems.fils_nonce) {
153 add_note(wt, MSG_INFO,
154 "FILS Authentication frame missing nonce");
155 return;
156 }
157
158 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
159 os_memcpy(sta->anonce, elems.fils_nonce, FILS_NONCE_LEN);
160 else
161 os_memcpy(sta->snonce, elems.fils_nonce, FILS_NONCE_LEN);
162 }
163
164
165 static void rx_mgmt_auth(struct wlantest *wt, const u8 *data, size_t len)
166 {
167 const struct ieee80211_mgmt *mgmt;
168 struct wlantest_bss *bss;
169 struct wlantest_sta *sta;
170 u16 alg, trans, status;
171
172 mgmt = (const struct ieee80211_mgmt *) data;
173 bss = bss_get(wt, mgmt->bssid);
174 if (bss == NULL)
175 return;
176 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
177 sta = sta_get(bss, mgmt->da);
178 else
179 sta = sta_get(bss, mgmt->sa);
180 if (sta == NULL)
181 return;
182
183 if (len < 24 + 6) {
184 add_note(wt, MSG_INFO, "Too short Authentication frame from "
185 MACSTR, MAC2STR(mgmt->sa));
186 return;
187 }
188
189 alg = le_to_host16(mgmt->u.auth.auth_alg);
190 sta->auth_alg = alg;
191 trans = le_to_host16(mgmt->u.auth.auth_transaction);
192 status = le_to_host16(mgmt->u.auth.status_code);
193
194 wpa_printf(MSG_DEBUG, "AUTH " MACSTR " -> " MACSTR
195 " (alg=%u trans=%u status=%u)",
196 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), alg, trans, status);
197
198 if (alg == 0 && trans == 2 && status == 0) {
199 if (sta->state == STATE1) {
200 add_note(wt, MSG_DEBUG, "STA " MACSTR
201 " moved to State 2 with " MACSTR,
202 MAC2STR(sta->addr), MAC2STR(bss->bssid));
203 sta->state = STATE2;
204 }
205 }
206
207 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
208 sta->counters[WLANTEST_STA_COUNTER_AUTH_RX]++;
209 else
210 sta->counters[WLANTEST_STA_COUNTER_AUTH_TX]++;
211
212 process_fils_auth(wt, bss, sta, mgmt, len);
213 }
214
215
216 static void deauth_all_stas(struct wlantest *wt, struct wlantest_bss *bss)
217 {
218 struct wlantest_sta *sta;
219 dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) {
220 if (sta->state == STATE1)
221 continue;
222 add_note(wt, MSG_DEBUG, "STA " MACSTR
223 " moved to State 1 with " MACSTR,
224 MAC2STR(sta->addr), MAC2STR(bss->bssid));
225 sta->state = STATE1;
226 }
227 }
228
229
230 static void tdls_link_down(struct wlantest *wt, struct wlantest_bss *bss,
231 struct wlantest_sta *sta)
232 {
233 struct wlantest_tdls *tdls;
234 dl_list_for_each(tdls, &bss->tdls, struct wlantest_tdls, list) {
235 if ((tdls->init == sta || tdls->resp == sta) && tdls->link_up)
236 {
237 add_note(wt, MSG_DEBUG, "TDLS: Set link down based on "
238 "STA deauth/disassoc");
239 tdls->link_up = 0;
240 }
241 }
242 }
243
244
245 static void rx_mgmt_deauth(struct wlantest *wt, const u8 *data, size_t len,
246 int valid)
247 {
248 const struct ieee80211_mgmt *mgmt;
249 struct wlantest_bss *bss;
250 struct wlantest_sta *sta;
251 u16 fc, reason;
252
253 mgmt = (const struct ieee80211_mgmt *) data;
254 bss = bss_get(wt, mgmt->bssid);
255 if (bss == NULL)
256 return;
257 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
258 sta = sta_get(bss, mgmt->da);
259 else
260 sta = sta_get(bss, mgmt->sa);
261
262 if (len < 24 + 2) {
263 add_note(wt, MSG_INFO, "Too short Deauthentication frame from "
264 MACSTR, MAC2STR(mgmt->sa));
265 return;
266 }
267
268 reason = le_to_host16(mgmt->u.deauth.reason_code);
269 wpa_printf(MSG_DEBUG, "DEAUTH " MACSTR " -> " MACSTR
270 " (reason=%u) (valid=%d)",
271 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
272 reason, valid);
273 wpa_hexdump(MSG_MSGDUMP, "DEAUTH payload", data + 24, len - 24);
274
275 if (sta == NULL) {
276 if (valid && mgmt->da[0] == 0xff)
277 deauth_all_stas(wt, bss);
278 return;
279 }
280
281 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
282 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_RX :
283 WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX]++;
284 if (sta->pwrmgt && !sta->pspoll)
285 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_ASLEEP]++;
286 else
287 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_AWAKE]++;
288
289 fc = le_to_host16(mgmt->frame_control);
290 if (!(fc & WLAN_FC_ISWEP) && reason == 6)
291 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_RC6]++;
292 else if (!(fc & WLAN_FC_ISWEP) && reason == 7)
293 sta->counters[WLANTEST_STA_COUNTER_DEAUTH_RX_RC7]++;
294 } else
295 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DEAUTH_TX :
296 WLANTEST_STA_COUNTER_INVALID_DEAUTH_TX]++;
297
298 if (!valid) {
299 add_note(wt, MSG_INFO, "Do not change STA " MACSTR " State "
300 "since Disassociation frame was not protected "
301 "correctly", MAC2STR(sta->addr));
302 return;
303 }
304
305 if (sta->state != STATE1) {
306 add_note(wt, MSG_DEBUG, "STA " MACSTR
307 " moved to State 1 with " MACSTR,
308 MAC2STR(sta->addr), MAC2STR(bss->bssid));
309 sta->state = STATE1;
310 }
311 tdls_link_down(wt, bss, sta);
312 }
313
314
315 static const u8 * get_fils_session(const u8 *ies, size_t ies_len)
316 {
317 const u8 *ie, *end;
318
319 ie = ies;
320 end = ((const u8 *) ie) + ies_len;
321 while (ie + 1 < end) {
322 if (ie + 2 + ie[1] > end)
323 break;
324 if (ie[0] == WLAN_EID_EXTENSION &&
325 ie[1] >= 1 + FILS_SESSION_LEN &&
326 ie[2] == WLAN_EID_EXT_FILS_SESSION)
327 return ie;
328 ie += 2 + ie[1];
329 }
330 return NULL;
331 }
332
333
334 static int try_rmsk(struct wlantest *wt, struct wlantest_bss *bss,
335 struct wlantest_sta *sta, struct wlantest_pmk *pmk,
336 const u8 *frame_start, const u8 *frame_ad,
337 const u8 *frame_ad_end, const u8 *encr_end)
338 {
339 size_t pmk_len = 0;
340 u8 pmk_buf[PMK_LEN_MAX];
341 struct wpa_ptk ptk;
342 u8 ick[FILS_ICK_MAX_LEN];
343 size_t ick_len;
344 const u8 *aad[5];
345 size_t aad_len[5];
346 u8 buf[2000];
347
348 if (fils_rmsk_to_pmk(sta->key_mgmt, pmk->pmk, pmk->pmk_len,
349 sta->snonce, sta->anonce, NULL, 0,
350 pmk_buf, &pmk_len) < 0)
351 return -1;
352
353 if (fils_pmk_to_ptk(pmk_buf, pmk_len, sta->addr, bss->bssid,
354 sta->snonce, sta->anonce, NULL, 0,
355 &ptk, ick, &ick_len,
356 sta->key_mgmt, sta->pairwise_cipher,
357 NULL, NULL) < 0)
358 return -1;
359
360 /* Check AES-SIV decryption with the derived key */
361
362 /* AES-SIV AAD vectors */
363
364 /* The STA's MAC address */
365 aad[0] = sta->addr;
366 aad_len[0] = ETH_ALEN;
367 /* The AP's BSSID */
368 aad[1] = bss->bssid;
369 aad_len[1] = ETH_ALEN;
370 /* The STA's nonce */
371 aad[2] = sta->snonce;
372 aad_len[2] = FILS_NONCE_LEN;
373 /* The AP's nonce */
374 aad[3] = sta->anonce;
375 aad_len[3] = FILS_NONCE_LEN;
376 /*
377 * The (Re)Association Request frame from the Capability Information
378 * field to the FILS Session element (both inclusive).
379 */
380 aad[4] = frame_ad;
381 aad_len[4] = frame_ad_end - frame_ad;
382
383 if (encr_end - frame_ad_end < AES_BLOCK_SIZE ||
384 encr_end - frame_ad_end > sizeof(buf))
385 return -1;
386 if (aes_siv_decrypt(ptk.kek, ptk.kek_len,
387 frame_ad_end, encr_end - frame_ad_end,
388 5, aad, aad_len, buf) < 0) {
389 wpa_printf(MSG_DEBUG,
390 "FILS: Derived PTK did not match AES-SIV data");
391 return -1;
392 }
393
394 add_note(wt, MSG_DEBUG, "Derived FILS PTK");
395 os_memcpy(&sta->ptk, &ptk, sizeof(ptk));
396 sta->ptk_set = 1;
397 sta->counters[WLANTEST_STA_COUNTER_PTK_LEARNED]++;
398 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements",
399 buf, encr_end - frame_ad_end - AES_BLOCK_SIZE);
400
401 if (wt->write_pcap_dumper || wt->pcapng) {
402 write_pcap_decrypted(wt, frame_start,
403 frame_ad_end - frame_start,
404 buf,
405 encr_end - frame_ad_end - AES_BLOCK_SIZE);
406 }
407
408 return 0;
409 }
410
411
412 static void derive_fils_keys(struct wlantest *wt, struct wlantest_bss *bss,
413 struct wlantest_sta *sta, const u8 *frame_start,
414 const u8 *frame_ad, const u8 *frame_ad_end,
415 const u8 *encr_end)
416 {
417 struct wlantest_pmk *pmk;
418
419 wpa_printf(MSG_DEBUG, "Trying to derive PTK for " MACSTR
420 " from FILS rMSK", MAC2STR(sta->addr));
421
422 dl_list_for_each(pmk, &bss->pmk, struct wlantest_pmk,
423 list) {
424 wpa_printf(MSG_DEBUG, "Try per-BSS PMK");
425 if (try_rmsk(wt, bss, sta, pmk, frame_start, frame_ad,
426 frame_ad_end, encr_end) == 0)
427 return;
428 }
429
430 dl_list_for_each(pmk, &wt->pmk, struct wlantest_pmk, list) {
431 wpa_printf(MSG_DEBUG, "Try global PMK");
432 if (try_rmsk(wt, bss, sta, pmk, frame_start, frame_ad,
433 frame_ad_end, encr_end) == 0)
434 return;
435 }
436 }
437
438
439 static void rx_mgmt_assoc_req(struct wlantest *wt, const u8 *data, size_t len)
440 {
441 const struct ieee80211_mgmt *mgmt;
442 struct wlantest_bss *bss;
443 struct wlantest_sta *sta;
444 struct ieee802_11_elems elems;
445 const u8 *ie;
446 size_t ie_len;
447
448 mgmt = (const struct ieee80211_mgmt *) data;
449 bss = bss_get(wt, mgmt->bssid);
450 if (bss == NULL)
451 return;
452 sta = sta_get(bss, mgmt->sa);
453 if (sta == NULL)
454 return;
455
456 if (len < 24 + 4) {
457 add_note(wt, MSG_INFO, "Too short Association Request frame "
458 "from " MACSTR, MAC2STR(mgmt->sa));
459 return;
460 }
461
462 wpa_printf(MSG_DEBUG, "ASSOCREQ " MACSTR " -> " MACSTR
463 " (capab=0x%x listen_int=%u)",
464 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
465 le_to_host16(mgmt->u.assoc_req.capab_info),
466 le_to_host16(mgmt->u.assoc_req.listen_interval));
467
468 sta->counters[WLANTEST_STA_COUNTER_ASSOCREQ_TX]++;
469
470 ie = mgmt->u.assoc_req.variable;
471 ie_len = len - (mgmt->u.assoc_req.variable - data);
472
473 if (sta->auth_alg == WLAN_AUTH_FILS_SK) {
474 const u8 *session, *frame_ad, *frame_ad_end, *encr_end;
475
476 session = get_fils_session(ie, ie_len);
477 if (session) {
478 frame_ad = (const u8 *) &mgmt->u.assoc_req.capab_info;
479 frame_ad_end = session + 2 + session[1];
480 encr_end = data + len;
481 derive_fils_keys(wt, bss, sta, data, frame_ad,
482 frame_ad_end, encr_end);
483 ie_len = session - ie;
484 }
485 }
486
487 if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
488 add_note(wt, MSG_INFO, "Invalid IEs in Association Request "
489 "frame from " MACSTR, MAC2STR(mgmt->sa));
490 return;
491 }
492
493 sta->assocreq_capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
494 sta->assocreq_listen_int =
495 le_to_host16(mgmt->u.assoc_req.listen_interval);
496 os_free(sta->assocreq_ies);
497 sta->assocreq_ies_len = len - (mgmt->u.assoc_req.variable - data);
498 sta->assocreq_ies = os_malloc(sta->assocreq_ies_len);
499 if (sta->assocreq_ies)
500 os_memcpy(sta->assocreq_ies, mgmt->u.assoc_req.variable,
501 sta->assocreq_ies_len);
502
503 sta_update_assoc(sta, &elems);
504 }
505
506
507 static void decrypt_fils_assoc_resp(struct wlantest *wt,
508 struct wlantest_bss *bss,
509 struct wlantest_sta *sta,
510 const u8 *frame_start, const u8 *frame_ad,
511 const u8 *frame_ad_end, const u8 *encr_end)
512 {
513 const u8 *aad[5];
514 size_t aad_len[5];
515 u8 buf[2000];
516
517 if (!sta->ptk_set)
518 return;
519
520 /* Check AES-SIV decryption with the derived key */
521
522 /* AES-SIV AAD vectors */
523
524 /* The AP's BSSID */
525 aad[0] = bss->bssid;
526 aad_len[0] = ETH_ALEN;
527 /* The STA's MAC address */
528 aad[1] = sta->addr;
529 aad_len[1] = ETH_ALEN;
530 /* The AP's nonce */
531 aad[2] = sta->anonce;
532 aad_len[2] = FILS_NONCE_LEN;
533 /* The STA's nonce */
534 aad[3] = sta->snonce;
535 aad_len[3] = FILS_NONCE_LEN;
536 /*
537 * The (Re)Association Response frame from the Capability Information
538 * field to the FILS Session element (both inclusive).
539 */
540 aad[4] = frame_ad;
541 aad_len[4] = frame_ad_end - frame_ad;
542
543 if (encr_end - frame_ad_end < AES_BLOCK_SIZE ||
544 encr_end - frame_ad_end > sizeof(buf))
545 return;
546 if (aes_siv_decrypt(sta->ptk.kek, sta->ptk.kek_len,
547 frame_ad_end, encr_end - frame_ad_end,
548 5, aad, aad_len, buf) < 0) {
549 wpa_printf(MSG_DEBUG,
550 "FILS: Derived PTK did not match AES-SIV data");
551 return;
552 }
553
554 wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Response elements",
555 buf, encr_end - frame_ad_end - AES_BLOCK_SIZE);
556
557 if (wt->write_pcap_dumper || wt->pcapng) {
558 write_pcap_decrypted(wt, frame_start,
559 frame_ad_end - frame_start,
560 buf,
561 encr_end - frame_ad_end - AES_BLOCK_SIZE);
562 }
563 }
564
565
566 static void rx_mgmt_assoc_resp(struct wlantest *wt, const u8 *data, size_t len)
567 {
568 const struct ieee80211_mgmt *mgmt;
569 struct wlantest_bss *bss;
570 struct wlantest_sta *sta;
571 u16 capab, status, aid;
572 const u8 *ies;
573 size_t ies_len;
574 struct wpa_ft_ies parse;
575
576 mgmt = (const struct ieee80211_mgmt *) data;
577 bss = bss_get(wt, mgmt->bssid);
578 if (bss == NULL)
579 return;
580 sta = sta_get(bss, mgmt->da);
581 if (sta == NULL)
582 return;
583
584 if (len < 24 + 6) {
585 add_note(wt, MSG_INFO, "Too short Association Response frame "
586 "from " MACSTR, MAC2STR(mgmt->sa));
587 return;
588 }
589
590 ies = mgmt->u.assoc_resp.variable;
591 ies_len = len - (mgmt->u.assoc_resp.variable - data);
592
593 capab = le_to_host16(mgmt->u.assoc_resp.capab_info);
594 status = le_to_host16(mgmt->u.assoc_resp.status_code);
595 aid = le_to_host16(mgmt->u.assoc_resp.aid);
596
597 wpa_printf(MSG_DEBUG, "ASSOCRESP " MACSTR " -> " MACSTR
598 " (capab=0x%x status=%u aid=%u)",
599 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
600 aid & 0x3fff);
601
602 if (sta->auth_alg == WLAN_AUTH_FILS_SK) {
603 const u8 *session, *frame_ad, *frame_ad_end, *encr_end;
604
605 session = get_fils_session(ies, ies_len);
606 if (session) {
607 frame_ad = (const u8 *) &mgmt->u.assoc_resp.capab_info;
608 frame_ad_end = session + 2 + session[1];
609 encr_end = data + len;
610 decrypt_fils_assoc_resp(wt, bss, sta, data, frame_ad,
611 frame_ad_end, encr_end);
612 ies_len = session - ies;
613 }
614 }
615
616 if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
617 struct ieee802_11_elems elems;
618 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
619 ParseFailed) {
620 add_note(wt, MSG_INFO, "Failed to parse IEs in "
621 "AssocResp from " MACSTR,
622 MAC2STR(mgmt->sa));
623 } else if (elems.timeout_int == NULL ||
624 elems.timeout_int[0] !=
625 WLAN_TIMEOUT_ASSOC_COMEBACK) {
626 add_note(wt, MSG_INFO, "No valid Timeout Interval IE "
627 "with Assoc Comeback time in AssocResp "
628 "(status=30) from " MACSTR,
629 MAC2STR(mgmt->sa));
630 } else {
631 sta->counters[
632 WLANTEST_STA_COUNTER_ASSOCRESP_COMEBACK]++;
633 }
634 }
635
636 if (status)
637 return;
638
639 if ((aid & 0xc000) != 0xc000) {
640 add_note(wt, MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
641 "in Association Response from " MACSTR,
642 MAC2STR(mgmt->sa));
643 }
644 sta->aid = aid & 0xc000;
645
646 if (sta->state < STATE2) {
647 add_note(wt, MSG_DEBUG,
648 "STA " MACSTR " was not in State 2 when "
649 "getting associated", MAC2STR(sta->addr));
650 }
651
652 if (sta->state < STATE3) {
653 add_note(wt, MSG_DEBUG, "STA " MACSTR
654 " moved to State 3 with " MACSTR,
655 MAC2STR(sta->addr), MAC2STR(bss->bssid));
656 sta->state = STATE3;
657 }
658
659 if (wpa_ft_parse_ies(ies, ies_len, &parse, 0) == 0) {
660 if (parse.r0kh_id) {
661 os_memcpy(bss->r0kh_id, parse.r0kh_id,
662 parse.r0kh_id_len);
663 bss->r0kh_id_len = parse.r0kh_id_len;
664 }
665 if (parse.r1kh_id)
666 os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
667 }
668 }
669
670
671 static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data,
672 size_t len)
673 {
674 const struct ieee80211_mgmt *mgmt;
675 struct wlantest_bss *bss;
676 struct wlantest_sta *sta;
677 struct ieee802_11_elems elems;
678 const u8 *ie;
679 size_t ie_len;
680
681 mgmt = (const struct ieee80211_mgmt *) data;
682 bss = bss_get(wt, mgmt->bssid);
683 if (bss == NULL)
684 return;
685 sta = sta_get(bss, mgmt->sa);
686 if (sta == NULL)
687 return;
688
689 if (len < 24 + 4 + ETH_ALEN) {
690 add_note(wt, MSG_INFO, "Too short Reassociation Request frame "
691 "from " MACSTR, MAC2STR(mgmt->sa));
692 return;
693 }
694
695 wpa_printf(MSG_DEBUG, "REASSOCREQ " MACSTR " -> " MACSTR
696 " (capab=0x%x listen_int=%u current_ap=" MACSTR ")",
697 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
698 le_to_host16(mgmt->u.reassoc_req.capab_info),
699 le_to_host16(mgmt->u.reassoc_req.listen_interval),
700 MAC2STR(mgmt->u.reassoc_req.current_ap));
701
702 sta->counters[WLANTEST_STA_COUNTER_REASSOCREQ_TX]++;
703
704 ie = mgmt->u.reassoc_req.variable;
705 ie_len = len - (mgmt->u.reassoc_req.variable - data);
706
707 if (sta->auth_alg == WLAN_AUTH_FILS_SK) {
708 const u8 *session, *frame_ad, *frame_ad_end, *encr_end;
709
710 session = get_fils_session(ie, ie_len);
711 if (session) {
712 frame_ad = (const u8 *) &mgmt->u.reassoc_req.capab_info;
713 frame_ad_end = session + 2 + session[1];
714 encr_end = data + len;
715 derive_fils_keys(wt, bss, sta, data, frame_ad,
716 frame_ad_end, encr_end);
717 ie_len = session - ie;
718 }
719 }
720
721 if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
722 add_note(wt, MSG_INFO, "Invalid IEs in Reassociation Request "
723 "frame from " MACSTR, MAC2STR(mgmt->sa));
724 return;
725 }
726
727 sta->assocreq_capab_info =
728 le_to_host16(mgmt->u.reassoc_req.capab_info);
729 sta->assocreq_listen_int =
730 le_to_host16(mgmt->u.reassoc_req.listen_interval);
731 os_free(sta->assocreq_ies);
732 sta->assocreq_ies_len = len - (mgmt->u.reassoc_req.variable - data);
733 sta->assocreq_ies = os_malloc(sta->assocreq_ies_len);
734 if (sta->assocreq_ies)
735 os_memcpy(sta->assocreq_ies, mgmt->u.reassoc_req.variable,
736 sta->assocreq_ies_len);
737
738 sta_update_assoc(sta, &elems);
739 }
740
741
742 static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data,
743 size_t len)
744 {
745 const struct ieee80211_mgmt *mgmt;
746 struct wlantest_bss *bss;
747 struct wlantest_sta *sta;
748 u16 capab, status, aid;
749 const u8 *ies;
750 size_t ies_len;
751
752 mgmt = (const struct ieee80211_mgmt *) data;
753 bss = bss_get(wt, mgmt->bssid);
754 if (bss == NULL)
755 return;
756 sta = sta_get(bss, mgmt->da);
757 if (sta == NULL)
758 return;
759
760 if (len < 24 + 6) {
761 add_note(wt, MSG_INFO, "Too short Reassociation Response frame "
762 "from " MACSTR, MAC2STR(mgmt->sa));
763 return;
764 }
765
766 ies = mgmt->u.reassoc_resp.variable;
767 ies_len = len - (mgmt->u.reassoc_resp.variable - data);
768
769 capab = le_to_host16(mgmt->u.reassoc_resp.capab_info);
770 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
771 aid = le_to_host16(mgmt->u.reassoc_resp.aid);
772
773 wpa_printf(MSG_DEBUG, "REASSOCRESP " MACSTR " -> " MACSTR
774 " (capab=0x%x status=%u aid=%u)",
775 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), capab, status,
776 aid & 0x3fff);
777
778 if (sta->auth_alg == WLAN_AUTH_FILS_SK) {
779 const u8 *session, *frame_ad, *frame_ad_end, *encr_end;
780
781 session = get_fils_session(ies, ies_len);
782 if (session) {
783 frame_ad = (const u8 *)
784 &mgmt->u.reassoc_resp.capab_info;
785 frame_ad_end = session + 2 + session[1];
786 encr_end = data + len;
787 decrypt_fils_assoc_resp(wt, bss, sta, data, frame_ad,
788 frame_ad_end, encr_end);
789 ies_len = session - ies;
790 }
791 }
792
793 if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
794 struct ieee802_11_elems elems;
795
796 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
797 ParseFailed) {
798 add_note(wt, MSG_INFO, "Failed to parse IEs in "
799 "ReassocResp from " MACSTR,
800 MAC2STR(mgmt->sa));
801 } else if (elems.timeout_int == NULL ||
802 elems.timeout_int[0] !=
803 WLAN_TIMEOUT_ASSOC_COMEBACK) {
804 add_note(wt, MSG_INFO, "No valid Timeout Interval IE "
805 "with Assoc Comeback time in ReassocResp "
806 "(status=30) from " MACSTR,
807 MAC2STR(mgmt->sa));
808 } else {
809 sta->counters[
810 WLANTEST_STA_COUNTER_REASSOCRESP_COMEBACK]++;
811 }
812 }
813
814 if (status)
815 return;
816
817 if ((aid & 0xc000) != 0xc000) {
818 add_note(wt, MSG_DEBUG, "Two MSBs of the AID were not set to 1 "
819 "in Reassociation Response from " MACSTR,
820 MAC2STR(mgmt->sa));
821 }
822 sta->aid = aid & 0xc000;
823
824 if (sta->state < STATE2) {
825 add_note(wt, MSG_DEBUG,
826 "STA " MACSTR " was not in State 2 when "
827 "getting associated", MAC2STR(sta->addr));
828 }
829
830 if (sta->state < STATE3) {
831 add_note(wt, MSG_DEBUG, "STA " MACSTR
832 " moved to State 3 with " MACSTR,
833 MAC2STR(sta->addr), MAC2STR(bss->bssid));
834 sta->state = STATE3;
835 }
836 }
837
838
839 static void disassoc_all_stas(struct wlantest *wt, struct wlantest_bss *bss)
840 {
841 struct wlantest_sta *sta;
842 dl_list_for_each(sta, &bss->sta, struct wlantest_sta, list) {
843 if (sta->state <= STATE2)
844 continue;
845 add_note(wt, MSG_DEBUG, "STA " MACSTR
846 " moved to State 2 with " MACSTR,
847 MAC2STR(sta->addr), MAC2STR(bss->bssid));
848 sta->state = STATE2;
849 }
850 }
851
852
853 static void rx_mgmt_disassoc(struct wlantest *wt, const u8 *data, size_t len,
854 int valid)
855 {
856 const struct ieee80211_mgmt *mgmt;
857 struct wlantest_bss *bss;
858 struct wlantest_sta *sta;
859 u16 fc, reason;
860
861 mgmt = (const struct ieee80211_mgmt *) data;
862 bss = bss_get(wt, mgmt->bssid);
863 if (bss == NULL)
864 return;
865 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
866 sta = sta_get(bss, mgmt->da);
867 else
868 sta = sta_get(bss, mgmt->sa);
869
870 if (len < 24 + 2) {
871 add_note(wt, MSG_INFO, "Too short Disassociation frame from "
872 MACSTR, MAC2STR(mgmt->sa));
873 return;
874 }
875
876 reason = le_to_host16(mgmt->u.disassoc.reason_code);
877 wpa_printf(MSG_DEBUG, "DISASSOC " MACSTR " -> " MACSTR
878 " (reason=%u) (valid=%d)",
879 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
880 reason, valid);
881 wpa_hexdump(MSG_MSGDUMP, "DISASSOC payload", data + 24, len - 24);
882
883 if (sta == NULL) {
884 if (valid && mgmt->da[0] == 0xff)
885 disassoc_all_stas(wt, bss);
886 return;
887 }
888
889 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
890 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_RX :
891 WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX]++;
892 if (sta->pwrmgt && !sta->pspoll)
893 sta->counters[
894 WLANTEST_STA_COUNTER_DISASSOC_RX_ASLEEP]++;
895 else
896 sta->counters[
897 WLANTEST_STA_COUNTER_DISASSOC_RX_AWAKE]++;
898
899 fc = le_to_host16(mgmt->frame_control);
900 if (!(fc & WLAN_FC_ISWEP) && reason == 6)
901 sta->counters[WLANTEST_STA_COUNTER_DISASSOC_RX_RC6]++;
902 else if (!(fc & WLAN_FC_ISWEP) && reason == 7)
903 sta->counters[WLANTEST_STA_COUNTER_DISASSOC_RX_RC7]++;
904 } else
905 sta->counters[valid ? WLANTEST_STA_COUNTER_VALID_DISASSOC_TX :
906 WLANTEST_STA_COUNTER_INVALID_DISASSOC_TX]++;
907
908 if (!valid) {
909 add_note(wt, MSG_INFO, "Do not change STA " MACSTR " State "
910 "since Disassociation frame was not protected "
911 "correctly", MAC2STR(sta->addr));
912 return;
913 }
914
915 if (sta->state < STATE2) {
916 add_note(wt, MSG_DEBUG,
917 "STA " MACSTR " was not in State 2 or 3 "
918 "when getting disassociated", MAC2STR(sta->addr));
919 }
920
921 if (sta->state > STATE2) {
922 add_note(wt, MSG_DEBUG, "STA " MACSTR
923 " moved to State 2 with " MACSTR,
924 MAC2STR(sta->addr), MAC2STR(bss->bssid));
925 sta->state = STATE2;
926 }
927 tdls_link_down(wt, bss, sta);
928 }
929
930
931 static void rx_mgmt_action_sa_query_req(struct wlantest *wt,
932 struct wlantest_sta *sta,
933 const struct ieee80211_mgmt *mgmt,
934 size_t len, int valid)
935 {
936 const u8 *rx_id;
937 u8 *id;
938
939 rx_id = (const u8 *) mgmt->u.action.u.sa_query_req.trans_id;
940 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
941 id = sta->ap_sa_query_tr;
942 else
943 id = sta->sta_sa_query_tr;
944 add_note(wt, MSG_INFO, "SA Query Request " MACSTR " -> " MACSTR
945 " (trans_id=%02x%02x)%s",
946 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1],
947 valid ? "" : " (invalid protection)");
948 os_memcpy(id, mgmt->u.action.u.sa_query_req.trans_id, 2);
949 if (os_memcmp(mgmt->sa, sta->addr, ETH_ALEN) == 0)
950 sta->counters[valid ?
951 WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_TX :
952 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_TX]++;
953 else
954 sta->counters[valid ?
955 WLANTEST_STA_COUNTER_VALID_SAQUERYREQ_RX :
956 WLANTEST_STA_COUNTER_INVALID_SAQUERYREQ_RX]++;
957 }
958
959
960 static void rx_mgmt_action_sa_query_resp(struct wlantest *wt,
961 struct wlantest_sta *sta,
962 const struct ieee80211_mgmt *mgmt,
963 size_t len, int valid)
964 {
965 const u8 *rx_id;
966 u8 *id;
967 int match;
968
969 rx_id = (const u8 *) mgmt->u.action.u.sa_query_resp.trans_id;
970 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
971 id = sta->sta_sa_query_tr;
972 else
973 id = sta->ap_sa_query_tr;
974 match = os_memcmp(rx_id, id, 2) == 0;
975 add_note(wt, MSG_INFO, "SA Query Response " MACSTR " -> " MACSTR
976 " (trans_id=%02x%02x; %s)%s",
977 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), rx_id[0], rx_id[1],
978 match ? "match" : "mismatch",
979 valid ? "" : " (invalid protection)");
980 if (os_memcmp(mgmt->sa, sta->addr, ETH_ALEN) == 0)
981 sta->counters[(valid && match) ?
982 WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_TX :
983 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_TX]++;
984 else
985 sta->counters[(valid && match) ?
986 WLANTEST_STA_COUNTER_VALID_SAQUERYRESP_RX :
987 WLANTEST_STA_COUNTER_INVALID_SAQUERYRESP_RX]++;
988 }
989
990
991 static void rx_mgmt_action_sa_query(struct wlantest *wt,
992 struct wlantest_sta *sta,
993 const struct ieee80211_mgmt *mgmt,
994 size_t len, int valid)
995 {
996 if (len < 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) {
997 add_note(wt, MSG_INFO, "Too short SA Query frame from " MACSTR,
998 MAC2STR(mgmt->sa));
999 return;
1000 }
1001
1002 if (len > 24 + 2 + WLAN_SA_QUERY_TR_ID_LEN) {
1003 size_t elen = len - (24 + 2 + WLAN_SA_QUERY_TR_ID_LEN);
1004 add_note(wt, MSG_INFO, "Unexpected %u octets of extra data at "
1005 "the end of SA Query frame from " MACSTR,
1006 (unsigned) elen, MAC2STR(mgmt->sa));
1007 wpa_hexdump(MSG_INFO, "SA Query extra data",
1008 ((const u8 *) mgmt) + len - elen, elen);
1009 }
1010
1011 switch (mgmt->u.action.u.sa_query_req.action) {
1012 case WLAN_SA_QUERY_REQUEST:
1013 rx_mgmt_action_sa_query_req(wt, sta, mgmt, len, valid);
1014 break;
1015 case WLAN_SA_QUERY_RESPONSE:
1016 rx_mgmt_action_sa_query_resp(wt, sta, mgmt, len, valid);
1017 break;
1018 default:
1019 add_note(wt, MSG_INFO, "Unexpected SA Query action value %u "
1020 "from " MACSTR,
1021 mgmt->u.action.u.sa_query_req.action,
1022 MAC2STR(mgmt->sa));
1023 }
1024 }
1025
1026
1027 static void rx_mgmt_action(struct wlantest *wt, const u8 *data, size_t len,
1028 int valid)
1029 {
1030 const struct ieee80211_mgmt *mgmt;
1031 struct wlantest_bss *bss;
1032 struct wlantest_sta *sta;
1033
1034 mgmt = (const struct ieee80211_mgmt *) data;
1035 if (mgmt->da[0] & 0x01) {
1036 add_note(wt, MSG_DEBUG, "Group addressed Action frame: DA="
1037 MACSTR " SA=" MACSTR " BSSID=" MACSTR
1038 " category=%u",
1039 MAC2STR(mgmt->da), MAC2STR(mgmt->sa),
1040 MAC2STR(mgmt->bssid), mgmt->u.action.category);
1041 return; /* Ignore group addressed Action frames for now */
1042 }
1043 bss = bss_get(wt, mgmt->bssid);
1044 if (bss == NULL)
1045 return;
1046 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
1047 sta = sta_get(bss, mgmt->da);
1048 else
1049 sta = sta_get(bss, mgmt->sa);
1050 if (sta == NULL)
1051 return;
1052
1053 if (len < 24 + 1) {
1054 add_note(wt, MSG_INFO, "Too short Action frame from " MACSTR,
1055 MAC2STR(mgmt->sa));
1056 return;
1057 }
1058
1059 wpa_printf(MSG_DEBUG, "ACTION " MACSTR " -> " MACSTR
1060 " (category=%u) (valid=%d)",
1061 MAC2STR(mgmt->sa), MAC2STR(mgmt->da),
1062 mgmt->u.action.category, valid);
1063 wpa_hexdump(MSG_MSGDUMP, "ACTION payload", data + 24, len - 24);
1064
1065 if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
1066 sta->state < STATE3) {
1067 add_note(wt, MSG_INFO, "Action frame sent when STA is not in "
1068 "State 3 (SA=" MACSTR " DATA=" MACSTR ")",
1069 MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
1070 }
1071
1072 switch (mgmt->u.action.category) {
1073 case WLAN_ACTION_SA_QUERY:
1074 rx_mgmt_action_sa_query(wt, sta, mgmt, len, valid);
1075 break;
1076 }
1077 }
1078
1079
1080 static int check_mmie_mic(unsigned int mgmt_group_cipher,
1081 const u8 *igtk, size_t igtk_len,
1082 const u8 *data, size_t len)
1083 {
1084 u8 *buf;
1085 u8 mic[16];
1086 u16 fc;
1087 const struct ieee80211_hdr *hdr;
1088 int ret, mic_len;
1089
1090 if (!mgmt_group_cipher || igtk_len < 16)
1091 return -1;
1092 mic_len = mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC ? 8 : 16;
1093
1094 if (len < 24 || len - 24 < mic_len)
1095 return -1;
1096
1097 buf = os_malloc(len + 20 - 24);
1098 if (buf == NULL)
1099 return -1;
1100
1101 /* BIP AAD: FC(masked) A1 A2 A3 */
1102 hdr = (const struct ieee80211_hdr *) data;
1103 fc = le_to_host16(hdr->frame_control);
1104 fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA);
1105 WPA_PUT_LE16(buf, fc);
1106 os_memcpy(buf + 2, hdr->addr1, 3 * ETH_ALEN);
1107
1108 /* Frame body with MMIE MIC masked to zero */
1109 os_memcpy(buf + 20, data + 24, len - 24 - mic_len);
1110 os_memset(buf + 20 + len - 24 - mic_len, 0, mic_len);
1111
1112 wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, len + 20 - 24);
1113 /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */
1114 if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
1115 ret = omac1_aes_128(igtk, buf, len + 20 - 24, mic);
1116 } else if (mgmt_group_cipher == WPA_CIPHER_BIP_CMAC_256) {
1117 ret = omac1_aes_256(igtk, buf, len + 20 - 24, mic);
1118 } else if (mgmt_group_cipher == WPA_CIPHER_BIP_GMAC_128 ||
1119 mgmt_group_cipher == WPA_CIPHER_BIP_GMAC_256) {
1120 u8 nonce[12], *npos;
1121 const u8 *ipn;
1122
1123 ipn = data + len - mic_len - 6;
1124
1125 /* Nonce: A2 | IPN */
1126 os_memcpy(nonce, hdr->addr2, ETH_ALEN);
1127 npos = nonce + ETH_ALEN;
1128 *npos++ = ipn[5];
1129 *npos++ = ipn[4];
1130 *npos++ = ipn[3];
1131 *npos++ = ipn[2];
1132 *npos++ = ipn[1];
1133 *npos++ = ipn[0];
1134
1135 ret = aes_gmac(igtk, igtk_len, nonce, sizeof(nonce),
1136 buf, len + 20 - 24, mic);
1137 } else {
1138 ret = -1;
1139 }
1140 if (ret < 0) {
1141 os_free(buf);
1142 return -1;
1143 }
1144
1145 os_free(buf);
1146
1147 if (os_memcmp(data + len - mic_len, mic, mic_len) != 0)
1148 return -1;
1149
1150 return 0;
1151 }
1152
1153
1154 static int check_bip(struct wlantest *wt, const u8 *data, size_t len)
1155 {
1156 const struct ieee80211_mgmt *mgmt;
1157 u16 fc, stype;
1158 const u8 *mmie;
1159 u16 keyid;
1160 struct wlantest_bss *bss;
1161 size_t mic_len;
1162
1163 mgmt = (const struct ieee80211_mgmt *) data;
1164 fc = le_to_host16(mgmt->frame_control);
1165 stype = WLAN_FC_GET_STYPE(fc);
1166
1167 if (stype == WLAN_FC_STYPE_ACTION) {
1168 if (len < 24 + 1)
1169 return 0;
1170 if (mgmt->u.action.category == WLAN_ACTION_PUBLIC)
1171 return 0; /* Not a robust management frame */
1172 }
1173
1174 bss = bss_get(wt, mgmt->bssid);
1175 if (bss == NULL)
1176 return 0; /* No key known yet */
1177
1178 mic_len = bss->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC ? 8 : 16;
1179
1180 if (len < 24 + 10 + mic_len ||
1181 data[len - (10 + mic_len)] != WLAN_EID_MMIE ||
1182 data[len - (10 + mic_len - 1)] != 8 + mic_len) {
1183 /* No MMIE */
1184 if (bss->rsn_capab & WPA_CAPABILITY_MFPC) {
1185 add_note(wt, MSG_INFO, "Robust group-addressed "
1186 "management frame sent without BIP by "
1187 MACSTR, MAC2STR(mgmt->sa));
1188 bss->counters[WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE]++;
1189 return -1;
1190 }
1191 return 0;
1192 }
1193
1194 mmie = data + len - (8 + mic_len);
1195 keyid = WPA_GET_LE16(mmie);
1196 if (keyid & 0xf000) {
1197 add_note(wt, MSG_INFO, "MMIE KeyID reserved bits not zero "
1198 "(%04x) from " MACSTR, keyid, MAC2STR(mgmt->sa));
1199 keyid &= 0x0fff;
1200 }
1201 if (keyid < 4 || keyid > 5) {
1202 add_note(wt, MSG_INFO, "Unexpected MMIE KeyID %u from " MACSTR,
1203 keyid, MAC2STR(mgmt->sa));
1204 bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
1205 return 0;
1206 }
1207 wpa_printf(MSG_DEBUG, "MMIE KeyID %u", keyid);
1208 wpa_hexdump(MSG_MSGDUMP, "MMIE IPN", mmie + 2, 6);
1209 wpa_hexdump(MSG_MSGDUMP, "MMIE MIC", mmie + 8, mic_len);
1210
1211 if (!bss->igtk_len[keyid]) {
1212 add_note(wt, MSG_DEBUG, "No IGTK known to validate BIP frame");
1213 return 0;
1214 }
1215
1216 if (os_memcmp(mmie + 2, bss->ipn[keyid], 6) <= 0) {
1217 add_note(wt, MSG_INFO, "BIP replay detected: SA=" MACSTR,
1218 MAC2STR(mgmt->sa));
1219 wpa_hexdump(MSG_INFO, "RX IPN", mmie + 2, 6);
1220 wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6);
1221 }
1222
1223 if (check_mmie_mic(bss->mgmt_group_cipher, bss->igtk[keyid],
1224 bss->igtk_len[keyid], data, len) < 0) {
1225 add_note(wt, MSG_INFO, "Invalid MMIE MIC in a frame from "
1226 MACSTR, MAC2STR(mgmt->sa));
1227 bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++;
1228 return -1;
1229 }
1230
1231 add_note(wt, MSG_DEBUG, "Valid MMIE MIC");
1232 os_memcpy(bss->ipn[keyid], mmie + 2, 6);
1233 bss->counters[WLANTEST_BSS_COUNTER_VALID_BIP_MMIE]++;
1234
1235 if (stype == WLAN_FC_STYPE_DEAUTH)
1236 bss->counters[WLANTEST_BSS_COUNTER_BIP_DEAUTH]++;
1237 else if (stype == WLAN_FC_STYPE_DISASSOC)
1238 bss->counters[WLANTEST_BSS_COUNTER_BIP_DISASSOC]++;
1239
1240 return 0;
1241 }
1242
1243
1244 static u8 * mgmt_ccmp_decrypt(struct wlantest *wt, const u8 *data, size_t len,
1245 size_t *dlen)
1246 {
1247 struct wlantest_bss *bss;
1248 struct wlantest_sta *sta;
1249 const struct ieee80211_hdr *hdr;
1250 int keyid;
1251 u8 *decrypted, *frame = NULL;
1252 u8 pn[6], *rsc;
1253
1254 hdr = (const struct ieee80211_hdr *) data;
1255 bss = bss_get(wt, hdr->addr3);
1256 if (bss == NULL)
1257 return NULL;
1258 if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
1259 sta = sta_get(bss, hdr->addr2);
1260 else
1261 sta = sta_get(bss, hdr->addr1);
1262 if (sta == NULL || !sta->ptk_set) {
1263 add_note(wt, MSG_MSGDUMP, "No PTK known to decrypt the frame");
1264 return NULL;
1265 }
1266
1267 if (len < 24 + 4)
1268 return NULL;
1269
1270 if (!(data[24 + 3] & 0x20)) {
1271 add_note(wt, MSG_INFO, "Expected CCMP frame from " MACSTR
1272 " did not have ExtIV bit set to 1",
1273 MAC2STR(hdr->addr2));
1274 return NULL;
1275 }
1276
1277 if (data[24 + 2] != 0 || (data[24 + 3] & 0x1f) != 0) {
1278 add_note(wt, MSG_INFO, "CCMP mgmt frame from " MACSTR " used "
1279 "non-zero reserved bit", MAC2STR(hdr->addr2));
1280 }
1281
1282 keyid = data[24 + 3] >> 6;
1283 if (keyid != 0) {
1284 add_note(wt, MSG_INFO, "Unexpected non-zero KeyID %d in "
1285 "individually addressed Management frame from "
1286 MACSTR, keyid, MAC2STR(hdr->addr2));
1287 }
1288
1289 if (os_memcmp(hdr->addr1, hdr->addr3, ETH_ALEN) == 0)
1290 rsc = sta->rsc_tods[16];
1291 else
1292 rsc = sta->rsc_fromds[16];
1293
1294 ccmp_get_pn(pn, data + 24);
1295 if (os_memcmp(pn, rsc, 6) <= 0) {
1296 u16 seq_ctrl = le_to_host16(hdr->seq_ctrl);
1297 add_note(wt, MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR
1298 " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u%s",
1299 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
1300 MAC2STR(hdr->addr3),
1301 WLAN_GET_SEQ_SEQ(seq_ctrl),
1302 WLAN_GET_SEQ_FRAG(seq_ctrl),
1303 (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ?
1304 " Retry" : "");
1305 wpa_hexdump(MSG_INFO, "RX PN", pn, 6);
1306 wpa_hexdump(MSG_INFO, "RSC", rsc, 6);
1307 }
1308
1309 decrypted = ccmp_decrypt(sta->ptk.tk, hdr, data + 24, len - 24, dlen);
1310 if (decrypted) {
1311 os_memcpy(rsc, pn, 6);
1312 frame = os_malloc(24 + *dlen);
1313 if (frame) {
1314 os_memcpy(frame, data, 24);
1315 os_memcpy(frame + 24, decrypted, *dlen);
1316 *dlen += 24;
1317 }
1318 } else {
1319 /* Assume the frame was corrupted and there was no FCS to check.
1320 * Allow retry of this particular frame to be processed so that
1321 * it could end up getting decrypted if it was received without
1322 * corruption. */
1323 sta->allow_duplicate = 1;
1324 }
1325
1326 os_free(decrypted);
1327
1328 return frame;
1329 }
1330
1331
1332 static int check_mgmt_ccmp(struct wlantest *wt, const u8 *data, size_t len)
1333 {
1334 const struct ieee80211_mgmt *mgmt;
1335 u16 fc;
1336 struct wlantest_bss *bss;
1337 struct wlantest_sta *sta;
1338
1339 mgmt = (const struct ieee80211_mgmt *) data;
1340 fc = le_to_host16(mgmt->frame_control);
1341
1342 if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) {
1343 if (len > 24 &&
1344 mgmt->u.action.category == WLAN_ACTION_PUBLIC)
1345 return 0; /* Not a robust management frame */
1346 }
1347
1348 bss = bss_get(wt, mgmt->bssid);
1349 if (bss == NULL)
1350 return 0;
1351 if (os_memcmp(mgmt->da, mgmt->bssid, ETH_ALEN) == 0)
1352 sta = sta_get(bss, mgmt->sa);
1353 else
1354 sta = sta_get(bss, mgmt->da);
1355 if (sta == NULL)
1356 return 0;
1357
1358 if ((sta->rsn_capab & WPA_CAPABILITY_MFPC) &&
1359 (sta->state == STATE3 ||
1360 WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION)) {
1361 add_note(wt, MSG_INFO, "Robust individually-addressed "
1362 "management frame sent without CCMP by "
1363 MACSTR, MAC2STR(mgmt->sa));
1364 return -1;
1365 }
1366
1367 return 0;
1368 }
1369
1370
1371 void rx_mgmt(struct wlantest *wt, const u8 *data, size_t len)
1372 {
1373 const struct ieee80211_hdr *hdr;
1374 u16 fc, stype;
1375 int valid = 1;
1376 u8 *decrypted = NULL;
1377 size_t dlen;
1378
1379 if (len < 24)
1380 return;
1381
1382 hdr = (const struct ieee80211_hdr *) data;
1383 fc = le_to_host16(hdr->frame_control);
1384 wt->rx_mgmt++;
1385 stype = WLAN_FC_GET_STYPE(fc);
1386
1387 if ((hdr->addr1[0] & 0x01) &&
1388 (stype == WLAN_FC_STYPE_DEAUTH ||
1389 stype == WLAN_FC_STYPE_DISASSOC ||
1390 stype == WLAN_FC_STYPE_ACTION)) {
1391 if (check_bip(wt, data, len) < 0)
1392 valid = 0;
1393 }
1394
1395 wpa_printf((stype == WLAN_FC_STYPE_BEACON ||
1396 stype == WLAN_FC_STYPE_PROBE_RESP ||
1397 stype == WLAN_FC_STYPE_PROBE_REQ) ?
1398 MSG_EXCESSIVE : MSG_MSGDUMP,
1399 "MGMT %s%s%s DA=" MACSTR " SA=" MACSTR " BSSID=" MACSTR,
1400 mgmt_stype(stype),
1401 fc & WLAN_FC_PWRMGT ? " PwrMgt" : "",
1402 fc & WLAN_FC_ISWEP ? " Prot" : "",
1403 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
1404 MAC2STR(hdr->addr3));
1405
1406 if ((fc & WLAN_FC_ISWEP) &&
1407 !(hdr->addr1[0] & 0x01) &&
1408 (stype == WLAN_FC_STYPE_DEAUTH ||
1409 stype == WLAN_FC_STYPE_DISASSOC ||
1410 stype == WLAN_FC_STYPE_ACTION)) {
1411 decrypted = mgmt_ccmp_decrypt(wt, data, len, &dlen);
1412 if (decrypted) {
1413 write_pcap_decrypted(wt, decrypted, dlen, NULL, 0);
1414 data = decrypted;
1415 len = dlen;
1416 } else
1417 valid = 0;
1418 }
1419
1420 if (!(fc & WLAN_FC_ISWEP) &&
1421 !(hdr->addr1[0] & 0x01) &&
1422 (stype == WLAN_FC_STYPE_DEAUTH ||
1423 stype == WLAN_FC_STYPE_DISASSOC ||
1424 stype == WLAN_FC_STYPE_ACTION)) {
1425 if (check_mgmt_ccmp(wt, data, len) < 0)
1426 valid = 0;
1427 }
1428
1429 switch (stype) {
1430 case WLAN_FC_STYPE_BEACON:
1431 rx_mgmt_beacon(wt, data, len);
1432 break;
1433 case WLAN_FC_STYPE_PROBE_RESP:
1434 rx_mgmt_probe_resp(wt, data, len);
1435 break;
1436 case WLAN_FC_STYPE_AUTH:
1437 rx_mgmt_auth(wt, data, len);
1438 break;
1439 case WLAN_FC_STYPE_DEAUTH:
1440 rx_mgmt_deauth(wt, data, len, valid);
1441 break;
1442 case WLAN_FC_STYPE_ASSOC_REQ:
1443 rx_mgmt_assoc_req(wt, data, len);
1444 break;
1445 case WLAN_FC_STYPE_ASSOC_RESP:
1446 rx_mgmt_assoc_resp(wt, data, len);
1447 break;
1448 case WLAN_FC_STYPE_REASSOC_REQ:
1449 rx_mgmt_reassoc_req(wt, data, len);
1450 break;
1451 case WLAN_FC_STYPE_REASSOC_RESP:
1452 rx_mgmt_reassoc_resp(wt, data, len);
1453 break;
1454 case WLAN_FC_STYPE_DISASSOC:
1455 rx_mgmt_disassoc(wt, data, len, valid);
1456 break;
1457 case WLAN_FC_STYPE_ACTION:
1458 rx_mgmt_action(wt, data, len, valid);
1459 break;
1460 }
1461
1462 os_free(decrypted);
1463
1464 wt->last_mgmt_valid = valid;
1465 }
1466
1467
1468 static void rx_mgmt_deauth_ack(struct wlantest *wt,
1469 const struct ieee80211_hdr *hdr)
1470 {
1471 const struct ieee80211_mgmt *mgmt;
1472 struct wlantest_bss *bss;
1473 struct wlantest_sta *sta;
1474
1475 mgmt = (const struct ieee80211_mgmt *) hdr;
1476 bss = bss_get(wt, mgmt->bssid);
1477 if (bss == NULL)
1478 return;
1479 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
1480 sta = sta_get(bss, mgmt->da);
1481 else
1482 sta = sta_get(bss, mgmt->sa);
1483 if (sta == NULL)
1484 return;
1485
1486 add_note(wt, MSG_DEBUG, "DEAUTH from " MACSTR " acknowledged by "
1487 MACSTR, MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
1488 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
1489 int c;
1490 c = wt->last_mgmt_valid ?
1491 WLANTEST_STA_COUNTER_VALID_DEAUTH_RX_ACK :
1492 WLANTEST_STA_COUNTER_INVALID_DEAUTH_RX_ACK;
1493 sta->counters[c]++;
1494 }
1495 }
1496
1497
1498 static void rx_mgmt_disassoc_ack(struct wlantest *wt,
1499 const struct ieee80211_hdr *hdr)
1500 {
1501 const struct ieee80211_mgmt *mgmt;
1502 struct wlantest_bss *bss;
1503 struct wlantest_sta *sta;
1504
1505 mgmt = (const struct ieee80211_mgmt *) hdr;
1506 bss = bss_get(wt, mgmt->bssid);
1507 if (bss == NULL)
1508 return;
1509 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0)
1510 sta = sta_get(bss, mgmt->da);
1511 else
1512 sta = sta_get(bss, mgmt->sa);
1513 if (sta == NULL)
1514 return;
1515
1516 add_note(wt, MSG_DEBUG, "DISASSOC from " MACSTR " acknowledged by "
1517 MACSTR, MAC2STR(mgmt->sa), MAC2STR(mgmt->da));
1518 if (os_memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN) == 0) {
1519 int c;
1520 c = wt->last_mgmt_valid ?
1521 WLANTEST_STA_COUNTER_VALID_DISASSOC_RX_ACK :
1522 WLANTEST_STA_COUNTER_INVALID_DISASSOC_RX_ACK;
1523 sta->counters[c]++;
1524 }
1525 }
1526
1527
1528 void rx_mgmt_ack(struct wlantest *wt, const struct ieee80211_hdr *hdr)
1529 {
1530 u16 fc, stype;
1531 fc = le_to_host16(hdr->frame_control);
1532 stype = WLAN_FC_GET_STYPE(fc);
1533
1534 wpa_printf(MSG_MSGDUMP, "MGMT ACK: stype=%u a1=" MACSTR " a2=" MACSTR
1535 " a3=" MACSTR,
1536 stype, MAC2STR(hdr->addr1), MAC2STR(hdr->addr2),
1537 MAC2STR(hdr->addr3));
1538
1539 switch (stype) {
1540 case WLAN_FC_STYPE_DEAUTH:
1541 rx_mgmt_deauth_ack(wt, hdr);
1542 break;
1543 case WLAN_FC_STYPE_DISASSOC:
1544 rx_mgmt_disassoc_ack(wt, hdr);
1545 break;
1546 }
1547 }