blob: 2e6d9a7d4b6173bfc73ab88e7ea543d0fd95e157 [file] [log] [blame]
Hai Shalom60840252021-02-19 19:02:11 -08001/*
2 * wpa_supplicant - PASN processing
3 *
4 * Copyright (C) 2019 Intel Corporation
5 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10#include "includes.h"
11
12#include "common/ieee802_11_defs.h"
13#include "common/ieee802_11_common.h"
14#include "common/dragonfly.h"
15#include "common/ptksa_cache.h"
16#include "utils/eloop.h"
17#include "drivers/driver.h"
18#include "crypto/crypto.h"
19#include "crypto/random.h"
20#include "eap_common/eap_defs.h"
21#include "rsn_supp/wpa.h"
22#include "rsn_supp/pmksa_cache.h"
23#include "wpa_supplicant_i.h"
24#include "driver_i.h"
25#include "bss.h"
Sunil Ravi89eba102022-09-13 21:04:37 -070026#include "scan.h"
Hai Shalom60840252021-02-19 19:02:11 -080027#include "config.h"
28
29static const int dot11RSNAConfigPMKLifetime = 43200;
30
31struct wpa_pasn_auth_work {
Sunil Ravi89eba102022-09-13 21:04:37 -070032 u8 own_addr[ETH_ALEN];
Hai Shalom60840252021-02-19 19:02:11 -080033 u8 bssid[ETH_ALEN];
34 int akmp;
35 int cipher;
36 u16 group;
37 int network_id;
Hai Shaloma20dcd72022-02-04 13:43:00 -080038 struct wpabuf *comeback;
Hai Shalom60840252021-02-19 19:02:11 -080039};
40
41
Hai Shaloma20dcd72022-02-04 13:43:00 -080042static void wpas_pasn_free_auth_work(struct wpa_pasn_auth_work *awork)
43{
44 wpabuf_free(awork->comeback);
45 awork->comeback = NULL;
46 os_free(awork);
47}
48
49
Hai Shalom60840252021-02-19 19:02:11 -080050static void wpas_pasn_auth_work_timeout(void *eloop_ctx, void *timeout_ctx)
51{
52 struct wpa_supplicant *wpa_s = eloop_ctx;
53
54 wpa_printf(MSG_DEBUG, "PASN: Auth work timeout - stopping auth");
55
56 wpas_pasn_auth_stop(wpa_s);
Sunil Ravi89eba102022-09-13 21:04:37 -070057
58 wpas_pasn_auth_work_done(wpa_s, PASN_STATUS_FAILURE);
Hai Shalom60840252021-02-19 19:02:11 -080059}
60
61
62static void wpas_pasn_cancel_auth_work(struct wpa_supplicant *wpa_s)
63{
64 wpa_printf(MSG_DEBUG, "PASN: Cancel pasn-start-auth work");
65
66 /* Remove pending/started work */
67 radio_remove_works(wpa_s, "pasn-start-auth", 0);
68}
69
70
71static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid,
Hai Shaloma20dcd72022-02-04 13:43:00 -080072 int akmp, int cipher, u8 status,
73 struct wpabuf *comeback,
74 u16 comeback_after)
Hai Shalom60840252021-02-19 19:02:11 -080075{
Hai Shaloma20dcd72022-02-04 13:43:00 -080076 if (comeback) {
77 size_t comeback_len = wpabuf_len(comeback);
78 size_t buflen = comeback_len * 2 + 1;
79 char *comeback_txt = os_malloc(buflen);
80
81 if (comeback_txt) {
82 wpa_snprintf_hex(comeback_txt, buflen,
83 wpabuf_head(comeback), comeback_len);
84
85 wpa_msg(wpa_s, MSG_INFO, PASN_AUTH_STATUS MACSTR
86 " akmp=%s, status=%u comeback_after=%u comeback=%s",
87 MAC2STR(bssid),
88 wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
89 status, comeback_after, comeback_txt);
90
91 os_free(comeback_txt);
92 return;
93 }
94 }
95
Hai Shalom60840252021-02-19 19:02:11 -080096 wpa_msg(wpa_s, MSG_INFO,
97 PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u",
98 MAC2STR(bssid), wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
99 status);
100}
101
102
103#ifdef CONFIG_SAE
104
105static struct wpabuf * wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
106{
107 struct wpas_pasn *pasn = &wpa_s->pasn;
108 struct wpabuf *buf = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800109 int ret;
110
Hai Shalom60840252021-02-19 19:02:11 -0800111 ret = sae_set_group(&pasn->sae, pasn->group);
112 if (ret) {
113 wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
114 return NULL;
115 }
116
Hai Shaloma20dcd72022-02-04 13:43:00 -0800117 ret = sae_prepare_commit_pt(&pasn->sae, pasn->ssid->pt,
Sunil Ravi89eba102022-09-13 21:04:37 -0700118 pasn->own_addr, pasn->bssid,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800119 NULL, NULL);
Hai Shalom60840252021-02-19 19:02:11 -0800120 if (ret) {
121 wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
122 return NULL;
123 }
124
125 /* Need to add the entire Authentication frame body */
126 buf = wpabuf_alloc(6 + SAE_COMMIT_MAX_LEN);
127 if (!buf) {
128 wpa_printf(MSG_DEBUG, "PASN: Failed to allocate SAE buffer");
129 return NULL;
130 }
131
132 wpabuf_put_le16(buf, WLAN_AUTH_SAE);
133 wpabuf_put_le16(buf, 1);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800134 wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
Hai Shalom60840252021-02-19 19:02:11 -0800135
136 sae_write_commit(&pasn->sae, buf, NULL, 0);
137 pasn->sae.state = SAE_COMMITTED;
138
139 return buf;
140}
141
142
143static int wpas_pasn_wd_sae_rx(struct wpa_supplicant *wpa_s, struct wpabuf *wd)
144{
145 struct wpas_pasn *pasn = &wpa_s->pasn;
146 const u8 *data;
147 size_t buf_len;
148 u16 len, res, alg, seq, status;
149 int groups[] = { pasn->group, 0 };
150 int ret;
151
152 if (!wd)
153 return -1;
154
155 data = wpabuf_head_u8(wd);
156 buf_len = wpabuf_len(wd);
157
158 /* first handle the commit message */
159 if (buf_len < 2) {
160 wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short (commit)");
161 return -1;
162 }
163
164 len = WPA_GET_LE16(data);
165 if (len < 6 || buf_len - 2 < len) {
166 wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short for commit");
167 return -1;
168 }
169
170 buf_len -= 2;
171 data += 2;
172
173 alg = WPA_GET_LE16(data);
174 seq = WPA_GET_LE16(data + 2);
175 status = WPA_GET_LE16(data + 4);
176
177 wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u",
178 alg, seq, status);
179
Hai Shaloma20dcd72022-02-04 13:43:00 -0800180 if (alg != WLAN_AUTH_SAE || seq != 1 ||
181 status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
Hai Shalom60840252021-02-19 19:02:11 -0800182 wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
183 return -1;
184 }
185
186 res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800187 1);
Hai Shalom60840252021-02-19 19:02:11 -0800188 if (res != WLAN_STATUS_SUCCESS) {
189 wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
190 return -1;
191 }
192
193 /* Process the commit message and derive the PMK */
194 ret = sae_process_commit(&pasn->sae);
195 if (ret) {
196 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer commit");
197 return -1;
198 }
199
200 buf_len -= len;
201 data += len;
202
203 /* Handle the confirm message */
204 if (buf_len < 2) {
205 wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short (confirm)");
206 return -1;
207 }
208
209 len = WPA_GET_LE16(data);
210 if (len < 6 || buf_len - 2 < len) {
211 wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short for confirm");
212 return -1;
213 }
214
215 buf_len -= 2;
216 data += 2;
217
218 alg = WPA_GET_LE16(data);
219 seq = WPA_GET_LE16(data + 2);
220 status = WPA_GET_LE16(data + 4);
221
222 wpa_printf(MSG_DEBUG, "PASN: SAE confirm: alg=%u, seq=%u, status=%u",
223 alg, seq, status);
224
225 if (alg != WLAN_AUTH_SAE || seq != 2 || status != WLAN_STATUS_SUCCESS) {
226 wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE confirm");
227 return -1;
228 }
229
230 res = sae_check_confirm(&pasn->sae, data + 6, len - 6);
231 if (res != WLAN_STATUS_SUCCESS) {
232 wpa_printf(MSG_DEBUG, "PASN: SAE failed checking confirm");
233 return -1;
234 }
235
236 wpa_printf(MSG_DEBUG, "PASN: SAE completed successfully");
237 pasn->sae.state = SAE_ACCEPTED;
238
239 return 0;
240}
241
242
243static struct wpabuf * wpas_pasn_wd_sae_confirm(struct wpa_supplicant *wpa_s)
244{
245 struct wpas_pasn *pasn = &wpa_s->pasn;
246 struct wpabuf *buf = NULL;
247
248 /* Need to add the entire authentication frame body */
249 buf = wpabuf_alloc(6 + SAE_CONFIRM_MAX_LEN);
250 if (!buf) {
251 wpa_printf(MSG_DEBUG, "PASN: Failed to allocate SAE buffer");
252 return NULL;
253 }
254
255 wpabuf_put_le16(buf, WLAN_AUTH_SAE);
256 wpabuf_put_le16(buf, 2);
257 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
258
259 sae_write_confirm(&pasn->sae, buf);
260 pasn->sae.state = SAE_CONFIRMED;
261
262 return buf;
263}
264
Hai Shaloma20dcd72022-02-04 13:43:00 -0800265
266static int wpas_pasn_sae_setup_pt(struct wpa_supplicant *wpa_s,
267 struct wpa_ssid *ssid, int group)
268{
269 const char *password = ssid->sae_password;
270 int groups[2] = { group, 0 };
271
272 if (!password)
273 password = ssid->passphrase;
274
275 if (!password) {
276 wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
277 return -1;
278 }
279
280 if (ssid->pt)
281 return 0; /* PT already derived */
282
283 ssid->pt = sae_derive_pt(groups, ssid->ssid, ssid->ssid_len,
284 (const u8 *) password, os_strlen(password),
285 ssid->sae_password_id);
286
287 return ssid->pt ? 0 : -1;
288}
289
Hai Shalom60840252021-02-19 19:02:11 -0800290#endif /* CONFIG_SAE */
291
292
Sunil Ravi89eba102022-09-13 21:04:37 -0700293static int wpas_pasn_get_params_from_bss(struct wpa_supplicant *wpa_s,
294 struct pasn_peer *peer)
295{
296 int ret;
297 const u8 *rsne, *rsnxe;
298 struct wpa_bss *bss;
299 struct wpa_ie_data rsne_data;
300 int sel, key_mgmt, pairwise_cipher;
301 int network_id = 0, group = 19;
302 struct wpa_ssid *ssid = NULL;
303 size_t ssid_str_len = 0;
304 const u8 *ssid_str = NULL;
305 const u8 *bssid = peer->peer_addr;
306
307 bss = wpa_bss_get_bssid(wpa_s, bssid);
308 if (!bss) {
309 wpa_supplicant_update_scan_results(wpa_s);
310 bss = wpa_bss_get_bssid(wpa_s, bssid);
311 if (!bss) {
312 wpa_printf(MSG_DEBUG, "PASN: BSS not found");
313 return -1;
314 }
315 }
316
317 rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
318 if (!rsne) {
319 wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
320 return -1;
321 }
322
323 ret = wpa_parse_wpa_ie(rsne, *(rsne + 1) + 2, &rsne_data);
324 if (ret) {
325 wpa_printf(MSG_DEBUG, "PASN: Failed parsing RSNE data");
326 return -1;
327 }
328
329 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
330
331 ssid_str_len = bss->ssid_len;
332 ssid_str = bss->ssid;
333
334 /* Get the network configuration based on the obtained SSID */
335 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
336 if (!wpas_network_disabled(wpa_s, ssid) &&
337 ssid_str_len == ssid->ssid_len &&
338 os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0)
339 break;
340 }
341
342 if (ssid)
343 network_id = ssid->id;
344
345 sel = rsne_data.pairwise_cipher;
346 if (ssid && ssid->pairwise_cipher)
347 sel &= ssid->pairwise_cipher;
348
349 wpa_printf(MSG_DEBUG, "PASN: peer pairwise 0x%x, select 0x%x",
350 rsne_data.pairwise_cipher, sel);
351
352 pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1);
353 if (pairwise_cipher < 0) {
354 wpa_msg(wpa_s, MSG_WARNING,
355 "PASN: Failed to select pairwise cipher");
356 return -1;
357 }
358
359 sel = rsne_data.key_mgmt;
360 if (ssid && ssid->key_mgmt)
361 sel &= ssid->key_mgmt;
362
363 wpa_printf(MSG_DEBUG, "PASN: peer AKMP 0x%x, select 0x%x",
364 rsne_data.key_mgmt, sel);
365#ifdef CONFIG_SAE
366 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE) || !ssid)
367 sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_SAE_EXT_KEY |
368 WPA_KEY_MGMT_FT_SAE | WPA_KEY_MGMT_FT_SAE_EXT_KEY);
369#endif /* CONFIG_SAE */
370#ifdef CONFIG_IEEE80211R
371 if (!(wpa_s->drv_flags & (WPA_DRIVER_FLAGS_SME |
372 WPA_DRIVER_FLAGS_UPDATE_FT_IES)))
373 sel &= ~WPA_KEY_MGMT_FT;
374#endif /* CONFIG_IEEE80211R */
375 if (0) {
376#ifdef CONFIG_IEEE80211R
377#ifdef CONFIG_SHA384
378 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) &&
379 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
380 key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
381 wpa_printf(MSG_DEBUG, "PASN: using KEY_MGMT FT/802.1X-SHA384");
382 if (ssid && !ssid->ft_eap_pmksa_caching &&
383 pmksa_cache_get_current(wpa_s->wpa)) {
384 /* PMKSA caching with FT may have interoperability
385 * issues, so disable that case by default for now.
386 */
387 wpa_printf(MSG_DEBUG,
388 "PASN: Disable PMKSA caching for FT/802.1X connection");
389 pmksa_cache_clear_current(wpa_s->wpa);
390 }
391#endif /* CONFIG_SHA384 */
392#endif /* CONFIG_IEEE80211R */
393#ifdef CONFIG_SAE
394 } else if ((sel & WPA_KEY_MGMT_SAE_EXT_KEY) &&
395 (ieee802_11_rsnx_capab(rsnxe,
396 WLAN_RSNX_CAPAB_SAE_H2E)) &&
397 (wpas_pasn_sae_setup_pt(wpa_s, ssid, group) == 0)) {
398 key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
399 wpa_printf(MSG_DEBUG, "PASN: using KEY_MGMT SAE (ext key)");
400 } else if ((sel & WPA_KEY_MGMT_SAE) &&
401 (ieee802_11_rsnx_capab(rsnxe,
402 WLAN_RSNX_CAPAB_SAE_H2E)) &&
403 (wpas_pasn_sae_setup_pt(wpa_s, ssid, group) == 0)) {
404 key_mgmt = WPA_KEY_MGMT_SAE;
405 wpa_printf(MSG_DEBUG, "PASN: using KEY_MGMT SAE");
406#endif /* CONFIG_SAE */
407#ifdef CONFIG_FILS
408 } else if (sel & WPA_KEY_MGMT_FILS_SHA384) {
409 key_mgmt = WPA_KEY_MGMT_FILS_SHA384;
410 wpa_printf(MSG_DEBUG, "PASN: using KEY_MGMT FILS-SHA384");
411 } else if (sel & WPA_KEY_MGMT_FILS_SHA256) {
412 key_mgmt = WPA_KEY_MGMT_FILS_SHA256;
413 wpa_printf(MSG_DEBUG, "PASN: using KEY_MGMT FILS-SHA256");
414#endif /* CONFIG_FILS */
415#ifdef CONFIG_IEEE80211R
416 } else if ((sel & WPA_KEY_MGMT_FT_IEEE8021X) &&
417 os_strcmp(wpa_supplicant_get_eap_mode(wpa_s), "LEAP") != 0) {
418 key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
419 wpa_printf(MSG_DEBUG, "PASN: using KEY_MGMT FT/802.1X");
420 if (ssid && !ssid->ft_eap_pmksa_caching &&
421 pmksa_cache_get_current(wpa_s->wpa)) {
422 /* PMKSA caching with FT may have interoperability
423 * issues, so disable that case by default for now.
424 */
425 wpa_printf(MSG_DEBUG,
426 "PASN: Disable PMKSA caching for FT/802.1X connection");
427 pmksa_cache_clear_current(wpa_s->wpa);
428 }
429 } else if (sel & WPA_KEY_MGMT_FT_PSK) {
430 key_mgmt = WPA_KEY_MGMT_FT_PSK;
431 wpa_printf(MSG_DEBUG, "PASN: using KEY_MGMT FT/PSK");
432#endif /* CONFIG_IEEE80211R */
433 } else if (sel & WPA_KEY_MGMT_PASN) {
434 key_mgmt = WPA_KEY_MGMT_PASN;
435 wpa_printf(MSG_DEBUG, "PASN: using KEY_MGMT PASN");
436 } else {
437 wpa_printf(MSG_DEBUG, "PASN: invalid AKMP");
438 return -1;
439 }
440
441 peer->akmp = key_mgmt;
442 peer->cipher = pairwise_cipher;
443 peer->network_id = network_id;
444 peer->group = group;
445 return 0;
446}
447
448
449static int wpas_pasn_set_keys_from_cache(struct wpa_supplicant *wpa_s,
450 const u8 *own_addr, const u8 *bssid,
451 int cipher, int akmp)
452{
453 struct ptksa_cache_entry *entry;
454
455 entry = ptksa_cache_get(wpa_s->ptksa, bssid, cipher);
456 if (!entry) {
457 wpa_printf(MSG_DEBUG, "PASN: peer " MACSTR
458 " not present in PTKSA cache", MAC2STR(bssid));
459 return -1;
460 }
461
462 if (os_memcmp(entry->own_addr, own_addr, ETH_ALEN) != 0) {
463 wpa_printf(MSG_DEBUG,
464 "PASN: own addr " MACSTR " and PTKSA entry own addr "
465 MACSTR " differ",
466 MAC2STR(own_addr), MAC2STR(entry->own_addr));
467 return -1;
468 }
469
470 wpa_printf(MSG_DEBUG, "PASN: " MACSTR " present in PTKSA cache",
471 MAC2STR(bssid));
472 wpa_drv_set_secure_ranging_ctx(wpa_s, own_addr, bssid, cipher,
473 entry->ptk.tk_len,
474 entry->ptk.tk,
475 entry->ptk.ltf_keyseed_len,
476 entry->ptk.ltf_keyseed, 0);
477 return 0;
478}
479
480
481static void wpas_pasn_configure_next_peer(struct wpa_supplicant *wpa_s,
482 struct pasn_auth *pasn_params)
483{
484 struct pasn_peer *peer;
485 u8 comeback_len = 0;
486 const u8 *comeback = NULL;
487
488 if (!pasn_params)
489 return;
490
491 while (wpa_s->pasn_count < pasn_params->num_peers) {
492 peer = &pasn_params->peer[wpa_s->pasn_count];
493
494 if (os_memcmp(wpa_s->bssid, peer->peer_addr, ETH_ALEN) == 0) {
495 wpa_printf(MSG_DEBUG,
496 "PASN: Associated peer is not expected");
497 peer->status = PASN_STATUS_FAILURE;
498 wpa_s->pasn_count++;
499 continue;
500 }
501
502 if (wpas_pasn_set_keys_from_cache(wpa_s, peer->own_addr,
503 peer->peer_addr,
504 peer->cipher,
505 peer->akmp) == 0) {
506 peer->status = PASN_STATUS_SUCCESS;
507 wpa_s->pasn_count++;
508 continue;
509 }
510
511 if (wpas_pasn_get_params_from_bss(wpa_s, peer)) {
512 peer->status = PASN_STATUS_FAILURE;
513 wpa_s->pasn_count++;
514 continue;
515 }
516
517 if (wpas_pasn_auth_start(wpa_s, peer->own_addr,
518 peer->peer_addr, peer->akmp,
519 peer->cipher, peer->group,
520 peer->network_id,
521 comeback, comeback_len)) {
522 peer->status = PASN_STATUS_FAILURE;
523 wpa_s->pasn_count++;
524 continue;
525 }
526 wpa_printf(MSG_DEBUG, "PASN: Sent PASN auth start for " MACSTR,
527 MAC2STR(peer->peer_addr));
528 return;
529 }
530
531 if (wpa_s->pasn_count == pasn_params->num_peers) {
532 wpa_drv_send_pasn_resp(wpa_s, pasn_params);
533 wpa_printf(MSG_DEBUG, "PASN: Response sent");
534 os_free(wpa_s->pasn_params);
535 wpa_s->pasn_params = NULL;
536 }
537}
538
539
540void wpas_pasn_auth_work_done(struct wpa_supplicant *wpa_s, int status)
541{
542 if (!wpa_s->pasn_params)
543 return;
544
545 wpa_s->pasn_params->peer[wpa_s->pasn_count].status = status;
546 wpa_s->pasn_count++;
547 wpas_pasn_configure_next_peer(wpa_s, wpa_s->pasn_params);
548}
549
550
551static void wpas_pasn_delete_peers(struct wpa_supplicant *wpa_s,
552 struct pasn_auth *pasn_params)
553{
554 struct pasn_peer *peer;
555 unsigned int i;
556
557 if (!pasn_params)
558 return;
559
560 for (i = 0; i < pasn_params->num_peers; i++) {
561 peer = &pasn_params->peer[i];
562 wpas_pasn_deauthenticate(wpa_s, peer->own_addr,
563 peer->peer_addr);
564 }
565}
566
567
Hai Shalom60840252021-02-19 19:02:11 -0800568#ifdef CONFIG_FILS
569
570static struct wpabuf * wpas_pasn_fils_build_auth(struct wpa_supplicant *wpa_s)
571{
572 struct wpas_pasn *pasn = &wpa_s->pasn;
573 struct wpabuf *buf = NULL;
574 struct wpabuf *erp_msg;
575 int ret;
576
577 erp_msg = eapol_sm_build_erp_reauth_start(wpa_s->eapol);
578 if (!erp_msg) {
579 wpa_printf(MSG_DEBUG,
580 "PASN: FILS: ERP EAP-Initiate/Re-auth unavailable");
581 return NULL;
582 }
583
584 if (random_get_bytes(pasn->fils.nonce, FILS_NONCE_LEN) < 0 ||
585 random_get_bytes(pasn->fils.session, FILS_SESSION_LEN) < 0)
586 goto fail;
587
588 wpa_hexdump(MSG_DEBUG, "PASN: FILS: Nonce", pasn->fils.nonce,
589 FILS_NONCE_LEN);
590
591 wpa_hexdump(MSG_DEBUG, "PASN: FILS: Session", pasn->fils.session,
592 FILS_SESSION_LEN);
593
594 buf = wpabuf_alloc(1500);
595 if (!buf)
596 goto fail;
597
598 /* Add the authentication algorithm */
599 wpabuf_put_le16(buf, WLAN_AUTH_FILS_SK);
600
601 /* Authentication Transaction seq# */
602 wpabuf_put_le16(buf, 1);
603
604 /* Status Code */
605 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
606
607 /* Own RSNE */
608 wpa_pasn_add_rsne(buf, NULL, pasn->akmp, pasn->cipher);
609
610 /* FILS Nonce */
611 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
612 wpabuf_put_u8(buf, 1 + FILS_NONCE_LEN);
613 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_NONCE);
614 wpabuf_put_data(buf, pasn->fils.nonce, FILS_NONCE_LEN);
615
616 /* FILS Session */
617 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
618 wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN);
619 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
620 wpabuf_put_data(buf, pasn->fils.session, FILS_SESSION_LEN);
621
622 /* Wrapped Data (ERP) */
623 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
624 wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg));
625 wpabuf_put_u8(buf, WLAN_EID_EXT_WRAPPED_DATA);
626 wpabuf_put_buf(buf, erp_msg);
627
628 /*
629 * Calculate pending PMKID here so that we do not need to maintain a
630 * copy of the EAP-Initiate/Reauth message.
631 */
632 ret = fils_pmkid_erp(pasn->akmp, wpabuf_head(erp_msg),
633 wpabuf_len(erp_msg),
634 pasn->fils.erp_pmkid);
635 if (ret) {
636 wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to get ERP PMKID");
637 goto fail;
638 }
639
640 wpabuf_free(erp_msg);
641 erp_msg = NULL;
642
643 wpa_hexdump_buf(MSG_DEBUG, "PASN: FILS: Authentication frame", buf);
644 return buf;
645fail:
646 wpabuf_free(erp_msg);
647 wpabuf_free(buf);
648 return NULL;
649}
650
651
652static void wpas_pasn_initiate_eapol(struct wpa_supplicant *wpa_s)
653{
654 struct wpas_pasn *pasn = &wpa_s->pasn;
655 struct eapol_config eapol_conf;
656 struct wpa_ssid *ssid = pasn->ssid;
657
658 wpa_printf(MSG_DEBUG, "PASN: FILS: Initiating EAPOL");
659
660 eapol_sm_notify_eap_success(wpa_s->eapol, false);
661 eapol_sm_notify_eap_fail(wpa_s->eapol, false);
662 eapol_sm_notify_portControl(wpa_s->eapol, Auto);
663
664 os_memset(&eapol_conf, 0, sizeof(eapol_conf));
665 eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
666 eapol_conf.workaround = ssid->eap_workaround;
667
668 eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
669}
670
671
672static struct wpabuf * wpas_pasn_wd_fils_auth(struct wpa_supplicant *wpa_s)
673{
674 struct wpas_pasn *pasn = &wpa_s->pasn;
675 struct wpa_bss *bss;
676 const u8 *indic;
677 u16 fils_info;
678
679 wpa_printf(MSG_DEBUG, "PASN: FILS: wrapped data - completed=%u",
680 pasn->fils.completed);
681
682 /* Nothing to add as we are done */
683 if (pasn->fils.completed)
684 return NULL;
685
686 if (!pasn->ssid) {
687 wpa_printf(MSG_DEBUG, "PASN: FILS: No network block");
688 return NULL;
689 }
690
691 bss = wpa_bss_get_bssid(wpa_s, pasn->bssid);
692 if (!bss) {
693 wpa_printf(MSG_DEBUG, "PASN: FILS: BSS not found");
694 return NULL;
695 }
696
697 indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
698 if (!indic || indic[1] < 2) {
699 wpa_printf(MSG_DEBUG, "PASN: Missing FILS Indication IE");
700 return NULL;
701 }
702
703 fils_info = WPA_GET_LE16(indic + 2);
704 if (!(fils_info & BIT(9))) {
705 wpa_printf(MSG_DEBUG,
706 "PASN: FILS auth without PFS not supported");
707 return NULL;
708 }
709
710 wpas_pasn_initiate_eapol(wpa_s);
711
712 return wpas_pasn_fils_build_auth(wpa_s);
713}
714
715
716static int wpas_pasn_wd_fils_rx(struct wpa_supplicant *wpa_s, struct wpabuf *wd)
717{
718 struct wpas_pasn *pasn = &wpa_s->pasn;
719 struct ieee802_11_elems elems;
720 struct wpa_ie_data rsne_data;
721 u8 rmsk[ERP_MAX_KEY_LEN];
722 size_t rmsk_len;
723 u8 anonce[FILS_NONCE_LEN];
724 const u8 *data;
725 size_t buf_len;
726 struct wpabuf *fils_wd = NULL;
727 u16 alg, seq, status;
728 int ret;
729
730 if (!wd)
731 return -1;
732
733 data = wpabuf_head(wd);
734 buf_len = wpabuf_len(wd);
735
736 wpa_hexdump(MSG_DEBUG, "PASN: FILS: Authentication frame len=%zu",
737 data, buf_len);
738
739 /* first handle the header */
740 if (buf_len < 6) {
741 wpa_printf(MSG_DEBUG, "PASN: FILS: Buffer too short");
742 return -1;
743 }
744
745 alg = WPA_GET_LE16(data);
746 seq = WPA_GET_LE16(data + 2);
747 status = WPA_GET_LE16(data + 4);
748
749 wpa_printf(MSG_DEBUG, "PASN: FILS: commit: alg=%u, seq=%u, status=%u",
750 alg, seq, status);
751
752 if (alg != WLAN_AUTH_FILS_SK || seq != 2 ||
753 status != WLAN_STATUS_SUCCESS) {
754 wpa_printf(MSG_DEBUG,
755 "PASN: FILS: Dropping peer authentication");
756 return -1;
757 }
758
759 data += 6;
760 buf_len -= 6;
761
762 if (ieee802_11_parse_elems(data, buf_len, &elems, 1) == ParseFailed) {
763 wpa_printf(MSG_DEBUG, "PASN: FILS: Could not parse elements");
764 return -1;
765 }
766
767 if (!elems.rsn_ie || !elems.fils_nonce || !elems.fils_nonce ||
768 !elems.wrapped_data) {
769 wpa_printf(MSG_DEBUG, "PASN: FILS: Missing IEs");
770 return -1;
771 }
772
773 ret = wpa_parse_wpa_ie(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
774 &rsne_data);
775 if (ret) {
776 wpa_printf(MSG_DEBUG, "PASN: FILS: Failed parsing RNSE");
777 return -1;
778 }
779
780 ret = wpa_pasn_validate_rsne(&rsne_data);
781 if (ret) {
782 wpa_printf(MSG_DEBUG, "PASN: FILS: Failed validating RSNE");
783 return -1;
784 }
785
786 if (rsne_data.num_pmkid) {
787 wpa_printf(MSG_DEBUG,
788 "PASN: FILS: Not expecting PMKID in RSNE");
789 return -1;
790 }
791
792 wpa_hexdump(MSG_DEBUG, "PASN: FILS: ANonce", elems.fils_nonce,
793 FILS_NONCE_LEN);
794 os_memcpy(anonce, elems.fils_nonce, FILS_NONCE_LEN);
795
796 wpa_hexdump(MSG_DEBUG, "PASN: FILS: FILS Session", elems.fils_session,
797 FILS_SESSION_LEN);
798
799 if (os_memcmp(pasn->fils.session, elems.fils_session,
800 FILS_SESSION_LEN)) {
801 wpa_printf(MSG_DEBUG, "PASN: FILS: Session mismatch");
802 return -1;
803 }
804
805 fils_wd = ieee802_11_defrag(&elems, WLAN_EID_EXTENSION,
806 WLAN_EID_EXT_WRAPPED_DATA);
807
808 if (!fils_wd) {
809 wpa_printf(MSG_DEBUG,
810 "PASN: FILS: Failed getting wrapped data");
811 return -1;
812 }
813
814 eapol_sm_process_erp_finish(wpa_s->eapol, wpabuf_head(fils_wd),
815 wpabuf_len(fils_wd));
816
817 wpabuf_free(fils_wd);
818 fils_wd = NULL;
819
820 if (eapol_sm_failed(wpa_s->eapol)) {
821 wpa_printf(MSG_DEBUG, "PASN: FILS: ERP finish failed");
822 return -1;
823 }
824
825 rmsk_len = ERP_MAX_KEY_LEN;
826 ret = eapol_sm_get_key(wpa_s->eapol, rmsk, rmsk_len);
827
828 if (ret == PMK_LEN) {
829 rmsk_len = PMK_LEN;
830 ret = eapol_sm_get_key(wpa_s->eapol, rmsk, rmsk_len);
831 }
832
833 if (ret) {
834 wpa_printf(MSG_DEBUG, "PASN: FILS: Failed getting RMSK");
835 return -1;
836 }
837
838 ret = fils_rmsk_to_pmk(pasn->akmp, rmsk, rmsk_len,
839 pasn->fils.nonce, anonce, NULL, 0,
840 pasn->pmk, &pasn->pmk_len);
841
842 forced_memzero(rmsk, sizeof(rmsk));
843
844 if (ret) {
845 wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PMK");
846 return -1;
847 }
848
849 wpa_hexdump(MSG_DEBUG, "PASN: FILS: PMKID", pasn->fils.erp_pmkid,
850 PMKID_LEN);
851
852 wpa_printf(MSG_DEBUG, "PASN: FILS: ERP processing succeeded");
853
854 wpa_pasn_pmksa_cache_add(wpa_s->wpa, pasn->pmk,
855 pasn->pmk_len, pasn->fils.erp_pmkid,
856 pasn->bssid, pasn->akmp);
857
858 pasn->fils.completed = true;
859 return 0;
860}
861
862#endif /* CONFIG_FILS */
863
864
865static struct wpabuf * wpas_pasn_get_wrapped_data(struct wpa_supplicant *wpa_s)
866{
867 struct wpas_pasn *pasn = &wpa_s->pasn;
868
869 if (pasn->using_pmksa)
870 return NULL;
871
872 switch (pasn->akmp) {
873 case WPA_KEY_MGMT_PASN:
874 /* no wrapped data */
875 return NULL;
876 case WPA_KEY_MGMT_SAE:
877#ifdef CONFIG_SAE
878 if (pasn->trans_seq == 0)
879 return wpas_pasn_wd_sae_commit(wpa_s);
880 if (pasn->trans_seq == 2)
881 return wpas_pasn_wd_sae_confirm(wpa_s);
882#endif /* CONFIG_SAE */
883 wpa_printf(MSG_ERROR,
884 "PASN: SAE: Cannot derive wrapped data");
885 return NULL;
886 case WPA_KEY_MGMT_FILS_SHA256:
887 case WPA_KEY_MGMT_FILS_SHA384:
888#ifdef CONFIG_FILS
889 return wpas_pasn_wd_fils_auth(wpa_s);
890#endif /* CONFIG_FILS */
891 case WPA_KEY_MGMT_FT_PSK:
892 case WPA_KEY_MGMT_FT_IEEE8021X:
893 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
894 /*
895 * Wrapped data with these AKMs is optional and is only needed
896 * for further validation of FT security parameters. For now do
897 * not use them.
898 */
899 return NULL;
900 default:
901 wpa_printf(MSG_ERROR,
902 "PASN: TODO: Wrapped data for akmp=0x%x",
903 pasn->akmp);
904 return NULL;
905 }
906}
907
908
909static u8 wpas_pasn_get_wrapped_data_format(struct wpas_pasn *pasn)
910{
911 if (pasn->using_pmksa)
912 return WPA_PASN_WRAPPED_DATA_NO;
913
914 /* Note: Valid AKMP is expected to already be validated */
915 switch (pasn->akmp) {
916 case WPA_KEY_MGMT_SAE:
917 return WPA_PASN_WRAPPED_DATA_SAE;
918 case WPA_KEY_MGMT_FILS_SHA256:
919 case WPA_KEY_MGMT_FILS_SHA384:
920 return WPA_PASN_WRAPPED_DATA_FILS_SK;
921 case WPA_KEY_MGMT_FT_PSK:
922 case WPA_KEY_MGMT_FT_IEEE8021X:
923 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
924 /*
925 * Wrapped data with these AKMs is optional and is only needed
926 * for further validation of FT security parameters. For now do
927 * not use them.
928 */
929 return WPA_PASN_WRAPPED_DATA_NO;
930 case WPA_KEY_MGMT_PASN:
931 default:
932 return WPA_PASN_WRAPPED_DATA_NO;
933 }
934}
935
936
Hai Shaloma20dcd72022-02-04 13:43:00 -0800937static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s,
938 const struct wpabuf *comeback)
Hai Shalom60840252021-02-19 19:02:11 -0800939{
940 struct wpas_pasn *pasn = &wpa_s->pasn;
941 struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
942 const u8 *pmkid;
943 u8 wrapped_data;
944 int ret;
945 u16 capab;
946
947 wpa_printf(MSG_DEBUG, "PASN: Building frame 1");
948
949 if (pasn->trans_seq)
950 return NULL;
951
952 buf = wpabuf_alloc(1500);
953 if (!buf)
954 goto fail;
955
956 /* Get public key */
957 pubkey = crypto_ecdh_get_pubkey(pasn->ecdh, 0);
958 pubkey = wpabuf_zeropad(pubkey, crypto_ecdh_prime_len(pasn->ecdh));
959 if (!pubkey) {
960 wpa_printf(MSG_DEBUG, "PASN: Failed to get pubkey");
961 goto fail;
962 }
963
964 wrapped_data = wpas_pasn_get_wrapped_data_format(pasn);
965
966 wpa_pasn_build_auth_header(buf, pasn->bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -0700967 pasn->own_addr, pasn->bssid,
Hai Shalom60840252021-02-19 19:02:11 -0800968 pasn->trans_seq + 1, WLAN_STATUS_SUCCESS);
969
970 pmkid = NULL;
971 if (wpa_key_mgmt_ft(pasn->akmp)) {
972 ret = wpa_pasn_ft_derive_pmk_r1(wpa_s->wpa, pasn->akmp,
973 pasn->bssid,
974 pasn->pmk_r1,
975 &pasn->pmk_r1_len,
976 pasn->pmk_r1_name);
977 if (ret) {
978 wpa_printf(MSG_DEBUG,
979 "PASN: FT: Failed to derive keys");
980 goto fail;
981 }
982
983 pmkid = pasn->pmk_r1_name;
984 } else if (wrapped_data != WPA_PASN_WRAPPED_DATA_NO) {
985 struct rsn_pmksa_cache_entry *pmksa;
986
987 pmksa = wpa_sm_pmksa_cache_get(wpa_s->wpa, pasn->bssid,
988 NULL, NULL, pasn->akmp);
989 if (pmksa)
990 pmkid = pmksa->pmkid;
991
992 /*
993 * Note: Even when PMKSA is available, also add wrapped data as
994 * it is possible that the PMKID is no longer valid at the AP.
995 */
996 wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s);
997 }
998
999 if (wpa_pasn_add_rsne(buf, pmkid, pasn->akmp, pasn->cipher) < 0)
1000 goto fail;
1001
1002 if (!wrapped_data_buf)
1003 wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
1004
1005 wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001006 pubkey, true, comeback, -1);
Hai Shalom60840252021-02-19 19:02:11 -08001007
1008 if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
1009 goto fail;
1010
1011 /* Add own RNSXE */
Hai Shalom60840252021-02-19 19:02:11 -08001012 capab = 0;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001013 capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
Sunil Ravi89eba102022-09-13 21:04:37 -07001014 if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_STA)
Hai Shalom60840252021-02-19 19:02:11 -08001015 capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
Sunil Ravi89eba102022-09-13 21:04:37 -07001016 if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT_STA)
Hai Shalom60840252021-02-19 19:02:11 -08001017 capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
Sunil Ravi89eba102022-09-13 21:04:37 -07001018 if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_STA)
Hai Shalom60840252021-02-19 19:02:11 -08001019 capab |= BIT(WLAN_RSNX_CAPAB_PROT_RANGE_NEG);
1020 wpa_pasn_add_rsnxe(buf, capab);
1021
1022 ret = pasn_auth_frame_hash(pasn->akmp, pasn->cipher,
1023 wpabuf_head_u8(buf) + IEEE80211_HDRLEN,
1024 wpabuf_len(buf) - IEEE80211_HDRLEN,
1025 pasn->hash);
1026 if (ret) {
1027 wpa_printf(MSG_DEBUG, "PASN: Failed to compute hash");
1028 goto fail;
1029 }
1030
1031 pasn->trans_seq++;
1032
1033 wpabuf_free(wrapped_data_buf);
1034 wpabuf_free(pubkey);
1035
1036 wpa_printf(MSG_DEBUG, "PASN: Frame 1: Success");
1037 return buf;
1038fail:
1039 pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1040 wpabuf_free(wrapped_data_buf);
1041 wpabuf_free(pubkey);
1042 wpabuf_free(buf);
1043 return NULL;
1044}
1045
1046
1047static struct wpabuf * wpas_pasn_build_auth_3(struct wpa_supplicant *wpa_s)
1048{
1049 struct wpas_pasn *pasn = &wpa_s->pasn;
1050 struct wpabuf *buf, *wrapped_data_buf = NULL;
1051 u8 mic[WPA_PASN_MAX_MIC_LEN];
1052 u8 mic_len, data_len;
1053 const u8 *data;
1054 u8 *ptr;
1055 u8 wrapped_data;
1056 int ret;
1057
1058 wpa_printf(MSG_DEBUG, "PASN: Building frame 3");
1059
1060 if (pasn->trans_seq != 2)
1061 return NULL;
1062
1063 buf = wpabuf_alloc(1500);
1064 if (!buf)
1065 goto fail;
1066
1067 wrapped_data = wpas_pasn_get_wrapped_data_format(pasn);
1068
1069 wpa_pasn_build_auth_header(buf, pasn->bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001070 pasn->own_addr, pasn->bssid,
Hai Shalom60840252021-02-19 19:02:11 -08001071 pasn->trans_seq + 1, WLAN_STATUS_SUCCESS);
1072
1073 wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s);
1074
1075 if (!wrapped_data_buf)
1076 wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
1077
1078 wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001079 NULL, false, NULL, -1);
Hai Shalom60840252021-02-19 19:02:11 -08001080
1081 if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
1082 goto fail;
1083 wpabuf_free(wrapped_data_buf);
1084 wrapped_data_buf = NULL;
1085
1086 /* Add the MIC */
1087 mic_len = pasn_mic_len(pasn->akmp, pasn->cipher);
1088 wpabuf_put_u8(buf, WLAN_EID_MIC);
1089 wpabuf_put_u8(buf, mic_len);
1090 ptr = wpabuf_put(buf, mic_len);
1091
1092 os_memset(ptr, 0, mic_len);
1093
1094 data = wpabuf_head_u8(buf) + IEEE80211_HDRLEN;
1095 data_len = wpabuf_len(buf) - IEEE80211_HDRLEN;
1096
1097 ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
Sunil Ravi89eba102022-09-13 21:04:37 -07001098 pasn->own_addr, pasn->bssid,
Hai Shalom60840252021-02-19 19:02:11 -08001099 pasn->hash, mic_len * 2, data, data_len, mic);
1100 if (ret) {
1101 wpa_printf(MSG_DEBUG, "PASN: frame 3: Failed MIC calculation");
1102 goto fail;
1103 }
1104
Hai Shaloma20dcd72022-02-04 13:43:00 -08001105#ifdef CONFIG_TESTING_OPTIONS
1106 if (wpa_s->conf->pasn_corrupt_mic) {
1107 wpa_printf(MSG_DEBUG, "PASN: frame 3: Corrupt MIC");
1108 mic[0] = ~mic[0];
1109 }
1110#endif /* CONFIG_TESTING_OPTIONS */
1111
Hai Shalom60840252021-02-19 19:02:11 -08001112 os_memcpy(ptr, mic, mic_len);
1113
1114 pasn->trans_seq++;
1115
1116 wpa_printf(MSG_DEBUG, "PASN: frame 3: Success");
1117 return buf;
1118fail:
1119 pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1120 wpabuf_free(wrapped_data_buf);
1121 wpabuf_free(buf);
1122 return NULL;
1123}
1124
1125
1126static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
1127{
1128 struct wpas_pasn *pasn = &wpa_s->pasn;
1129
1130 wpa_printf(MSG_DEBUG, "PASN: Reset");
1131
1132 crypto_ecdh_deinit(pasn->ecdh);
1133 pasn->ecdh = NULL;
1134
1135 wpas_pasn_cancel_auth_work(wpa_s);
1136 wpa_s->pasn_auth_work = NULL;
1137
1138 eloop_cancel_timeout(wpas_pasn_auth_work_timeout, wpa_s, NULL);
1139
1140 pasn->akmp = 0;
1141 pasn->cipher = 0;
1142 pasn->group = 0;
1143 pasn->trans_seq = 0;
1144 pasn->pmk_len = 0;
1145 pasn->using_pmksa = false;
1146
1147 forced_memzero(pasn->pmk, sizeof(pasn->pmk));
1148 forced_memzero(&pasn->ptk, sizeof(pasn->ptk));
1149 forced_memzero(&pasn->hash, sizeof(pasn->hash));
1150
1151 wpabuf_free(pasn->beacon_rsne_rsnxe);
1152 pasn->beacon_rsne_rsnxe = NULL;
1153
Hai Shaloma20dcd72022-02-04 13:43:00 -08001154 wpabuf_free(pasn->comeback);
1155 pasn->comeback = NULL;
1156 pasn->comeback_after = 0;
1157
Hai Shalom60840252021-02-19 19:02:11 -08001158#ifdef CONFIG_SAE
1159 sae_clear_data(&pasn->sae);
1160#endif /* CONFIG_SAE */
1161
1162#ifdef CONFIG_FILS
1163 os_memset(&pasn->fils, 0, sizeof(pasn->fils));
1164#endif /* CONFIG_FILS*/
1165
1166#ifdef CONFIG_IEEE80211R
1167 forced_memzero(pasn->pmk_r1, sizeof(pasn->pmk_r1));
1168 pasn->pmk_r1_len = 0;
1169 os_memset(pasn->pmk_r1_name, 0, sizeof(pasn->pmk_r1_name));
1170#endif /* CONFIG_IEEE80211R */
1171 pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1172}
1173
1174
1175static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s,
1176 struct wpa_ie_data *rsn_data,
1177 struct wpa_pasn_params_data *pasn_data,
1178 struct wpabuf *wrapped_data)
1179{
1180 static const u8 pasn_default_pmk[] = {'P', 'M', 'K', 'z'};
1181 struct wpas_pasn *pasn = &wpa_s->pasn;
1182
1183 os_memset(pasn->pmk, 0, sizeof(pasn->pmk));
1184 pasn->pmk_len = 0;
1185
1186 if (pasn->akmp == WPA_KEY_MGMT_PASN) {
1187 wpa_printf(MSG_DEBUG, "PASN: Using default PMK");
1188
1189 pasn->pmk_len = WPA_PASN_PMK_LEN;
1190 os_memcpy(pasn->pmk, pasn_default_pmk,
1191 sizeof(pasn_default_pmk));
1192 return 0;
1193 }
1194
1195 if (wpa_key_mgmt_ft(pasn->akmp)) {
1196#ifdef CONFIG_IEEE80211R
1197 wpa_printf(MSG_DEBUG, "PASN: FT: Using PMK-R1");
1198 pasn->pmk_len = pasn->pmk_r1_len;
1199 os_memcpy(pasn->pmk, pasn->pmk_r1, pasn->pmk_r1_len);
1200 pasn->using_pmksa = true;
1201 return 0;
1202#else /* CONFIG_IEEE80211R */
1203 wpa_printf(MSG_DEBUG, "PASN: FT: Not supported");
1204 return -1;
1205#endif /* CONFIG_IEEE80211R */
1206 }
1207
1208 if (rsn_data->num_pmkid) {
1209 struct rsn_pmksa_cache_entry *pmksa;
1210
1211 pmksa = wpa_sm_pmksa_cache_get(wpa_s->wpa, pasn->bssid,
1212 rsn_data->pmkid, NULL,
1213 pasn->akmp);
1214 if (pmksa) {
1215 wpa_printf(MSG_DEBUG, "PASN: Using PMKSA");
1216
1217 pasn->pmk_len = pmksa->pmk_len;
1218 os_memcpy(pasn->pmk, pmksa->pmk, pmksa->pmk_len);
1219 pasn->using_pmksa = true;
1220
1221 return 0;
1222 }
1223 }
1224
1225#ifdef CONFIG_SAE
1226 if (pasn->akmp == WPA_KEY_MGMT_SAE) {
1227 int ret;
1228
1229 ret = wpas_pasn_wd_sae_rx(wpa_s, wrapped_data);
1230 if (ret) {
1231 wpa_printf(MSG_DEBUG,
1232 "PASN: Failed processing SAE wrapped data");
1233 pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1234 return -1;
1235 }
1236
1237 wpa_printf(MSG_DEBUG, "PASN: Success deriving PMK with SAE");
1238 pasn->pmk_len = PMK_LEN;
1239 os_memcpy(pasn->pmk, pasn->sae.pmk, PMK_LEN);
1240
1241 wpa_pasn_pmksa_cache_add(wpa_s->wpa, pasn->pmk,
1242 pasn->pmk_len, pasn->sae.pmkid,
1243 pasn->bssid, pasn->akmp);
1244 return 0;
1245 }
1246#endif /* CONFIG_SAE */
1247
1248#ifdef CONFIG_FILS
1249 if (pasn->akmp == WPA_KEY_MGMT_FILS_SHA256 ||
1250 pasn->akmp == WPA_KEY_MGMT_FILS_SHA384) {
1251 int ret;
1252
1253 ret = wpas_pasn_wd_fils_rx(wpa_s, wrapped_data);
1254 if (ret) {
1255 wpa_printf(MSG_DEBUG,
1256 "PASN: Failed processing FILS wrapped data");
1257 pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1258 return -1;
1259 }
1260
1261 return 0;
1262 }
1263#endif /* CONFIG_FILS */
1264
1265 /* TODO: Derive PMK based on wrapped data */
1266 wpa_printf(MSG_DEBUG, "PASN: Missing implementation to derive PMK");
1267 pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1268 return -1;
1269}
1270
1271
Sunil Ravi89eba102022-09-13 21:04:37 -07001272static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *own_addr,
1273 const u8 *bssid, int akmp, int cipher, u16 group,
1274 int freq, const u8 *beacon_rsne, u8 beacon_rsne_len,
Hai Shalom60840252021-02-19 19:02:11 -08001275 const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001276 int network_id, struct wpabuf *comeback)
Hai Shalom60840252021-02-19 19:02:11 -08001277{
1278 struct wpas_pasn *pasn = &wpa_s->pasn;
1279 struct wpa_ssid *ssid = NULL;
1280 struct wpabuf *frame;
1281 int ret;
Sunil Ravia04bd252022-05-02 22:54:18 -07001282 bool derive_kdk;
Hai Shalom60840252021-02-19 19:02:11 -08001283
1284 /* TODO: Currently support only ECC groups */
1285 if (!dragonfly_suitable_group(group, 1)) {
1286 wpa_printf(MSG_DEBUG,
1287 "PASN: Reject unsuitable group %u", group);
1288 return -1;
1289 }
1290
1291 ssid = wpa_config_get_network(wpa_s->conf, network_id);
1292
1293 switch (akmp) {
1294 case WPA_KEY_MGMT_PASN:
1295 break;
1296#ifdef CONFIG_SAE
1297 case WPA_KEY_MGMT_SAE:
1298 if (!ssid) {
1299 wpa_printf(MSG_DEBUG,
1300 "PASN: No network profile found for SAE");
1301 return -1;
1302 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001303
1304 if (!ieee802_11_rsnx_capab(beacon_rsnxe,
1305 WLAN_RSNX_CAPAB_SAE_H2E)) {
1306 wpa_printf(MSG_DEBUG,
1307 "PASN: AP does not support SAE H2E");
1308 return -1;
1309 }
1310
1311 if (wpas_pasn_sae_setup_pt(wpa_s, ssid, group) < 0) {
1312 wpa_printf(MSG_DEBUG,
1313 "PASN: Failed to derive PT");
1314 return -1;
1315 }
1316
Hai Shalom60840252021-02-19 19:02:11 -08001317 pasn->sae.state = SAE_NOTHING;
1318 pasn->sae.send_confirm = 0;
1319 pasn->ssid = ssid;
1320 break;
1321#endif /* CONFIG_SAE */
1322#ifdef CONFIG_FILS
1323 case WPA_KEY_MGMT_FILS_SHA256:
1324 case WPA_KEY_MGMT_FILS_SHA384:
1325 pasn->ssid = ssid;
1326 break;
1327#endif /* CONFIG_FILS */
1328#ifdef CONFIG_IEEE80211R
1329 case WPA_KEY_MGMT_FT_PSK:
1330 case WPA_KEY_MGMT_FT_IEEE8021X:
1331 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
1332 break;
1333#endif /* CONFIG_IEEE80211R */
1334 default:
1335 wpa_printf(MSG_ERROR, "PASN: Unsupported AKMP=0x%x", akmp);
1336 return -1;
1337 }
1338
1339 pasn->ecdh = crypto_ecdh_init(group);
1340 if (!pasn->ecdh) {
1341 wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
1342 goto fail;
1343 }
1344
1345 pasn->beacon_rsne_rsnxe = wpabuf_alloc(beacon_rsne_len +
1346 beacon_rsnxe_len);
1347 if (!pasn->beacon_rsne_rsnxe) {
1348 wpa_printf(MSG_DEBUG, "PASN: Failed storing beacon RSNE/RSNXE");
1349 goto fail;
1350 }
1351
1352 wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsne, beacon_rsne_len);
1353 if (beacon_rsnxe && beacon_rsnxe_len)
1354 wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsnxe,
1355 beacon_rsnxe_len);
1356
1357 pasn->akmp = akmp;
1358 pasn->cipher = cipher;
1359 pasn->group = group;
1360 pasn->freq = freq;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001361
Sunil Ravi89eba102022-09-13 21:04:37 -07001362 derive_kdk = (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_STA) &&
Sunil Ravia04bd252022-05-02 22:54:18 -07001363 ieee802_11_rsnx_capab(beacon_rsnxe,
1364 WLAN_RSNX_CAPAB_SECURE_LTF);
1365#ifdef CONFIG_TESTING_OPTIONS
1366 if (!derive_kdk)
1367 derive_kdk = wpa_s->conf->force_kdk_derivation;
1368#endif /* CONFIG_TESTING_OPTIONS */
1369 if (derive_kdk)
Hai Shaloma20dcd72022-02-04 13:43:00 -08001370 pasn->kdk_len = WPA_KDK_MAX_LEN;
1371 else
1372 pasn->kdk_len = 0;
1373 wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", pasn->kdk_len);
1374
Sunil Ravi89eba102022-09-13 21:04:37 -07001375 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_STA) &&
1376 ieee802_11_rsnx_capab(beacon_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))
1377 pasn->secure_ltf = true;
1378 else
1379 pasn->secure_ltf = false;
1380
1381 os_memcpy(pasn->own_addr, own_addr, ETH_ALEN);
Hai Shalom60840252021-02-19 19:02:11 -08001382 os_memcpy(pasn->bssid, bssid, ETH_ALEN);
1383
1384 wpa_printf(MSG_DEBUG,
1385 "PASN: Init: " MACSTR " akmp=0x%x, cipher=0x%x, group=%u",
1386 MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher,
1387 pasn->group);
1388
Hai Shaloma20dcd72022-02-04 13:43:00 -08001389 frame = wpas_pasn_build_auth_1(wpa_s, comeback);
Hai Shalom60840252021-02-19 19:02:11 -08001390 if (!frame) {
1391 wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
1392 goto fail;
1393 }
1394
1395 ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(frame), wpabuf_len(frame), 0,
1396 pasn->freq, 1000);
1397
1398 wpabuf_free(frame);
1399 if (ret) {
1400 wpa_printf(MSG_DEBUG, "PASN: Failed sending 1st auth frame");
1401 goto fail;
1402 }
1403
1404 eloop_register_timeout(2, 0, wpas_pasn_auth_work_timeout, wpa_s, NULL);
1405 return 0;
1406
1407fail:
1408 return -1;
1409}
1410
1411
1412static struct wpa_bss * wpas_pasn_allowed(struct wpa_supplicant *wpa_s,
1413 const u8 *bssid, int akmp, int cipher)
1414{
1415 struct wpa_bss *bss;
1416 const u8 *rsne;
1417 struct wpa_ie_data rsne_data;
1418 int ret;
1419
1420 if (os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) == 0) {
1421 wpa_printf(MSG_DEBUG,
1422 "PASN: Not doing authentication with current BSS");
1423 return NULL;
1424 }
1425
1426 bss = wpa_bss_get_bssid(wpa_s, bssid);
1427 if (!bss) {
1428 wpa_printf(MSG_DEBUG, "PASN: BSS not found");
1429 return NULL;
1430 }
1431
1432 rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1433 if (!rsne) {
1434 wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
1435 return NULL;
1436 }
1437
1438 ret = wpa_parse_wpa_ie(rsne, *(rsne + 1) + 2, &rsne_data);
1439 if (ret) {
1440 wpa_printf(MSG_DEBUG, "PASN: Failed parsing RSNE data");
1441 return NULL;
1442 }
1443
1444 if (!(rsne_data.key_mgmt & akmp) ||
1445 !(rsne_data.pairwise_cipher & cipher)) {
1446 wpa_printf(MSG_DEBUG,
1447 "PASN: AP does not support requested AKMP or cipher");
1448 return NULL;
1449 }
1450
1451 return bss;
1452}
1453
1454
1455static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
1456{
1457 struct wpa_supplicant *wpa_s = work->wpa_s;
1458 struct wpa_pasn_auth_work *awork = work->ctx;
1459 struct wpa_bss *bss;
1460 const u8 *rsne, *rsnxe;
1461 int ret;
1462
1463 wpa_printf(MSG_DEBUG, "PASN: auth_start_cb: deinit=%d", deinit);
1464
1465 if (deinit) {
1466 if (work->started) {
1467 eloop_cancel_timeout(wpas_pasn_auth_work_timeout,
1468 wpa_s, NULL);
1469 wpa_s->pasn_auth_work = NULL;
1470 }
Hai Shaloma20dcd72022-02-04 13:43:00 -08001471
1472 wpas_pasn_free_auth_work(awork);
Hai Shalom60840252021-02-19 19:02:11 -08001473 return;
1474 }
1475
1476 /*
1477 * It is possible that by the time the callback is called, the PASN
1478 * authentication is not allowed, e.g., a connection with the AP was
1479 * established.
1480 */
1481 bss = wpas_pasn_allowed(wpa_s, awork->bssid, awork->akmp,
1482 awork->cipher);
1483 if (!bss) {
1484 wpa_printf(MSG_DEBUG, "PASN: auth_start_cb: Not allowed");
1485 goto fail;
1486 }
1487
1488 rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
1489 if (!rsne) {
1490 wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
1491 goto fail;
1492 }
1493
1494 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
1495
Sunil Ravi89eba102022-09-13 21:04:37 -07001496 ret = wpas_pasn_start(wpa_s, awork->own_addr, awork->bssid, awork->akmp,
1497 awork->cipher, awork->group, bss->freq,
1498 rsne, *(rsne + 1) + 2,
Hai Shalom60840252021-02-19 19:02:11 -08001499 rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001500 awork->network_id, awork->comeback);
Hai Shalom60840252021-02-19 19:02:11 -08001501 if (ret) {
1502 wpa_printf(MSG_DEBUG,
1503 "PASN: Failed to start PASN authentication");
1504 goto fail;
1505 }
1506
Hai Shaloma20dcd72022-02-04 13:43:00 -08001507 /* comeback token is no longer needed at this stage */
1508 wpabuf_free(awork->comeback);
1509 awork->comeback = NULL;
1510
Hai Shalom60840252021-02-19 19:02:11 -08001511 wpa_s->pasn_auth_work = work;
1512 return;
1513fail:
Hai Shaloma20dcd72022-02-04 13:43:00 -08001514 wpas_pasn_free_auth_work(awork);
Hai Shalom60840252021-02-19 19:02:11 -08001515 work->ctx = NULL;
1516 radio_work_done(work);
1517}
1518
1519
Sunil Ravi89eba102022-09-13 21:04:37 -07001520int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
1521 const u8 *own_addr, const u8 *bssid,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001522 int akmp, int cipher, u16 group, int network_id,
1523 const u8 *comeback, size_t comeback_len)
Hai Shalom60840252021-02-19 19:02:11 -08001524{
1525 struct wpa_pasn_auth_work *awork;
1526 struct wpa_bss *bss;
1527
1528 wpa_printf(MSG_DEBUG, "PASN: Start: " MACSTR " akmp=0x%x, cipher=0x%x",
1529 MAC2STR(bssid), akmp, cipher);
1530
1531 /*
1532 * TODO: Consider modifying the offchannel logic to handle additional
1533 * Management frames other then Action frames. For now allow PASN only
1534 * with drivers that support off-channel TX.
1535 */
1536 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX)) {
1537 wpa_printf(MSG_DEBUG,
1538 "PASN: Driver does not support offchannel TX");
1539 return -1;
1540 }
1541
1542 if (radio_work_pending(wpa_s, "pasn-start-auth")) {
1543 wpa_printf(MSG_DEBUG,
1544 "PASN: send_auth: Work is already pending");
1545 return -1;
1546 }
1547
1548 if (wpa_s->pasn_auth_work) {
1549 wpa_printf(MSG_DEBUG, "PASN: send_auth: Already in progress");
1550 return -1;
1551 }
1552
1553 bss = wpas_pasn_allowed(wpa_s, bssid, akmp, cipher);
1554 if (!bss)
1555 return -1;
1556
1557 wpas_pasn_reset(wpa_s);
1558
1559 awork = os_zalloc(sizeof(*awork));
1560 if (!awork)
1561 return -1;
1562
Sunil Ravi89eba102022-09-13 21:04:37 -07001563 os_memcpy(awork->own_addr, own_addr, ETH_ALEN);
Hai Shalom60840252021-02-19 19:02:11 -08001564 os_memcpy(awork->bssid, bssid, ETH_ALEN);
1565 awork->akmp = akmp;
1566 awork->cipher = cipher;
1567 awork->group = group;
1568 awork->network_id = network_id;
1569
Hai Shaloma20dcd72022-02-04 13:43:00 -08001570 if (comeback && comeback_len) {
1571 awork->comeback = wpabuf_alloc_copy(comeback, comeback_len);
1572 if (!awork->comeback) {
1573 wpas_pasn_free_auth_work(awork);
1574 return -1;
1575 }
1576 }
1577
Hai Shalom60840252021-02-19 19:02:11 -08001578 if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1,
1579 wpas_pasn_auth_start_cb, awork) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001580 wpas_pasn_free_auth_work(awork);
Hai Shalom60840252021-02-19 19:02:11 -08001581 return -1;
1582 }
1583
1584 wpa_printf(MSG_DEBUG, "PASN: Auth work successfully added");
1585 return 0;
1586}
1587
1588
1589void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s)
1590{
1591 struct wpas_pasn *pasn = &wpa_s->pasn;
1592
1593 if (!wpa_s->pasn.ecdh)
1594 return;
1595
1596 wpa_printf(MSG_DEBUG, "PASN: Stopping authentication");
1597
1598 wpas_pasn_auth_status(wpa_s, pasn->bssid, pasn->akmp, pasn->cipher,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001599 pasn->status, pasn->comeback,
1600 pasn->comeback_after);
Hai Shalom60840252021-02-19 19:02:11 -08001601
1602 wpas_pasn_reset(wpa_s);
1603}
1604
1605
Hai Shaloma20dcd72022-02-04 13:43:00 -08001606static int wpas_pasn_immediate_retry(struct wpa_supplicant *wpa_s,
1607 struct wpas_pasn *pasn,
1608 struct wpa_pasn_params_data *params)
1609{
1610 int akmp = pasn->akmp;
1611 int cipher = pasn->cipher;
1612 u16 group = pasn->group;
Sunil Ravi89eba102022-09-13 21:04:37 -07001613 u8 own_addr[ETH_ALEN];
Hai Shaloma20dcd72022-02-04 13:43:00 -08001614 u8 bssid[ETH_ALEN];
1615 int network_id = pasn->ssid ? pasn->ssid->id : 0;
1616
1617 wpa_printf(MSG_DEBUG, "PASN: Immediate retry");
Sunil Ravi89eba102022-09-13 21:04:37 -07001618 os_memcpy(own_addr, pasn->own_addr, ETH_ALEN);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001619 os_memcpy(bssid, pasn->bssid, ETH_ALEN);
1620 wpas_pasn_reset(wpa_s);
1621
Sunil Ravi89eba102022-09-13 21:04:37 -07001622 return wpas_pasn_auth_start(wpa_s, own_addr, bssid, akmp, cipher, group,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001623 network_id,
1624 params->comeback, params->comeback_len);
1625}
1626
1627
Sunil Ravi89eba102022-09-13 21:04:37 -07001628static void wpas_pasn_deauth_cb(struct ptksa_cache_entry *entry)
1629{
1630 struct wpa_supplicant *wpa_s = entry->ctx;
1631
1632 wpas_pasn_deauthenticate(wpa_s, entry->own_addr, entry->addr);
1633}
1634
1635
Hai Shalom60840252021-02-19 19:02:11 -08001636int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
1637 const struct ieee80211_mgmt *mgmt, size_t len)
1638{
1639 struct wpas_pasn *pasn = &wpa_s->pasn;
1640 struct ieee802_11_elems elems;
1641 struct wpa_ie_data rsn_data;
1642 struct wpa_pasn_params_data pasn_params;
1643 struct wpabuf *wrapped_data = NULL, *secret = NULL, *frame = NULL;
1644 u8 mic[WPA_PASN_MAX_MIC_LEN], out_mic[WPA_PASN_MAX_MIC_LEN];
1645 u8 mic_len;
1646 u16 status;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001647 int ret, inc_y;
Hai Shalom60840252021-02-19 19:02:11 -08001648 u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
1649 (WLAN_FC_STYPE_AUTH << 4));
1650
1651 if (!wpa_s->pasn_auth_work || !mgmt ||
1652 len < offsetof(struct ieee80211_mgmt, u.auth.variable))
1653 return -2;
1654
1655 /* Not an Authentication frame; do nothing */
1656 if ((mgmt->frame_control & fc) != fc)
1657 return -2;
1658
1659 /* Not our frame; do nothing */
Sunil Ravi89eba102022-09-13 21:04:37 -07001660 if (os_memcmp(mgmt->da, pasn->own_addr, ETH_ALEN) != 0 ||
Hai Shalom60840252021-02-19 19:02:11 -08001661 os_memcmp(mgmt->sa, pasn->bssid, ETH_ALEN) != 0 ||
1662 os_memcmp(mgmt->bssid, pasn->bssid, ETH_ALEN) != 0)
1663 return -2;
1664
1665 /* Not PASN; do nothing */
1666 if (mgmt->u.auth.auth_alg != host_to_le16(WLAN_AUTH_PASN))
1667 return -2;
1668
1669 if (mgmt->u.auth.auth_transaction !=
1670 host_to_le16(pasn->trans_seq + 1)) {
1671 wpa_printf(MSG_DEBUG,
1672 "PASN: RX: Invalid transaction sequence: (%u != %u)",
1673 le_to_host16(mgmt->u.auth.auth_transaction),
1674 pasn->trans_seq + 1);
1675 return -1;
1676 }
1677
1678 status = le_to_host16(mgmt->u.auth.status_code);
1679
1680 if (status != WLAN_STATUS_SUCCESS &&
1681 status != WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
1682 wpa_printf(MSG_DEBUG,
1683 "PASN: Authentication rejected - status=%u", status);
Sunil Ravi89eba102022-09-13 21:04:37 -07001684 goto fail;
Hai Shalom60840252021-02-19 19:02:11 -08001685 }
1686
1687 if (ieee802_11_parse_elems(mgmt->u.auth.variable,
1688 len - offsetof(struct ieee80211_mgmt,
1689 u.auth.variable),
1690 &elems, 0) == ParseFailed) {
1691 wpa_printf(MSG_DEBUG,
1692 "PASN: Failed parsing Authentication frame");
1693 goto fail;
1694 }
1695
1696 /* Check that the MIC IE exists. Save it and zero out the memory */
1697 mic_len = pasn_mic_len(pasn->akmp, pasn->cipher);
1698 if (status == WLAN_STATUS_SUCCESS) {
1699 if (!elems.mic || elems.mic_len != mic_len) {
1700 wpa_printf(MSG_DEBUG,
1701 "PASN: Invalid MIC. Expecting len=%u",
1702 mic_len);
1703 goto fail;
1704 } else {
1705 os_memcpy(mic, elems.mic, mic_len);
1706 /* TODO: Clean this up.. Should not be modifying the
1707 * received message buffer. */
1708 os_memset((u8 *) elems.mic, 0, mic_len);
1709 }
1710 }
1711
1712 if (!elems.pasn_params || !elems.pasn_params_len) {
1713 wpa_printf(MSG_DEBUG,
1714 "PASN: Missing PASN Parameters IE");
1715 goto fail;
1716 }
1717
1718 ret = wpa_pasn_parse_parameter_ie(elems.pasn_params - 3,
1719 elems.pasn_params_len + 3,
1720 true, &pasn_params);
1721 if (ret) {
1722 wpa_printf(MSG_DEBUG,
1723 "PASN: Failed validation PASN of Parameters IE");
1724 goto fail;
1725 }
1726
Hai Shalom60840252021-02-19 19:02:11 -08001727 if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
1728 wpa_printf(MSG_DEBUG,
1729 "PASN: Authentication temporarily rejected");
Hai Shaloma20dcd72022-02-04 13:43:00 -08001730
1731 if (pasn_params.comeback && pasn_params.comeback_len) {
1732 wpa_printf(MSG_DEBUG,
1733 "PASN: Comeback token available. After=%u",
1734 pasn_params.after);
1735
1736 if (!pasn_params.after)
1737 return wpas_pasn_immediate_retry(wpa_s, pasn,
1738 &pasn_params);
1739
1740 pasn->comeback = wpabuf_alloc_copy(
1741 pasn_params.comeback, pasn_params.comeback_len);
1742 if (pasn->comeback)
1743 pasn->comeback_after = pasn_params.after;
1744 }
1745
1746 pasn->status = status;
Hai Shalom60840252021-02-19 19:02:11 -08001747 goto fail;
1748 }
1749
1750 ret = wpa_parse_wpa_ie(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
1751 &rsn_data);
1752 if (ret) {
1753 wpa_printf(MSG_DEBUG, "PASN: Failed parsing RNSE");
1754 goto fail;
1755 }
1756
1757 ret = wpa_pasn_validate_rsne(&rsn_data);
1758 if (ret) {
1759 wpa_printf(MSG_DEBUG, "PASN: Failed validating RSNE");
1760 goto fail;
1761 }
1762
1763 if (pasn->akmp != rsn_data.key_mgmt ||
1764 pasn->cipher != rsn_data.pairwise_cipher) {
1765 wpa_printf(MSG_DEBUG, "PASN: Mismatch in AKMP/cipher");
1766 goto fail;
1767 }
1768
1769 if (pasn->group != pasn_params.group) {
1770 wpa_printf(MSG_DEBUG, "PASN: Mismatch in group");
1771 goto fail;
1772 }
1773
1774 if (!pasn_params.pubkey || !pasn_params.pubkey_len) {
1775 wpa_printf(MSG_DEBUG, "PASN: Invalid public key");
1776 goto fail;
1777 }
1778
Hai Shaloma20dcd72022-02-04 13:43:00 -08001779 if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) {
1780 inc_y = 1;
1781 } else if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 ||
1782 pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) {
1783 inc_y = 0;
1784 } else {
1785 wpa_printf(MSG_DEBUG,
1786 "PASN: Invalid first octet in pubkey=0x%x",
1787 pasn_params.pubkey[0]);
1788 goto fail;
1789 }
1790
1791 secret = crypto_ecdh_set_peerkey(pasn->ecdh, inc_y,
1792 pasn_params.pubkey + 1,
1793 pasn_params.pubkey_len - 1);
Hai Shalom60840252021-02-19 19:02:11 -08001794
1795 if (!secret) {
1796 wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret");
1797 goto fail;
1798 }
1799
1800 if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
1801 wrapped_data = ieee802_11_defrag(&elems,
1802 WLAN_EID_EXTENSION,
1803 WLAN_EID_EXT_WRAPPED_DATA);
1804
1805 if (!wrapped_data) {
1806 wpa_printf(MSG_DEBUG, "PASN: Missing wrapped data");
1807 goto fail;
1808 }
1809 }
1810
1811 ret = wpas_pasn_set_pmk(wpa_s, &rsn_data, &pasn_params, wrapped_data);
1812 if (ret) {
1813 wpa_printf(MSG_DEBUG, "PASN: Failed to set PMK");
1814 goto fail;
1815 }
1816
1817 ret = pasn_pmk_to_ptk(pasn->pmk, pasn->pmk_len,
Sunil Ravi89eba102022-09-13 21:04:37 -07001818 pasn->own_addr, pasn->bssid,
Hai Shalom60840252021-02-19 19:02:11 -08001819 wpabuf_head(secret), wpabuf_len(secret),
1820 &pasn->ptk, pasn->akmp, pasn->cipher,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001821 pasn->kdk_len);
Hai Shalom60840252021-02-19 19:02:11 -08001822 if (ret) {
1823 wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
1824 goto fail;
1825 }
1826
Sunil Ravi89eba102022-09-13 21:04:37 -07001827 if (pasn->secure_ltf) {
1828 ret = wpa_ltf_keyseed(&pasn->ptk, pasn->akmp, pasn->cipher);
1829 if (ret) {
1830 wpa_printf(MSG_DEBUG,
1831 "PASN: Failed to derive LTF keyseed");
1832 goto fail;
1833 }
1834 }
1835
Hai Shalom60840252021-02-19 19:02:11 -08001836 wpabuf_free(wrapped_data);
1837 wrapped_data = NULL;
1838 wpabuf_free(secret);
1839 secret = NULL;
1840
1841 /* Verify the MIC */
1842 ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
Sunil Ravi89eba102022-09-13 21:04:37 -07001843 pasn->bssid, pasn->own_addr,
Hai Shalom60840252021-02-19 19:02:11 -08001844 wpabuf_head(pasn->beacon_rsne_rsnxe),
1845 wpabuf_len(pasn->beacon_rsne_rsnxe),
1846 (u8 *) &mgmt->u.auth,
1847 len - offsetof(struct ieee80211_mgmt, u.auth),
1848 out_mic);
1849
1850 wpa_hexdump_key(MSG_DEBUG, "PASN: Frame MIC", mic, mic_len);
1851 if (ret || os_memcmp(mic, out_mic, mic_len) != 0) {
1852 wpa_printf(MSG_DEBUG, "PASN: Failed MIC verification");
1853 goto fail;
1854 }
1855
1856 pasn->trans_seq++;
1857
1858 wpa_printf(MSG_DEBUG, "PASN: Success verifying Authentication frame");
1859
1860 frame = wpas_pasn_build_auth_3(wpa_s);
1861 if (!frame) {
1862 wpa_printf(MSG_DEBUG, "PASN: Failed building 3rd auth frame");
1863 goto fail;
1864 }
1865
1866 ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(frame), wpabuf_len(frame), 0,
1867 pasn->freq, 100);
1868 wpabuf_free(frame);
1869 if (ret) {
1870 wpa_printf(MSG_DEBUG, "PASN: Failed sending 3st auth frame");
1871 goto fail;
1872 }
1873
1874 wpa_printf(MSG_DEBUG, "PASN: Success sending last frame. Store PTK");
1875
Sunil Ravi89eba102022-09-13 21:04:37 -07001876 ptksa_cache_add(wpa_s->ptksa, pasn->own_addr, pasn->bssid,
1877 pasn->cipher, dot11RSNAConfigPMKLifetime, &pasn->ptk,
1878 wpa_s->pasn_params ? wpas_pasn_deauth_cb : NULL,
1879 wpa_s->pasn_params ? wpa_s : NULL);
Hai Shalom60840252021-02-19 19:02:11 -08001880
1881 forced_memzero(&pasn->ptk, sizeof(pasn->ptk));
1882
1883 pasn->status = WLAN_STATUS_SUCCESS;
1884 return 0;
1885fail:
1886 wpa_printf(MSG_DEBUG, "PASN: Failed RX processing - terminating");
1887 wpabuf_free(wrapped_data);
1888 wpabuf_free(secret);
1889
1890 /*
1891 * TODO: In case of an error the standard allows to silently drop
1892 * the frame and terminate the authentication exchange. However, better
1893 * reply to the AP with an error status.
1894 */
Hai Shaloma20dcd72022-02-04 13:43:00 -08001895 if (status == WLAN_STATUS_SUCCESS)
1896 pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1897 else
1898 pasn->status = status;
1899
Hai Shalom60840252021-02-19 19:02:11 -08001900 wpas_pasn_auth_stop(wpa_s);
Sunil Ravi89eba102022-09-13 21:04:37 -07001901
1902 wpas_pasn_auth_work_done(wpa_s, PASN_STATUS_FAILURE);
Hai Shalom60840252021-02-19 19:02:11 -08001903 return -1;
1904}
1905
1906
Sunil Ravi89eba102022-09-13 21:04:37 -07001907void wpas_pasn_auth_trigger(struct wpa_supplicant *wpa_s,
1908 struct pasn_auth *pasn_auth)
1909{
1910 struct pasn_peer *src, *dst;
1911 unsigned int i, num_peers = pasn_auth->num_peers;
1912
1913 if (wpa_s->pasn_params) {
1914 wpa_printf(MSG_DEBUG,
1915 "PASN: auth_trigger: Already in progress");
1916 return;
1917 }
1918
1919 if (!num_peers || num_peers > WPAS_MAX_PASN_PEERS) {
1920 wpa_printf(MSG_DEBUG,
1921 "PASN: auth trigger: Invalid number of peers");
1922 return;
1923 }
1924
1925 wpa_s->pasn_params = os_zalloc(sizeof(struct pasn_auth));
1926 if (!wpa_s->pasn_params) {
1927 wpa_printf(MSG_DEBUG,
1928 "PASN: auth trigger: Failed to allocate a buffer");
1929 return;
1930 }
1931
1932 wpa_s->pasn_count = 0;
1933 wpa_s->pasn_params->num_peers = num_peers;
1934
1935 for (i = 0; i < num_peers; i++) {
1936 dst = &wpa_s->pasn_params->peer[i];
1937 src = &pasn_auth->peer[i];
1938 os_memcpy(dst->own_addr, wpa_s->own_addr, ETH_ALEN);
1939 os_memcpy(dst->peer_addr, src->peer_addr, ETH_ALEN);
1940 dst->ltf_keyseed_required = src->ltf_keyseed_required;
1941 dst->status = PASN_STATUS_SUCCESS;
1942
1943 if (!is_zero_ether_addr(src->own_addr)) {
1944 os_memcpy(dst->own_addr, src->own_addr, ETH_ALEN);
1945 wpa_printf(MSG_DEBUG, "PASN: Own (source) MAC addr: "
1946 MACSTR, MAC2STR(dst->own_addr));
1947 }
1948 }
1949
1950 if (pasn_auth->action == PASN_ACTION_DELETE_SECURE_RANGING_CONTEXT) {
1951 wpas_pasn_delete_peers(wpa_s, wpa_s->pasn_params);
1952 os_free(wpa_s->pasn_params);
1953 wpa_s->pasn_params = NULL;
1954 } else if (pasn_auth->action == PASN_ACTION_AUTH) {
1955 wpas_pasn_configure_next_peer(wpa_s, wpa_s->pasn_params);
1956 }
1957}
1958
1959
Hai Shalom60840252021-02-19 19:02:11 -08001960int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
1961 const u8 *data, size_t data_len, u8 acked)
1962
1963{
1964 struct wpas_pasn *pasn = &wpa_s->pasn;
1965 const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) data;
1966 u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
1967 (WLAN_FC_STYPE_AUTH << 4));
1968
1969 wpa_printf(MSG_DEBUG, "PASN: auth_tx_status: acked=%u", acked);
1970
1971 if (!wpa_s->pasn_auth_work) {
1972 wpa_printf(MSG_DEBUG,
1973 "PASN: auth_tx_status: no work in progress");
1974 return -1;
1975 }
1976
1977 if (!mgmt ||
1978 data_len < offsetof(struct ieee80211_mgmt, u.auth.variable))
1979 return -1;
1980
1981 /* Not an authentication frame; do nothing */
1982 if ((mgmt->frame_control & fc) != fc)
1983 return -1;
1984
1985 /* Not our frame; do nothing */
1986 if (os_memcmp(mgmt->da, pasn->bssid, ETH_ALEN) ||
Sunil Ravi89eba102022-09-13 21:04:37 -07001987 os_memcmp(mgmt->sa, pasn->own_addr, ETH_ALEN) ||
Hai Shalom60840252021-02-19 19:02:11 -08001988 os_memcmp(mgmt->bssid, pasn->bssid, ETH_ALEN))
1989 return -1;
1990
1991 /* Not PASN; do nothing */
1992 if (mgmt->u.auth.auth_alg != host_to_le16(WLAN_AUTH_PASN))
1993 return -1;
1994
1995 if (mgmt->u.auth.auth_transaction != host_to_le16(pasn->trans_seq)) {
1996 wpa_printf(MSG_ERROR,
1997 "PASN: Invalid transaction sequence: (%u != %u)",
1998 pasn->trans_seq,
1999 le_to_host16(mgmt->u.auth.auth_transaction));
2000 return 0;
2001 }
2002
2003 wpa_printf(MSG_ERROR,
2004 "PASN: auth with trans_seq=%u, acked=%u", pasn->trans_seq,
2005 acked);
2006
2007 /*
2008 * Even if the frame was not acked, do not treat this is an error, and
2009 * try to complete the flow, relying on the PASN timeout callback to
2010 * clean up.
2011 */
2012 if (pasn->trans_seq == 3) {
2013 wpa_printf(MSG_DEBUG, "PASN: auth complete with: " MACSTR,
2014 MAC2STR(pasn->bssid));
2015 /*
2016 * Either frame was not ACKed or it was ACKed but the trans_seq
2017 * != 1, i.e., not expecting an RX frame, so we are done.
2018 */
Sunil Ravi89eba102022-09-13 21:04:37 -07002019 if (!wpa_s->pasn_params) {
2020 wpas_pasn_auth_stop(wpa_s);
2021 return 0;
2022 }
2023
2024 wpas_pasn_set_keys_from_cache(wpa_s, pasn->own_addr,
2025 pasn->bssid, pasn->cipher,
2026 pasn->akmp);
Hai Shalom60840252021-02-19 19:02:11 -08002027 wpas_pasn_auth_stop(wpa_s);
Sunil Ravi89eba102022-09-13 21:04:37 -07002028
2029 wpas_pasn_auth_work_done(wpa_s, PASN_STATUS_SUCCESS);
Hai Shalom60840252021-02-19 19:02:11 -08002030 }
2031
2032 return 0;
2033}
Hai Shaloma20dcd72022-02-04 13:43:00 -08002034
2035
Sunil Ravi89eba102022-09-13 21:04:37 -07002036int wpas_pasn_deauthenticate(struct wpa_supplicant *wpa_s, const u8 *own_addr,
2037 const u8 *bssid)
Hai Shaloma20dcd72022-02-04 13:43:00 -08002038{
2039 struct wpa_bss *bss;
2040 struct wpabuf *buf;
2041 struct ieee80211_mgmt *deauth;
2042 int ret;
2043
2044 if (os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) == 0) {
2045 wpa_printf(MSG_DEBUG,
2046 "PASN: Cannot deauthenticate from current BSS");
2047 return -1;
2048 }
2049
Sunil Ravi89eba102022-09-13 21:04:37 -07002050 wpa_drv_set_secure_ranging_ctx(wpa_s, own_addr, bssid, 0, 0, NULL, 0,
2051 NULL, 1);
2052
Hai Shaloma20dcd72022-02-04 13:43:00 -08002053 wpa_printf(MSG_DEBUG, "PASN: deauth: Flushing all PTKSA entries for "
2054 MACSTR, MAC2STR(bssid));
2055 ptksa_cache_flush(wpa_s->ptksa, bssid, WPA_CIPHER_NONE);
2056
2057 bss = wpa_bss_get_bssid(wpa_s, bssid);
2058 if (!bss) {
2059 wpa_printf(MSG_DEBUG, "PASN: deauth: BSS not found");
2060 return -1;
2061 }
2062
2063 buf = wpabuf_alloc(64);
2064 if (!buf) {
2065 wpa_printf(MSG_DEBUG, "PASN: deauth: Failed wpabuf allocate");
2066 return -1;
2067 }
2068
2069 deauth = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
2070 u.deauth.variable));
2071
2072 deauth->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
2073 (WLAN_FC_STYPE_DEAUTH << 4));
2074
2075 os_memcpy(deauth->da, bssid, ETH_ALEN);
Sunil Ravi89eba102022-09-13 21:04:37 -07002076 os_memcpy(deauth->sa, own_addr, ETH_ALEN);
Hai Shaloma20dcd72022-02-04 13:43:00 -08002077 os_memcpy(deauth->bssid, bssid, ETH_ALEN);
2078 deauth->u.deauth.reason_code =
2079 host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
2080
2081 /*
2082 * Since we do not expect any response from the AP, implement the
2083 * Deauthentication frame transmission using direct call to the driver
2084 * without a radio work.
2085 */
2086 ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1,
2087 bss->freq, 0);
2088
2089 wpabuf_free(buf);
2090 wpa_printf(MSG_DEBUG, "PASN: deauth: send_mlme ret=%d", ret);
2091
2092 return ret;
2093}