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