blob: e344898df2935dac923cdbe7c5e9c3ae249236de [file] [log] [blame]
Sunil Ravi77d572f2023-01-17 23:58:31 +00001/*
2 * PASN responder processing
3 *
4 * Copyright (C) 2019, Intel Corporation
5 * Copyright (C) 2022, Qualcomm Innovation Center, Inc.
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "utils/includes.h"
12
13#include "utils/common.h"
14#include "common/wpa_common.h"
15#include "common/sae.h"
16#include "common/ieee802_11_common.h"
17#include "common/ieee802_11_defs.h"
18#include "crypto/sha384.h"
19#include "crypto/sha256.h"
20#include "crypto/random.h"
21#include "crypto/crypto.h"
22#include "ap/hostapd.h"
23#include "ap/comeback_token.h"
24#include "ap/ieee802_1x.h"
25#include "ap/pmksa_cache_auth.h"
26#include "pasn_common.h"
27
Sunil Ravi99c035e2024-07-12 01:42:03 +000028
Sunil Ravic0f5d412024-09-11 22:12:49 +000029struct rsn_pmksa_cache * pasn_responder_pmksa_cache_init(void)
30{
31 return pmksa_cache_auth_init(NULL, NULL);
32}
33
34
35void pasn_responder_pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
36{
37 return pmksa_cache_auth_deinit(pmksa);
38}
39
40
41int pasn_responder_pmksa_cache_add(struct rsn_pmksa_cache *pmksa,
42 const u8 *own_addr, const u8 *bssid, u8 *pmk,
43 size_t pmk_len, u8 *pmkid)
44{
45 if (pmksa_cache_auth_add(pmksa, pmk, pmk_len, pmkid, NULL, 0, own_addr,
46 bssid, 0, NULL, WPA_KEY_MGMT_SAE))
47 return 0;
48 return -1;
49}
50
51
52int pasn_responder_pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
53 const u8 *bssid, u8 *pmkid, u8 *pmk,
54 size_t *pmk_len)
55{
56 struct rsn_pmksa_cache_entry *entry;
57
58 entry = pmksa_cache_auth_get(pmksa, bssid, NULL);
59 if (entry) {
60 os_memcpy(pmkid, entry->pmkid, PMKID_LEN);
61 os_memcpy(pmk, entry->pmk, entry->pmk_len);
62 *pmk_len = entry->pmk_len;
63 return 0;
64 }
65 return -1;
66}
67
68
69void pasn_responder_pmksa_cache_remove(struct rsn_pmksa_cache *pmksa,
70 const u8 *bssid)
71{
72 struct rsn_pmksa_cache_entry *entry;
73
74 entry = pmksa_cache_auth_get(pmksa, bssid, NULL);
75 if (!entry)
76 return;
77
78 pmksa_cache_free_entry(pmksa, entry);
79}
80
81
82void pasn_responder_pmksa_cache_flush(struct rsn_pmksa_cache *pmksa)
83{
84 return pmksa_cache_auth_flush(pmksa);
85}
86
87
Sunil Ravi99c035e2024-07-12 01:42:03 +000088void pasn_set_responder_pmksa(struct pasn_data *pasn,
89 struct rsn_pmksa_cache *pmksa)
90{
91 if (pasn)
92 pasn->pmksa = pmksa;
93}
94
95
Sunil Ravi77d572f2023-01-17 23:58:31 +000096#ifdef CONFIG_PASN
97#ifdef CONFIG_SAE
98
99static int pasn_wd_handle_sae_commit(struct pasn_data *pasn,
100 const u8 *own_addr, const u8 *peer_addr,
101 struct wpabuf *wd)
102{
103 const u8 *data;
104 size_t buf_len;
105 u16 res, alg, seq, status;
106 int groups[] = { pasn->group, 0 };
107 int ret;
108
109 if (!wd)
110 return -1;
111
112 data = wpabuf_head_u8(wd);
113 buf_len = wpabuf_len(wd);
114
115 if (buf_len < 6) {
116 wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short. len=%zu",
117 buf_len);
118 return -1;
119 }
120
121 alg = WPA_GET_LE16(data);
122 seq = WPA_GET_LE16(data + 2);
123 status = WPA_GET_LE16(data + 4);
124
125 wpa_printf(MSG_DEBUG, "PASN: SAE commit: alg=%u, seq=%u, status=%u",
126 alg, seq, status);
127
128 if (alg != WLAN_AUTH_SAE || seq != 1 ||
129 status != WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
130 wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE commit");
131 return -1;
132 }
133
134 sae_clear_data(&pasn->sae);
135 pasn->sae.state = SAE_NOTHING;
136
137 ret = sae_set_group(&pasn->sae, pasn->group);
138 if (ret) {
139 wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
140 return -1;
141 }
142
143 if (!pasn->password || !pasn->pt) {
144 wpa_printf(MSG_DEBUG, "PASN: No SAE PT found");
145 return -1;
146 }
147
148 ret = sae_prepare_commit_pt(&pasn->sae, pasn->pt, own_addr, peer_addr,
149 NULL, NULL);
150 if (ret) {
151 wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
152 return -1;
153 }
154
155 res = sae_parse_commit(&pasn->sae, data + 6, buf_len - 6, NULL, 0,
156 groups, 0, NULL);
157 if (res != WLAN_STATUS_SUCCESS) {
158 wpa_printf(MSG_DEBUG, "PASN: Failed parsing SAE commit");
159 return -1;
160 }
161
162 /* Process the commit message and derive the PMK */
163 ret = sae_process_commit(&pasn->sae);
164 if (ret) {
165 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer commit");
166 return -1;
167 }
168
169 pasn->sae.state = SAE_COMMITTED;
170
171 return 0;
172}
173
174
175static int pasn_wd_handle_sae_confirm(struct pasn_data *pasn,
176 const u8 *peer_addr, struct wpabuf *wd)
177{
178 const u8 *data;
179 size_t buf_len;
180 u16 res, alg, seq, status;
181
182 if (!wd)
183 return -1;
184
185 data = wpabuf_head_u8(wd);
186 buf_len = wpabuf_len(wd);
187
188 if (buf_len < 6) {
189 wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short. len=%zu",
190 buf_len);
191 return -1;
192 }
193
194 alg = WPA_GET_LE16(data);
195 seq = WPA_GET_LE16(data + 2);
196 status = WPA_GET_LE16(data + 4);
197
198 wpa_printf(MSG_DEBUG, "PASN: SAE confirm: alg=%u, seq=%u, status=%u",
199 alg, seq, status);
200
201 if (alg != WLAN_AUTH_SAE || seq != 2 || status != WLAN_STATUS_SUCCESS) {
202 wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE confirm");
203 return -1;
204 }
205
206 res = sae_check_confirm(&pasn->sae, data + 6, buf_len - 6, NULL);
207 if (res != WLAN_STATUS_SUCCESS) {
208 wpa_printf(MSG_DEBUG, "PASN: SAE failed checking confirm");
209 return -1;
210 }
211
212 pasn->sae.state = SAE_ACCEPTED;
213
214 /*
215 * TODO: Based on on IEEE P802.11az/D2.6, the PMKSA derived with
216 * PASN/SAE should only be allowed with future PASN only. For now do not
217 * restrict this only for PASN.
218 */
219 if (pasn->disable_pmksa_caching)
220 return 0;
221
222 wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE",
223 pasn->sae.pmk, pasn->sae.pmk_len);
224 if (!pasn->sae.akmp)
225 pasn->sae.akmp = WPA_KEY_MGMT_SAE;
226
227 pmksa_cache_auth_add(pasn->pmksa, pasn->sae.pmk, pasn->sae.pmk_len,
228 pasn->sae.pmkid, NULL, 0, pasn->own_addr,
229 peer_addr, 0, NULL, pasn->sae.akmp);
230 return 0;
231}
232
233
234static struct wpabuf * pasn_get_sae_wd(struct pasn_data *pasn)
235{
236 struct wpabuf *buf = NULL;
237 u8 *len_ptr;
238 size_t len;
239
240 /* Need to add the entire Authentication frame body */
241 buf = wpabuf_alloc(8 + SAE_COMMIT_MAX_LEN + 8 + SAE_CONFIRM_MAX_LEN);
242 if (!buf) {
243 wpa_printf(MSG_DEBUG, "PASN: Failed to allocate SAE buffer");
244 return NULL;
245 }
246
247 /* Need to add the entire authentication frame body for the commit */
248 len_ptr = wpabuf_put(buf, 2);
249 wpabuf_put_le16(buf, WLAN_AUTH_SAE);
250 wpabuf_put_le16(buf, 1);
251 wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
252
253 /* Write the actual commit and update the length accordingly */
254 sae_write_commit(&pasn->sae, buf, NULL, 0);
255 len = wpabuf_len(buf);
256 WPA_PUT_LE16(len_ptr, len - 2);
257
258 /* Need to add the entire Authentication frame body for the confirm */
259 len_ptr = wpabuf_put(buf, 2);
260 wpabuf_put_le16(buf, WLAN_AUTH_SAE);
261 wpabuf_put_le16(buf, 2);
262 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
263
264 sae_write_confirm(&pasn->sae, buf);
265 WPA_PUT_LE16(len_ptr, wpabuf_len(buf) - len - 2);
266
267 pasn->sae.state = SAE_CONFIRMED;
268
269 return buf;
270}
271
272#endif /* CONFIG_SAE */
273
274
275#ifdef CONFIG_FILS
276
277static struct wpabuf * pasn_get_fils_wd(struct pasn_data *pasn)
278{
279 struct pasn_fils *fils = &pasn->fils;
280 struct wpabuf *buf = NULL;
281
282 if (!fils->erp_resp) {
283 wpa_printf(MSG_DEBUG, "PASN: FILS: Missing erp_resp");
284 return NULL;
285 }
286
287 buf = wpabuf_alloc(1500);
288 if (!buf)
289 return NULL;
290
291 /* Add the authentication algorithm */
292 wpabuf_put_le16(buf, WLAN_AUTH_FILS_SK);
293
294 /* Authentication Transaction seq# */
295 wpabuf_put_le16(buf, 2);
296
297 /* Status Code */
298 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
299
300 /* Own RSNE */
301 wpa_pasn_add_rsne(buf, NULL, pasn->akmp, pasn->cipher);
302
303 /* FILS Nonce */
304 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
305 wpabuf_put_u8(buf, 1 + FILS_NONCE_LEN);
306 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_NONCE);
307 wpabuf_put_data(buf, fils->anonce, FILS_NONCE_LEN);
308
309 /* FILS Session */
310 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
311 wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN);
312 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
313 wpabuf_put_data(buf, fils->session, FILS_SESSION_LEN);
314
315 /* Wrapped Data */
316 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
317 wpabuf_put_u8(buf, 1 + wpabuf_len(fils->erp_resp));
318 wpabuf_put_u8(buf, WLAN_EID_EXT_WRAPPED_DATA);
319 wpabuf_put_buf(buf, fils->erp_resp);
320
321 return buf;
322}
323
324#endif /* CONFIG_FILS */
325
326static struct wpabuf * pasn_get_wrapped_data(struct pasn_data *pasn)
327{
328 switch (pasn->akmp) {
329 case WPA_KEY_MGMT_PASN:
330 /* no wrapped data */
331 return NULL;
332 case WPA_KEY_MGMT_SAE:
333#ifdef CONFIG_SAE
334 return pasn_get_sae_wd(pasn);
335#else /* CONFIG_SAE */
336 wpa_printf(MSG_ERROR,
337 "PASN: SAE: Cannot derive wrapped data");
338 return NULL;
339#endif /* CONFIG_SAE */
340 case WPA_KEY_MGMT_FILS_SHA256:
341 case WPA_KEY_MGMT_FILS_SHA384:
342#ifdef CONFIG_FILS
343 return pasn_get_fils_wd(pasn);
344#endif /* CONFIG_FILS */
345 /* fall through */
346 case WPA_KEY_MGMT_FT_PSK:
347 case WPA_KEY_MGMT_FT_IEEE8021X:
348 case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
349 default:
350 wpa_printf(MSG_ERROR,
351 "PASN: TODO: Wrapped data for akmp=0x%x",
352 pasn->akmp);
353 return NULL;
354 }
355}
356
357
358static int
359pasn_derive_keys(struct pasn_data *pasn,
360 const u8 *own_addr, const u8 *peer_addr,
361 const u8 *cached_pmk, size_t cached_pmk_len,
362 struct wpa_pasn_params_data *pasn_data,
363 struct wpabuf *wrapped_data,
364 struct wpabuf *secret)
365{
366 static const u8 pasn_default_pmk[] = {'P', 'M', 'K', 'z'};
367 u8 pmk[PMK_LEN_MAX];
368 u8 pmk_len;
369 int ret;
370
371 os_memset(pmk, 0, sizeof(pmk));
372 pmk_len = 0;
373
374 if (!cached_pmk || !cached_pmk_len)
375 wpa_printf(MSG_DEBUG, "PASN: No valid PMKSA entry");
376
377 if (pasn->akmp == WPA_KEY_MGMT_PASN) {
378 wpa_printf(MSG_DEBUG, "PASN: Using default PMK");
379
380 pmk_len = WPA_PASN_PMK_LEN;
381 os_memcpy(pmk, pasn_default_pmk, sizeof(pasn_default_pmk));
382 } else if (cached_pmk && cached_pmk_len) {
383 wpa_printf(MSG_DEBUG, "PASN: Using PMKSA entry");
384
385 pmk_len = cached_pmk_len;
386 os_memcpy(pmk, cached_pmk, cached_pmk_len);
387 } else {
388 switch (pasn->akmp) {
389#ifdef CONFIG_SAE
390 case WPA_KEY_MGMT_SAE:
391 if (pasn->sae.state == SAE_COMMITTED) {
392 pmk_len = PMK_LEN;
393 os_memcpy(pmk, pasn->sae.pmk, PMK_LEN);
394 break;
395 }
396#endif /* CONFIG_SAE */
397 /* fall through */
398 default:
399 /* TODO: Derive PMK based on wrapped data */
400 wpa_printf(MSG_DEBUG,
401 "PASN: Missing PMK derivation");
402 return -1;
403 }
404 }
405
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000406 pasn->pmk_len = pmk_len;
407 os_memcpy(pasn->pmk, pmk, pmk_len);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000408 ret = pasn_pmk_to_ptk(pmk, pmk_len, peer_addr, own_addr,
409 wpabuf_head(secret), wpabuf_len(secret),
410 &pasn->ptk, pasn->akmp,
Sunil Ravic0f5d412024-09-11 22:12:49 +0000411 pasn->cipher, pasn->kdk_len, pasn->kek_len);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000412 if (ret) {
413 wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
414 return -1;
415 }
416
417 if (pasn->secure_ltf) {
418 ret = wpa_ltf_keyseed(&pasn->ptk, pasn->akmp,
419 pasn->cipher);
420 if (ret) {
421 wpa_printf(MSG_DEBUG,
422 "PASN: Failed to derive LTF keyseed");
423 return -1;
424 }
425 }
426
427 wpa_printf(MSG_DEBUG, "PASN: PTK successfully derived");
428 return 0;
429}
430
431
432static void handle_auth_pasn_comeback(struct pasn_data *pasn,
433 const u8 *own_addr, const u8 *peer_addr,
434 u16 group)
435{
436 struct wpabuf *buf, *comeback;
437 int ret;
438
439 wpa_printf(MSG_DEBUG,
440 "PASN: Building comeback frame 2. Comeback after=%u",
441 pasn->comeback_after);
442
443 buf = wpabuf_alloc(1500);
444 if (!buf)
445 return;
446
447 wpa_pasn_build_auth_header(buf, pasn->bssid, own_addr, peer_addr, 2,
448 WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY);
449
450 /*
451 * Do not include the group as a part of the token since it is not going
452 * to be used.
453 */
454 comeback = auth_build_token_req(&pasn->last_comeback_key_update,
455 pasn->comeback_key, pasn->comeback_idx,
456 pasn->comeback_pending_idx,
457 sizeof(u16) * COMEBACK_PENDING_IDX_SIZE,
458 0, peer_addr, 0);
459 if (!comeback) {
460 wpa_printf(MSG_DEBUG,
461 "PASN: Failed sending auth with comeback");
462 wpabuf_free(buf);
463 return;
464 }
465
466 wpa_pasn_add_parameter_ie(buf, group,
467 WPA_PASN_WRAPPED_DATA_NO,
468 NULL, 0, comeback,
469 pasn->comeback_after);
470 wpabuf_free(comeback);
471
472 wpa_printf(MSG_DEBUG,
473 "PASN: comeback: STA=" MACSTR, MAC2STR(peer_addr));
474
475 ret = pasn->send_mgmt(pasn->cb_ctx, wpabuf_head_u8(buf),
Sunil Ravic0f5d412024-09-11 22:12:49 +0000476 wpabuf_len(buf), 0, pasn->freq, 0);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000477 if (ret)
478 wpa_printf(MSG_INFO, "PASN: Failed to send comeback frame 2");
479
480 wpabuf_free(buf);
481}
482
483
484int handle_auth_pasn_resp(struct pasn_data *pasn, const u8 *own_addr,
485 const u8 *peer_addr,
486 struct rsn_pmksa_cache_entry *pmksa, u16 status)
487{
488 struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
489 struct wpabuf *rsn_buf = NULL;
490 u8 mic[WPA_PASN_MAX_MIC_LEN];
491 u8 mic_len;
492 u8 *ptr;
493 const u8 *frame, *data, *rsn_ie, *rsnxe_ie;
494 u8 *data_buf = NULL;
495 size_t frame_len, data_len;
496 int ret;
497 const u8 *pmkid = NULL;
498
499 wpa_printf(MSG_DEBUG, "PASN: Building frame 2: status=%u", status);
500
501 buf = wpabuf_alloc(1500);
502 if (!buf)
503 goto fail;
504
505 wpa_pasn_build_auth_header(buf, pasn->bssid, own_addr, peer_addr, 2,
506 status);
507
508 if (status != WLAN_STATUS_SUCCESS)
509 goto done;
510
511 if (pmksa && pasn->custom_pmkid_valid)
512 pmkid = pasn->custom_pmkid;
513 else if (pmksa) {
514 pmkid = pmksa->pmkid;
515#ifdef CONFIG_SAE
516 } else if (pasn->akmp == WPA_KEY_MGMT_SAE) {
517 wpa_printf(MSG_DEBUG, "PASN: Use SAE PMKID");
518 pmkid = pasn->sae.pmkid;
519#endif /* CONFIG_SAE */
520#ifdef CONFIG_FILS
521 } else if (pasn->akmp == WPA_KEY_MGMT_FILS_SHA256 ||
522 pasn->akmp == WPA_KEY_MGMT_FILS_SHA384) {
523 wpa_printf(MSG_DEBUG, "PASN: Use FILS ERP PMKID");
524 pmkid = pasn->fils.erp_pmkid;
525#endif /* CONFIG_FILS */
526 }
527
528 if (wpa_pasn_add_rsne(buf, pmkid,
529 pasn->akmp, pasn->cipher) < 0)
530 goto fail;
531
532 /* No need to derive PMK if PMKSA is given */
533 if (!pmksa)
534 wrapped_data_buf = pasn_get_wrapped_data(pasn);
535 else
536 pasn->wrapped_data_format = WPA_PASN_WRAPPED_DATA_NO;
537
538 /* Get public key */
539 pubkey = crypto_ecdh_get_pubkey(pasn->ecdh, 0);
540 pubkey = wpabuf_zeropad(pubkey,
541 crypto_ecdh_prime_len(pasn->ecdh));
542 if (!pubkey) {
543 wpa_printf(MSG_DEBUG, "PASN: Failed to get pubkey");
544 goto fail;
545 }
546
547 wpa_pasn_add_parameter_ie(buf, pasn->group,
548 pasn->wrapped_data_format,
549 pubkey, true, NULL, 0);
550
551 if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
552 goto fail;
553
554 wpabuf_free(wrapped_data_buf);
555 wrapped_data_buf = NULL;
556 wpabuf_free(pubkey);
557 pubkey = NULL;
558
559 /* Add RSNXE if needed */
560 rsnxe_ie = pasn->rsnxe_ie;
561 if (rsnxe_ie)
562 wpabuf_put_data(buf, rsnxe_ie, 2 + rsnxe_ie[1]);
563
564 wpa_pasn_add_extra_ies(buf, pasn->extra_ies, pasn->extra_ies_len);
565
566 /* Add the mic */
567 mic_len = pasn_mic_len(pasn->akmp, pasn->cipher);
568 wpabuf_put_u8(buf, WLAN_EID_MIC);
569 wpabuf_put_u8(buf, mic_len);
570 ptr = wpabuf_put(buf, mic_len);
571
572 os_memset(ptr, 0, mic_len);
573
574 frame = wpabuf_head_u8(buf) + IEEE80211_HDRLEN;
575 frame_len = wpabuf_len(buf) - IEEE80211_HDRLEN;
576
577 if (pasn->rsn_ie && pasn->rsn_ie_len) {
578 rsn_ie = pasn->rsn_ie;
579 } else {
580 /*
581 * Note: when pasn->rsn_ie is NULL, it is likely that Beacon
582 * frame RSNE is not initialized. This is possible in case of
583 * PASN authentication used for Wi-Fi Aware for which Beacon
584 * frame RSNE and RSNXE are same as RSNE and RSNXE in the
585 * Authentication frame.
586 */
587 rsn_buf = wpabuf_alloc(500);
588 if (!rsn_buf)
589 goto fail;
590
591 if (wpa_pasn_add_rsne(rsn_buf, pmkid,
592 pasn->akmp, pasn->cipher) < 0)
593 goto fail;
594
595 rsn_ie = wpabuf_head_u8(rsn_buf);
596 }
597
598 /*
599 * Note: wpa_auth_get_wpa_ie() might return not only the RSNE but also
600 * MDE, etc. Thus, do not use the returned length but instead use the
601 * length specified in the IE header.
602 */
603 data_len = rsn_ie[1] + 2;
604 if (rsnxe_ie) {
605 data_buf = os_zalloc(rsn_ie[1] + 2 + rsnxe_ie[1] + 2);
606 if (!data_buf)
607 goto fail;
608
609 os_memcpy(data_buf, rsn_ie, rsn_ie[1] + 2);
610 os_memcpy(data_buf + rsn_ie[1] + 2, rsnxe_ie, rsnxe_ie[1] + 2);
611 data_len += rsnxe_ie[1] + 2;
612 data = data_buf;
613 } else {
614 data = rsn_ie;
615 }
616
617 ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
618 own_addr, peer_addr, data, data_len,
619 frame, frame_len, mic);
620 os_free(data_buf);
621 if (ret) {
622 wpa_printf(MSG_DEBUG, "PASN: Frame 3: Failed MIC calculation");
623 goto fail;
624 }
625
626#ifdef CONFIG_TESTING_OPTIONS
627 if (pasn->corrupt_mic) {
628 wpa_printf(MSG_DEBUG, "PASN: frame 2: Corrupt MIC");
629 mic[0] = ~mic[0];
630 }
631#endif /* CONFIG_TESTING_OPTIONS */
632
633 os_memcpy(ptr, mic, mic_len);
634
635done:
636 wpa_printf(MSG_DEBUG,
637 "PASN: Building frame 2: success; resp STA=" MACSTR,
638 MAC2STR(peer_addr));
639
640 ret = pasn->send_mgmt(pasn->cb_ctx, wpabuf_head_u8(buf),
Sunil Ravic0f5d412024-09-11 22:12:49 +0000641 wpabuf_len(buf), 0, pasn->freq, 0);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000642 if (ret)
643 wpa_printf(MSG_INFO, "send_auth_reply: Send failed");
644
645 wpabuf_free(rsn_buf);
646 wpabuf_free(buf);
647 return ret;
648fail:
649 wpabuf_free(wrapped_data_buf);
650 wpabuf_free(pubkey);
651 wpabuf_free(rsn_buf);
652 wpabuf_free(buf);
653 return -1;
654}
655
656
657int handle_auth_pasn_1(struct pasn_data *pasn,
658 const u8 *own_addr, const u8 *peer_addr,
Sunil Ravic0f5d412024-09-11 22:12:49 +0000659 const struct ieee80211_mgmt *mgmt, size_t len,
660 bool reject)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000661{
662 struct ieee802_11_elems elems;
663 struct wpa_ie_data rsn_data;
664 struct wpa_pasn_params_data pasn_params;
665 struct rsn_pmksa_cache_entry *pmksa = NULL;
666 const u8 *cached_pmk = NULL;
667 size_t cached_pmk_len = 0;
668 struct wpabuf *wrapped_data = NULL, *secret = NULL;
669 const int *groups = pasn->pasn_groups;
670 static const int default_groups[] = { 19, 0 };
671 u16 status = WLAN_STATUS_SUCCESS;
672 int ret, inc_y;
673 bool derive_keys;
674 u32 i;
675
676 if (!groups)
677 groups = default_groups;
678
Sunil Ravic0f5d412024-09-11 22:12:49 +0000679 if (reject) {
680 wpa_printf(MSG_DEBUG, "PASN: Received Rejection");
681 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
682 goto send_resp;
683 }
684
Sunil Ravi77d572f2023-01-17 23:58:31 +0000685 if (ieee802_11_parse_elems(mgmt->u.auth.variable,
686 len - offsetof(struct ieee80211_mgmt,
687 u.auth.variable),
688 &elems, 0) == ParseFailed) {
689 wpa_printf(MSG_DEBUG,
690 "PASN: Failed parsing Authentication frame");
691 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
692 goto send_resp;
693 }
694
695 if (!elems.rsn_ie) {
696 wpa_printf(MSG_DEBUG, "PASN: No RSNE");
697 status = WLAN_STATUS_INVALID_RSNIE;
698 goto send_resp;
699 }
700
701 ret = wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
702 &rsn_data);
703 if (ret) {
704 wpa_printf(MSG_DEBUG, "PASN: Failed parsing RSNE");
705 status = WLAN_STATUS_INVALID_RSNIE;
706 goto send_resp;
707 }
708
709 ret = wpa_pasn_validate_rsne(&rsn_data);
710 if (ret) {
711 wpa_printf(MSG_DEBUG, "PASN: Failed validating RSNE");
712 status = WLAN_STATUS_INVALID_RSNIE;
713 goto send_resp;
714 }
715
716 if (!(rsn_data.key_mgmt & pasn->wpa_key_mgmt) ||
717 !(rsn_data.pairwise_cipher & pasn->rsn_pairwise)) {
718 wpa_printf(MSG_DEBUG, "PASN: Mismatch in AKMP/cipher");
719 status = WLAN_STATUS_INVALID_RSNIE;
720 goto send_resp;
721 }
722
723 pasn->akmp = rsn_data.key_mgmt;
724 pasn->cipher = rsn_data.pairwise_cipher;
725
726 if (pasn->derive_kdk &&
727 ieee802_11_rsnx_capab_len(elems.rsnxe, elems.rsnxe_len,
728 WLAN_RSNX_CAPAB_SECURE_LTF))
729 pasn->secure_ltf = true;
730
731 if (pasn->derive_kdk)
732 pasn->kdk_len = WPA_KDK_MAX_LEN;
733 else
734 pasn->kdk_len = 0;
735
736 wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", pasn->kdk_len);
737
738 if (!elems.pasn_params || !elems.pasn_params_len) {
739 wpa_printf(MSG_DEBUG,
740 "PASN: No PASN Parameters element found");
741 status = WLAN_STATUS_INVALID_PARAMETERS;
742 goto send_resp;
743 }
744
745 ret = wpa_pasn_parse_parameter_ie(elems.pasn_params - 3,
746 elems.pasn_params_len + 3,
747 false, &pasn_params);
748 if (ret) {
749 wpa_printf(MSG_DEBUG,
750 "PASN: Failed validation of PASN Parameters IE");
751 status = WLAN_STATUS_INVALID_PARAMETERS;
752 goto send_resp;
753 }
754
755 for (i = 0; groups[i] > 0 && groups[i] != pasn_params.group; i++)
756 ;
757
758 if (!pasn_params.group || groups[i] != pasn_params.group) {
759 wpa_printf(MSG_DEBUG, "PASN: Requested group=%hu not allowed",
760 pasn_params.group);
761 status = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
762 goto send_resp;
763 }
764
765 if (!pasn_params.pubkey || !pasn_params.pubkey_len) {
766 wpa_printf(MSG_DEBUG, "PASN: Invalid public key");
767 status = WLAN_STATUS_INVALID_PARAMETERS;
768 goto send_resp;
769 }
770
771 if (pasn_params.comeback) {
772 wpa_printf(MSG_DEBUG, "PASN: Checking peer comeback token");
773
774 ret = check_comeback_token(pasn->comeback_key,
775 pasn->comeback_pending_idx,
776 peer_addr,
777 pasn_params.comeback,
778 pasn_params.comeback_len);
779
780 if (ret) {
781 wpa_printf(MSG_DEBUG, "PASN: Invalid comeback token");
782 status = WLAN_STATUS_INVALID_PARAMETERS;
783 goto send_resp;
784 }
785 } else if (pasn->use_anti_clogging) {
786 wpa_printf(MSG_DEBUG, "PASN: Respond with comeback");
787 handle_auth_pasn_comeback(pasn, own_addr, peer_addr,
788 pasn_params.group);
789 return -1;
790 }
791
792 pasn->ecdh = crypto_ecdh_init(pasn_params.group);
793 if (!pasn->ecdh) {
794 wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
795 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
796 goto send_resp;
797 }
798
799 pasn->group = pasn_params.group;
800
801 if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_UNCOMPRESSED) {
802 inc_y = 1;
803 } else if (pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_0 ||
804 pasn_params.pubkey[0] == WPA_PASN_PUBKEY_COMPRESSED_1) {
805 inc_y = 0;
806 } else {
807 wpa_printf(MSG_DEBUG,
808 "PASN: Invalid first octet in pubkey=0x%x",
809 pasn_params.pubkey[0]);
810 status = WLAN_STATUS_INVALID_PUBLIC_KEY;
811 goto send_resp;
812 }
813
814 secret = crypto_ecdh_set_peerkey(pasn->ecdh, inc_y,
815 pasn_params.pubkey + 1,
816 pasn_params.pubkey_len - 1);
817 if (!secret) {
818 wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret");
819 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
820 goto send_resp;
821 }
822
Sunil Ravi640215c2023-06-28 23:08:09 +0000823 if (!pasn->noauth && pasn->akmp == WPA_KEY_MGMT_PASN) {
824 wpa_printf(MSG_DEBUG, "PASN: Refuse PASN-UNAUTH");
825 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
826 goto send_resp;
827 }
828
Sunil Ravi77d572f2023-01-17 23:58:31 +0000829 derive_keys = true;
830 if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000831 wrapped_data = ieee802_11_defrag(elems.wrapped_data,
832 elems.wrapped_data_len, true);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000833 if (!wrapped_data) {
834 wpa_printf(MSG_DEBUG, "PASN: Missing wrapped data");
835 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
836 goto send_resp;
837 }
838
839#ifdef CONFIG_SAE
840 if (pasn->akmp == WPA_KEY_MGMT_SAE) {
841 ret = pasn_wd_handle_sae_commit(pasn, own_addr,
842 peer_addr,
843 wrapped_data);
844 if (ret) {
845 wpa_printf(MSG_DEBUG,
846 "PASN: Failed processing SAE commit");
847 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
848 goto send_resp;
849 }
850 }
851#endif /* CONFIG_SAE */
852#ifdef CONFIG_FILS
853 if (pasn->akmp == WPA_KEY_MGMT_FILS_SHA256 ||
854 pasn->akmp == WPA_KEY_MGMT_FILS_SHA384) {
855 if (!pasn->fils_wd_valid) {
856 wpa_printf(MSG_DEBUG,
857 "PASN: Invalid FILS wrapped data");
858 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
859 goto send_resp;
860 }
861
862 wpa_printf(MSG_DEBUG,
863 "PASN: FILS: Pending AS response");
864
865 /*
866 * With PASN/FILS, keys can be derived only after a
867 * response from the AS is processed.
868 */
869 derive_keys = false;
870 }
871#endif /* CONFIG_FILS */
872 }
873
874 pasn->wrapped_data_format = pasn_params.wrapped_data_format;
875
876 ret = pasn_auth_frame_hash(pasn->akmp, pasn->cipher,
877 ((const u8 *) mgmt) + IEEE80211_HDRLEN,
878 len - IEEE80211_HDRLEN, pasn->hash);
879 if (ret) {
880 wpa_printf(MSG_DEBUG, "PASN: Failed to compute hash");
881 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
882 goto send_resp;
883 }
884
885 if (!derive_keys) {
886 wpa_printf(MSG_DEBUG, "PASN: Storing secret");
887 pasn->secret = secret;
888 wpabuf_free(wrapped_data);
889 return 0;
890 }
891
892 if (rsn_data.num_pmkid) {
893 if (wpa_key_mgmt_ft(pasn->akmp)) {
894#ifdef CONFIG_IEEE80211R_AP
895 wpa_printf(MSG_DEBUG, "PASN: FT: Fetch PMK-R1");
896
897 if (!pasn->pmk_r1_len) {
898 wpa_printf(MSG_DEBUG,
899 "PASN: FT: Failed getting PMK-R1");
900 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
901 goto send_resp;
902 }
903 cached_pmk = pasn->pmk_r1;
904 cached_pmk_len = pasn->pmk_r1_len;
905#else /* CONFIG_IEEE80211R_AP */
906 wpa_printf(MSG_DEBUG, "PASN: FT: Not supported");
907 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
908 goto send_resp;
909#endif /* CONFIG_IEEE80211R_AP */
910 } else {
911 wpa_printf(MSG_DEBUG, "PASN: Try to find PMKSA entry");
912
913 if (pasn->pmksa) {
914 const u8 *pmkid = NULL;
915
916 if (pasn->custom_pmkid_valid) {
917 ret = pasn->validate_custom_pmkid(
918 pasn->cb_ctx, peer_addr,
919 rsn_data.pmkid);
920 if (ret) {
921 wpa_printf(MSG_DEBUG,
922 "PASN: Failed custom PMKID validation");
923 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
924 goto send_resp;
925 }
926 } else {
927 pmkid = rsn_data.pmkid;
928 }
929
930 pmksa = pmksa_cache_auth_get(pasn->pmksa,
931 peer_addr,
932 pmkid);
933 if (pmksa) {
934 cached_pmk = pmksa->pmk;
935 cached_pmk_len = pmksa->pmk_len;
936 }
937 }
938 }
939 } else {
940 wpa_printf(MSG_DEBUG, "PASN: No PMKID specified");
941 }
942
943 ret = pasn_derive_keys(pasn, own_addr, peer_addr,
944 cached_pmk, cached_pmk_len,
945 &pasn_params, wrapped_data, secret);
946 if (ret) {
947 wpa_printf(MSG_DEBUG, "PASN: Failed to derive keys");
948 status = WLAN_STATUS_PASN_BASE_AKMP_FAILED;
949 goto send_resp;
950 }
951
952 ret = pasn_auth_frame_hash(pasn->akmp, pasn->cipher,
953 ((const u8 *) mgmt) + IEEE80211_HDRLEN,
954 len - IEEE80211_HDRLEN, pasn->hash);
955 if (ret) {
956 wpa_printf(MSG_DEBUG, "PASN: Failed to compute hash");
957 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
958 }
959
960send_resp:
961 ret = handle_auth_pasn_resp(pasn, own_addr, peer_addr, pmksa, status);
962 if (ret) {
963 wpa_printf(MSG_DEBUG, "PASN: Failed to send response");
964 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
965 } else {
966 wpa_printf(MSG_DEBUG,
967 "PASN: Success handling transaction == 1");
968 }
969
970 wpabuf_free(secret);
971 wpabuf_free(wrapped_data);
972
973 if (status != WLAN_STATUS_SUCCESS)
974 return -1;
975
976 return 0;
977}
978
979
980int handle_auth_pasn_3(struct pasn_data *pasn, const u8 *own_addr,
981 const u8 *peer_addr,
982 const struct ieee80211_mgmt *mgmt, size_t len)
983{
984 struct ieee802_11_elems elems;
985 struct wpa_pasn_params_data pasn_params;
986 struct wpabuf *wrapped_data = NULL;
987 u8 mic[WPA_PASN_MAX_MIC_LEN], out_mic[WPA_PASN_MAX_MIC_LEN];
988 u8 mic_len;
989 int ret;
990 u8 *copy = NULL;
991 size_t copy_len, mic_offset;
992
993 if (ieee802_11_parse_elems(mgmt->u.auth.variable,
994 len - offsetof(struct ieee80211_mgmt,
995 u.auth.variable),
996 &elems, 0) == ParseFailed) {
997 wpa_printf(MSG_DEBUG,
998 "PASN: Failed parsing Authentication frame");
999 goto fail;
1000 }
1001
1002 /* Check that the MIC IE exists. Save it and zero out the memory. */
1003 mic_len = pasn_mic_len(pasn->akmp, pasn->cipher);
1004 if (!elems.mic || elems.mic_len != mic_len) {
1005 wpa_printf(MSG_DEBUG,
1006 "PASN: Invalid MIC. Expecting len=%u", mic_len);
1007 goto fail;
1008 }
1009 os_memcpy(mic, elems.mic, mic_len);
1010
1011 if (!elems.pasn_params || !elems.pasn_params_len) {
1012 wpa_printf(MSG_DEBUG,
1013 "PASN: No PASN Parameters element found");
1014 goto fail;
1015 }
1016
1017 ret = wpa_pasn_parse_parameter_ie(elems.pasn_params - 3,
1018 elems.pasn_params_len + 3,
1019 false, &pasn_params);
1020 if (ret) {
1021 wpa_printf(MSG_DEBUG,
1022 "PASN: Failed validation of PASN Parameters IE");
1023 goto fail;
1024 }
1025
1026 if (pasn_params.pubkey || pasn_params.pubkey_len) {
1027 wpa_printf(MSG_DEBUG,
1028 "PASN: Public key should not be included");
1029 goto fail;
1030 }
1031
1032 /* Verify the MIC */
1033 copy_len = len - offsetof(struct ieee80211_mgmt, u.auth);
1034 mic_offset = elems.mic - (const u8 *) &mgmt->u.auth;
1035 copy_len = len - offsetof(struct ieee80211_mgmt, u.auth);
1036 if (mic_offset + mic_len > copy_len)
1037 goto fail;
1038 copy = os_memdup(&mgmt->u.auth, copy_len);
1039 if (!copy)
1040 goto fail;
1041 os_memset(copy + mic_offset, 0, mic_len);
1042 ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
1043 peer_addr, own_addr,
1044 pasn->hash, mic_len * 2,
1045 copy, copy_len, out_mic);
1046 os_free(copy);
1047 copy = NULL;
1048
1049 wpa_hexdump_key(MSG_DEBUG, "PASN: Frame MIC", mic, mic_len);
1050 if (ret || os_memcmp(mic, out_mic, mic_len) != 0) {
1051 wpa_printf(MSG_DEBUG, "PASN: Failed MIC verification");
1052 goto fail;
1053 }
1054
1055 if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001056 wrapped_data = ieee802_11_defrag(elems.wrapped_data,
1057 elems.wrapped_data_len,
1058 true);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001059
1060 if (!wrapped_data) {
1061 wpa_printf(MSG_DEBUG, "PASN: Missing wrapped data");
1062 goto fail;
1063 }
1064
1065#ifdef CONFIG_SAE
1066 if (pasn->akmp == WPA_KEY_MGMT_SAE) {
1067 ret = pasn_wd_handle_sae_confirm(pasn, peer_addr,
1068 wrapped_data);
1069 if (ret) {
1070 wpa_printf(MSG_DEBUG,
1071 "PASN: Failed processing SAE confirm");
1072 wpabuf_free(wrapped_data);
1073 goto fail;
1074 }
1075 }
1076#endif /* CONFIG_SAE */
1077#ifdef CONFIG_FILS
1078 if (pasn->akmp == WPA_KEY_MGMT_FILS_SHA256 ||
1079 pasn->akmp == WPA_KEY_MGMT_FILS_SHA384) {
1080 if (wrapped_data) {
1081 wpa_printf(MSG_DEBUG,
1082 "PASN: FILS: Ignore wrapped data");
1083 }
1084 }
1085#endif /* CONFIG_FILS */
1086 wpabuf_free(wrapped_data);
1087 }
1088
1089 wpa_printf(MSG_INFO,
1090 "PASN: Success handling transaction == 3. Store PTK");
1091 return 0;
1092
1093fail:
1094 os_free(copy);
1095 return -1;
1096}
1097
1098#endif /* CONFIG_PASN */