blob: 3eaa01527e72b2f5c3418c63adfabac38cf6609e [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - WPA state machine and EAPOL-Key processing
Roshan Pius3a1667e2018-07-03 15:17:14 -07003 * Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi>
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004 * Copyright(c) 2015 Intel Deutschland GmbH
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08006 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07008 */
9
10#include "includes.h"
11
12#include "common.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080013#include "crypto/aes.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#include "crypto/aes_wrap.h"
15#include "crypto/crypto.h"
16#include "crypto/random.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080017#include "crypto/aes_siv.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070018#include "crypto/sha256.h"
19#include "crypto/sha384.h"
20#include "crypto/sha512.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "common/ieee802_11_defs.h"
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080022#include "common/ieee802_11_common.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080023#include "common/ocv.h"
Hai Shalom4fbc08f2020-05-18 12:37:00 -070024#include "common/dpp.h"
Hai Shalom899fcc72020-10-19 14:38:18 -070025#include "common/wpa_ctrl.h"
Paul Stewart092955c2017-02-06 09:13:09 -080026#include "eap_common/eap_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070027#include "eapol_supp/eapol_supp_sm.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080028#include "drivers/driver.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070029#include "wpa.h"
30#include "eloop.h"
31#include "preauth.h"
32#include "pmksa_cache.h"
33#include "wpa_i.h"
34#include "wpa_ie.h"
Mir Alieaaf04e2021-06-07 12:17:29 +053035#include "wpa_supplicant_i.h"
36#include "driver_i.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080038static const u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
39
40
Sunil Ravi77d572f2023-01-17 23:58:31 +000041static void _wpa_hexdump_link(int level, u8 link_id, const char *title,
42 const void *buf, size_t len, bool key)
43{
44 char *link_title = NULL;
45
46 if (link_id >= MAX_NUM_MLD_LINKS)
47 goto out;
48
49 link_title = os_malloc(os_strlen(title) + 20);
50 if (!link_title)
51 goto out;
52
53 os_snprintf(link_title, os_strlen(title) + 20, "MLO link[%u]: %s",
54 link_id, title);
55
56out:
57 if (key)
58 wpa_hexdump_key(level, link_title ? link_title : title, buf,
59 len);
60 else
61 wpa_hexdump(level, link_title ? link_title : title, buf, len);
62 os_free(link_title);
63}
64
65
66static void wpa_hexdump_link(int level, u8 link_id, const char *title,
67 const void *buf, size_t len)
68{
69 _wpa_hexdump_link(level, link_id, title, buf, len, false);
70}
71
72
73static void wpa_hexdump_link_key(int level, u8 link_id, const char *title,
74 const void *buf, size_t len)
75{
76 _wpa_hexdump_link(level, link_id, title, buf, len, true);
77}
78
79
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070080/**
81 * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message
82 * @sm: Pointer to WPA state machine data from wpa_sm_init()
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080083 * @ptk: PTK for Key Confirmation/Encryption Key
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070084 * @ver: Version field from Key Info
85 * @dest: Destination address for the frame
86 * @proto: Ethertype (usually ETH_P_EAPOL)
87 * @msg: EAPOL-Key message
88 * @msg_len: Length of message
89 * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080090 * Returns: >= 0 on success, < 0 on failure
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070091 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -080092int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080093 int ver, const u8 *dest, u16 proto,
94 u8 *msg, size_t msg_len, u8 *key_mic)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070095{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080096 int ret = -1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070097 size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -080098
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070099 wpa_printf(MSG_DEBUG, "WPA: Send EAPOL-Key frame to " MACSTR
100 " ver=%d mic_len=%d key_mgmt=0x%x",
101 MAC2STR(dest), ver, (int) mic_len, sm->key_mgmt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102 if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) {
103 /*
104 * Association event was not yet received; try to fetch
105 * BSSID from the driver.
106 */
107 if (wpa_sm_get_bssid(sm, sm->bssid) < 0) {
108 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
109 "WPA: Failed to read BSSID for "
110 "EAPOL-Key destination address");
111 } else {
112 dest = sm->bssid;
113 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
114 "WPA: Use BSSID (" MACSTR
115 ") as the destination for EAPOL-Key",
116 MAC2STR(dest));
117 }
118 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800119
120 if (mic_len) {
121 if (key_mic && (!ptk || !ptk->kck_len))
122 goto out;
123
124 if (key_mic &&
125 wpa_eapol_key_mic(ptk->kck, ptk->kck_len, sm->key_mgmt, ver,
126 msg, msg_len, key_mic)) {
127 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
128 "WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC",
129 ver, sm->key_mgmt);
130 goto out;
131 }
Dmitry Shmidt29333592017-01-09 12:27:11 -0800132 if (ptk)
133 wpa_hexdump_key(MSG_DEBUG, "WPA: KCK",
134 ptk->kck, ptk->kck_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800135 wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC",
136 key_mic, mic_len);
137 } else {
138#ifdef CONFIG_FILS
139 /* AEAD cipher - Key MIC field not used */
140 struct ieee802_1x_hdr *s_hdr, *hdr;
141 struct wpa_eapol_key *s_key, *key;
142 u8 *buf, *s_key_data, *key_data;
143 size_t buf_len = msg_len + AES_BLOCK_SIZE;
144 size_t key_data_len;
145 u16 eapol_len;
146 const u8 *aad[1];
147 size_t aad_len[1];
148
149 if (!ptk || !ptk->kek_len)
150 goto out;
151
152 key_data_len = msg_len - sizeof(struct ieee802_1x_hdr) -
153 sizeof(struct wpa_eapol_key) - 2;
154
155 buf = os_malloc(buf_len);
156 if (!buf)
157 goto out;
158
159 os_memcpy(buf, msg, msg_len);
160 hdr = (struct ieee802_1x_hdr *) buf;
161 key = (struct wpa_eapol_key *) (hdr + 1);
162 key_data = ((u8 *) (key + 1)) + 2;
163
164 /* Update EAPOL header to include AES-SIV overhead */
165 eapol_len = be_to_host16(hdr->length);
166 eapol_len += AES_BLOCK_SIZE;
167 hdr->length = host_to_be16(eapol_len);
168
169 /* Update Key Data Length field to include AES-SIV overhead */
170 WPA_PUT_BE16((u8 *) (key + 1), AES_BLOCK_SIZE + key_data_len);
171
172 s_hdr = (struct ieee802_1x_hdr *) msg;
173 s_key = (struct wpa_eapol_key *) (s_hdr + 1);
174 s_key_data = ((u8 *) (s_key + 1)) + 2;
175
176 wpa_hexdump_key(MSG_DEBUG, "WPA: Plaintext Key Data",
177 s_key_data, key_data_len);
178
179 wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len);
180 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
181 * to Key Data (exclusive). */
182 aad[0] = buf;
183 aad_len[0] = key_data - buf;
184 if (aes_siv_encrypt(ptk->kek, ptk->kek_len,
185 s_key_data, key_data_len,
186 1, aad, aad_len, key_data) < 0) {
187 os_free(buf);
188 goto out;
189 }
190
191 wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV",
192 key_data, AES_BLOCK_SIZE + key_data_len);
193
194 os_free(msg);
195 msg = buf;
196 msg_len = buf_len;
197#else /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700198 goto out;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800199#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700200 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800201
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700202 wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800203 ret = wpa_sm_ether_send(sm, dest, proto, msg, msg_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700204 eapol_sm_notify_tx_eapol_key(sm->eapol);
205out:
206 os_free(msg);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800207 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700208}
209
210
211/**
212 * wpa_sm_key_request - Send EAPOL-Key Request
213 * @sm: Pointer to WPA state machine data from wpa_sm_init()
214 * @error: Indicate whether this is an Michael MIC error report
215 * @pairwise: 1 = error report for pairwise packet, 0 = for group packet
216 *
217 * Send an EAPOL-Key Request to the current authenticator. This function is
218 * used to request rekeying and it is usually called when a local Michael MIC
219 * failure is detected.
220 */
221void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
222{
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800223 size_t mic_len, hdrlen, rlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700224 struct wpa_eapol_key *reply;
225 int key_info, ver;
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000226 u8 *rbuf, *key_mic, *mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700227
Hai Shalomfdcde762020-04-02 11:19:20 -0700228 if (pairwise && sm->wpa_deny_ptk0_rekey && !sm->use_ext_key_id &&
Sunil8cd6f4d2022-06-28 18:40:46 +0000229 wpa_sm_get_state(sm) == WPA_COMPLETED && !error) {
Hai Shalomfdcde762020-04-02 11:19:20 -0700230 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
231 "WPA: PTK0 rekey not allowed, reconnecting");
232 wpa_sm_reconnect(sm);
233 return;
234 }
235
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000236 if (!sm->ptk_set) {
237 wpa_printf(MSG_INFO,
238 "WPA: No PTK derived yet - cannot send EAPOL-Key Request");
239 return;
240 }
241
Roshan Pius3a1667e2018-07-03 15:17:14 -0700242 if (wpa_use_akm_defined(sm->key_mgmt))
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800243 ver = WPA_KEY_INFO_TYPE_AKM_DEFINED;
244 else if (wpa_key_mgmt_ft(sm->key_mgmt) ||
245 wpa_key_mgmt_sha256(sm->key_mgmt))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700246 ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700247 else if (sm->pairwise_cipher != WPA_CIPHER_TKIP)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700248 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
249 else
250 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
251
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700252 mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800253 hdrlen = sizeof(*reply) + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800255 hdrlen, &rlen, (void *) &reply);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700256 if (rbuf == NULL)
257 return;
258
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800259 reply->type = (sm->proto == WPA_PROTO_RSN ||
260 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700261 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
262 key_info = WPA_KEY_INFO_REQUEST | ver;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000263 key_info |= WPA_KEY_INFO_SECURE;
264 if (mic_len)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800265 key_info |= WPA_KEY_INFO_MIC;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000266 else
267 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700268 if (error)
269 key_info |= WPA_KEY_INFO_ERROR;
270 if (pairwise)
271 key_info |= WPA_KEY_INFO_KEY_TYPE;
272 WPA_PUT_BE16(reply->key_info, key_info);
273 WPA_PUT_BE16(reply->key_length, 0);
274 os_memcpy(reply->replay_counter, sm->request_counter,
275 WPA_REPLAY_COUNTER_LEN);
276 inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
277
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800278 mic = (u8 *) (reply + 1);
279 WPA_PUT_BE16(mic + mic_len, 0);
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800280 if (!(key_info & WPA_KEY_INFO_MIC))
281 key_mic = NULL;
282 else
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800283 key_mic = mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700284
285 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
286 "WPA: Sending EAPOL-Key Request (error=%d "
287 "pairwise=%d ptk_set=%d len=%lu)",
288 error, pairwise, sm->ptk_set, (unsigned long) rlen);
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000289 wpa_eapol_key_send(sm, &sm->ptk, ver, wpa_sm_get_auth_addr(sm),
290 ETH_P_EAPOL, rbuf, rlen, key_mic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700291}
292
293
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800294static void wpa_supplicant_key_mgmt_set_pmk(struct wpa_sm *sm)
295{
296#ifdef CONFIG_IEEE80211R
297 if (sm->key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) {
298 if (wpa_sm_key_mgmt_set_pmk(sm, sm->xxkey, sm->xxkey_len))
299 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
300 "RSN: Cannot set low order 256 bits of MSK for key management offload");
301 } else {
302#endif /* CONFIG_IEEE80211R */
303 if (wpa_sm_key_mgmt_set_pmk(sm, sm->pmk, sm->pmk_len))
304 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
305 "RSN: Cannot set PMK for key management offload");
306#ifdef CONFIG_IEEE80211R
307 }
308#endif /* CONFIG_IEEE80211R */
309}
310
311
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700312static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
313 const unsigned char *src_addr,
314 const u8 *pmkid)
315{
316 int abort_cached = 0;
317
318 if (pmkid && !sm->cur_pmksa) {
319 /* When using drivers that generate RSN IE, wpa_supplicant may
320 * not have enough time to get the association information
321 * event before receiving this 1/4 message, so try to find a
322 * matching PMKSA cache entry here. */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000323 sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr,
324 sm->own_addr, pmkid,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700325 NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700326 if (sm->cur_pmksa) {
327 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
328 "RSN: found matching PMKID from PMKSA cache");
329 } else {
330 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
331 "RSN: no matching PMKID found");
332 abort_cached = 1;
333 }
334 }
335
336 if (pmkid && sm->cur_pmksa &&
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700337 os_memcmp_const(pmkid, sm->cur_pmksa->pmkid, PMKID_LEN) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700338 wpa_hexdump(MSG_DEBUG, "RSN: matched PMKID", pmkid, PMKID_LEN);
339 wpa_sm_set_pmk_from_pmksa(sm);
340 wpa_hexdump_key(MSG_DEBUG, "RSN: PMK from PMKSA cache",
341 sm->pmk, sm->pmk_len);
342 eapol_sm_notify_cached(sm->eapol);
343#ifdef CONFIG_IEEE80211R
344 sm->xxkey_len = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700345#ifdef CONFIG_SAE
Sunil Ravi89eba102022-09-13 21:04:37 -0700346 if ((sm->key_mgmt == WPA_KEY_MGMT_FT_SAE ||
347 sm->key_mgmt == WPA_KEY_MGMT_FT_SAE_EXT_KEY) &&
Roshan Pius3a1667e2018-07-03 15:17:14 -0700348 sm->pmk_len == PMK_LEN) {
349 /* Need to allow FT key derivation to proceed with
350 * PMK from SAE being used as the XXKey in cases where
351 * the PMKID in msg 1/4 matches the PMKSA entry that was
352 * just added based on SAE authentication for the
353 * initial mobility domain association. */
354 os_memcpy(sm->xxkey, sm->pmk, sm->pmk_len);
355 sm->xxkey_len = sm->pmk_len;
356 }
357#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700358#endif /* CONFIG_IEEE80211R */
359 } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && sm->eapol) {
360 int res, pmk_len;
Hai Shalom81f62d82019-07-22 12:10:00 -0700361#ifdef CONFIG_IEEE80211R
362 u8 buf[2 * PMK_LEN];
363#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800364
Dmitry Shmidtebd93af2017-02-21 13:40:44 -0800365 if (wpa_key_mgmt_sha384(sm->key_mgmt))
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800366 pmk_len = PMK_LEN_SUITE_B_192;
367 else
368 pmk_len = PMK_LEN;
369 res = eapol_sm_get_key(sm->eapol, sm->pmk, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700370 if (res) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800371 if (pmk_len == PMK_LEN) {
372 /*
373 * EAP-LEAP is an exception from other EAP
374 * methods: it uses only 16-byte PMK.
375 */
376 res = eapol_sm_get_key(sm->eapol, sm->pmk, 16);
377 pmk_len = 16;
378 }
Hai Shalomf1c97642019-07-19 23:42:07 +0000379 }
Hai Shalom81f62d82019-07-22 12:10:00 -0700380#ifdef CONFIG_IEEE80211R
381 if (res == 0 &&
382 eapol_sm_get_key(sm->eapol, buf, 2 * PMK_LEN) == 0) {
383 if (wpa_key_mgmt_sha384(sm->key_mgmt)) {
384 os_memcpy(sm->xxkey, buf, SHA384_MAC_LEN);
385 sm->xxkey_len = SHA384_MAC_LEN;
386 } else {
387 os_memcpy(sm->xxkey, buf + PMK_LEN, PMK_LEN);
388 sm->xxkey_len = PMK_LEN;
389 }
390 forced_memzero(buf, sizeof(buf));
391 if (sm->proto == WPA_PROTO_RSN &&
392 wpa_key_mgmt_ft(sm->key_mgmt)) {
393 struct rsn_pmksa_cache_entry *sa = NULL;
394 const u8 *fils_cache_id = NULL;
395
396#ifdef CONFIG_FILS
397 if (sm->fils_cache_id_set)
398 fils_cache_id = sm->fils_cache_id;
399#endif /* CONFIG_FILS */
400 wpa_hexdump_key(MSG_DEBUG,
401 "FT: Cache XXKey/MPMK",
402 sm->xxkey, sm->xxkey_len);
403 sa = pmksa_cache_add(sm->pmksa,
404 sm->xxkey, sm->xxkey_len,
405 NULL, NULL, 0,
406 src_addr, sm->own_addr,
407 sm->network_ctx,
408 sm->key_mgmt,
409 fils_cache_id);
410 if (!sm->cur_pmksa)
411 sm->cur_pmksa = sa;
412 }
413 }
414#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 if (res == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700416 struct rsn_pmksa_cache_entry *sa = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700417 const u8 *fils_cache_id = NULL;
418
419#ifdef CONFIG_FILS
420 if (sm->fils_cache_id_set)
421 fils_cache_id = sm->fils_cache_id;
422#endif /* CONFIG_FILS */
423
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700424 wpa_hexdump_key(MSG_DEBUG, "WPA: PMK from EAPOL state "
425 "machines", sm->pmk, pmk_len);
426 sm->pmk_len = pmk_len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800427 wpa_supplicant_key_mgmt_set_pmk(sm);
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700428 if (sm->proto == WPA_PROTO_RSN &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800429 !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700430 !wpa_key_mgmt_ft(sm->key_mgmt)) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700431 sa = pmksa_cache_add(sm->pmksa,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800432 sm->pmk, pmk_len, NULL,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800433 NULL, 0,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700434 src_addr, sm->own_addr,
435 sm->network_ctx,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700436 sm->key_mgmt,
437 fils_cache_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700438 }
439 if (!sm->cur_pmksa && pmkid &&
Sunil Ravi77d572f2023-01-17 23:58:31 +0000440 pmksa_cache_get(sm->pmksa, src_addr, sm->own_addr,
441 pmkid, NULL, 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
443 "RSN: the new PMK matches with the "
444 "PMKID");
445 abort_cached = 0;
Jouni Malinen6ec30382015-07-08 20:48:18 +0300446 } else if (sa && !sm->cur_pmksa && pmkid) {
447 /*
448 * It looks like the authentication server
449 * derived mismatching MSK. This should not
450 * really happen, but bugs happen.. There is not
451 * much we can do here without knowing what
452 * exactly caused the server to misbehave.
453 */
Dmitry Shmidt014a3ff2015-12-28 13:27:49 -0800454 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Jouni Malinen6ec30382015-07-08 20:48:18 +0300455 "RSN: PMKID mismatch - authentication server may have derived different MSK?!");
456 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700457 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700458
459 if (!sm->cur_pmksa)
460 sm->cur_pmksa = sa;
Hai Shalom81f62d82019-07-22 12:10:00 -0700461#ifdef CONFIG_IEEE80211R
462 } else if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->ft_protocol) {
463 wpa_printf(MSG_DEBUG,
464 "FT: Continue 4-way handshake without PMK/PMKID for association using FT protocol");
465#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700466 } else {
467 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
468 "WPA: Failed to get master session key from "
469 "EAPOL state machines - key handshake "
470 "aborted");
471 if (sm->cur_pmksa) {
472 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
473 "RSN: Cancelled PMKSA caching "
474 "attempt");
475 sm->cur_pmksa = NULL;
476 abort_cached = 1;
477 } else if (!abort_cached) {
478 return -1;
479 }
480 }
481 }
482
Dmitry Shmidtc55524a2011-07-07 11:18:38 -0700483 if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800484 !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800485 !wpa_key_mgmt_ft(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OSEN)
486 {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700487 /* Send EAPOL-Start to trigger full EAP authentication. */
488 u8 *buf;
489 size_t buflen;
490
491 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
492 "RSN: no PMKSA entry found - trigger "
493 "full EAP authentication");
494 buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START,
495 NULL, 0, &buflen, NULL);
496 if (buf) {
Hai Shalomc1a21442022-02-04 13:43:00 -0800497 /* Set and reset eapFail to allow EAP state machine to
498 * proceed with new authentication. */
499 eapol_sm_notify_eap_fail(sm->eapol, true);
500 eapol_sm_notify_eap_fail(sm->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700501 wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL,
502 buf, buflen);
503 os_free(buf);
504 return -2;
505 }
506
507 return -1;
508 }
509
510 return 0;
511}
512
513
514/**
515 * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake
516 * @sm: Pointer to WPA state machine data from wpa_sm_init()
517 * @dst: Destination address for the frame
518 * @key: Pointer to the EAPOL-Key frame header
519 * @ver: Version bits from EAPOL-Key Key Info
520 * @nonce: Nonce value for the EAPOL-Key frame
521 * @wpa_ie: WPA/RSN IE
522 * @wpa_ie_len: Length of the WPA/RSN IE
523 * @ptk: PTK to use for keyed hash and encryption
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800524 * Returns: >= 0 on success, < 0 on failure
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700525 */
526int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst,
527 const struct wpa_eapol_key *key,
528 int ver, const u8 *nonce,
529 const u8 *wpa_ie, size_t wpa_ie_len,
530 struct wpa_ptk *ptk)
531{
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000532 size_t mic_len, hdrlen, rlen, extra_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700533 struct wpa_eapol_key *reply;
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800534 u8 *rbuf, *key_mic;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700535 u8 *rsn_ie_buf = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800536 u16 key_info;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000537#ifdef CONFIG_TESTING_OPTIONS
538 size_t pad_len = 0;
539#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700540
541 if (wpa_ie == NULL) {
542 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - "
543 "cannot generate msg 2/4");
544 return -1;
545 }
546
547#ifdef CONFIG_IEEE80211R
548 if (wpa_key_mgmt_ft(sm->key_mgmt)) {
549 int res;
550
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800551 wpa_hexdump(MSG_DEBUG, "WPA: WPA IE before FT processing",
552 wpa_ie, wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700553 /*
554 * Add PMKR1Name into RSN IE (PMKID-List) and add MDIE and
555 * FTIE from (Re)Association Response.
556 */
557 rsn_ie_buf = os_malloc(wpa_ie_len + 2 + 2 + PMKID_LEN +
558 sm->assoc_resp_ies_len);
559 if (rsn_ie_buf == NULL)
560 return -1;
561 os_memcpy(rsn_ie_buf, wpa_ie, wpa_ie_len);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -0800562 res = wpa_insert_pmkid(rsn_ie_buf, &wpa_ie_len,
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000563 sm->pmk_r1_name, !sm->ft_prepend_pmkid);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700564 if (res < 0) {
565 os_free(rsn_ie_buf);
566 return -1;
567 }
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800568 wpa_hexdump(MSG_DEBUG,
569 "WPA: WPA IE after PMKID[PMKR1Name] addition into RSNE",
570 rsn_ie_buf, wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700571
572 if (sm->assoc_resp_ies) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800573 wpa_hexdump(MSG_DEBUG, "WPA: Add assoc_resp_ies",
574 sm->assoc_resp_ies,
575 sm->assoc_resp_ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700576 os_memcpy(rsn_ie_buf + wpa_ie_len, sm->assoc_resp_ies,
577 sm->assoc_resp_ies_len);
578 wpa_ie_len += sm->assoc_resp_ies_len;
579 }
580
581 wpa_ie = rsn_ie_buf;
582 }
583#endif /* CONFIG_IEEE80211R */
584
585 wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len);
586
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000587#ifdef CONFIG_TESTING_OPTIONS
588 if (sm->test_eapol_m2_elems)
589 extra_len = wpabuf_len(sm->test_eapol_m2_elems);
590 if (sm->encrypt_eapol_m2) {
591 pad_len = (wpa_ie_len + extra_len) % 8;
592 if (pad_len)
593 pad_len = 8 - pad_len;
594 extra_len += pad_len + 8;
595 }
596#endif /* CONFIG_TESTING_OPTIONS */
597
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700598 mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800599 hdrlen = sizeof(*reply) + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700600 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000601 NULL, hdrlen + wpa_ie_len + extra_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 &rlen, (void *) &reply);
603 if (rbuf == NULL) {
604 os_free(rsn_ie_buf);
605 return -1;
606 }
607
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800608 reply->type = (sm->proto == WPA_PROTO_RSN ||
609 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700610 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800611 key_info = ver | WPA_KEY_INFO_KEY_TYPE;
Sunil8cd6f4d2022-06-28 18:40:46 +0000612 if (sm->ptk_set && sm->proto != WPA_PROTO_WPA)
613 key_info |= WPA_KEY_INFO_SECURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800614 if (mic_len)
615 key_info |= WPA_KEY_INFO_MIC;
616 else
617 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000618#ifdef CONFIG_TESTING_OPTIONS
619 if (sm->encrypt_eapol_m2)
620 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
621#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800622 WPA_PUT_BE16(reply->key_info, key_info);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800623 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 WPA_PUT_BE16(reply->key_length, 0);
625 else
626 os_memcpy(reply->key_length, key->key_length, 2);
627 os_memcpy(reply->replay_counter, key->replay_counter,
628 WPA_REPLAY_COUNTER_LEN);
629 wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter,
630 WPA_REPLAY_COUNTER_LEN);
631
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800632 key_mic = (u8 *) (reply + 1);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000633 /* Key Data Length */
634 WPA_PUT_BE16(key_mic + mic_len, wpa_ie_len + extra_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800635 os_memcpy(key_mic + mic_len + 2, wpa_ie, wpa_ie_len); /* Key Data */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700636 os_free(rsn_ie_buf);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000637#ifdef CONFIG_TESTING_OPTIONS
638 if (sm->test_eapol_m2_elems) {
639 os_memcpy(key_mic + mic_len + 2 + wpa_ie_len,
640 wpabuf_head(sm->test_eapol_m2_elems),
641 wpabuf_len(sm->test_eapol_m2_elems));
642 }
643
644 if (sm->encrypt_eapol_m2) {
645 u8 *plain;
646 size_t plain_len;
647
648 if (sm->test_eapol_m2_elems)
649 extra_len = wpabuf_len(sm->test_eapol_m2_elems);
650 else
651 extra_len = 0;
652 plain_len = wpa_ie_len + extra_len + pad_len;
653 plain = os_memdup(key_mic + mic_len + 2, plain_len);
654 if (!plain) {
655 os_free(rbuf);
656 return -1;
657 }
658 if (pad_len)
659 plain[plain_len - pad_len] = 0xdd;
660
661 wpa_hexdump_key(MSG_DEBUG, "RSN: AES-WRAP using KEK",
662 ptk->kek, ptk->kek_len);
663 if (aes_wrap(ptk->kek, ptk->kek_len, plain_len / 8, plain,
664 key_mic + mic_len + 2)) {
665 os_free(plain);
666 os_free(rbuf);
667 return -1;
668 }
669 wpa_hexdump(MSG_DEBUG,
670 "RSN: Encrypted Key Data from AES-WRAP",
671 key_mic + mic_len + 2, plain_len + 8);
672 os_free(plain);
673 }
674#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700675
676 os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN);
677
Roshan Pius5e7db942018-04-12 12:27:41 -0700678 wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key 2/4");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800679 return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
680 key_mic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700681}
682
683
684static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr,
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800685 const struct wpa_eapol_key *key, struct wpa_ptk *ptk)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700686{
Sunil Ravi89eba102022-09-13 21:04:37 -0700687 int ret;
Hai Shalom021b0b52019-04-10 11:17:58 -0700688 const u8 *z = NULL;
Hai Shalom60840252021-02-19 19:02:11 -0800689 size_t z_len = 0, kdk_len;
Hai Shalomfdcde762020-04-02 11:19:20 -0700690 int akmp;
Hai Shalom021b0b52019-04-10 11:17:58 -0700691
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692#ifdef CONFIG_IEEE80211R
693 if (wpa_key_mgmt_ft(sm->key_mgmt))
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800694 return wpa_derive_ptk_ft(sm, src_addr, key, ptk);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700695#endif /* CONFIG_IEEE80211R */
696
Hai Shalom021b0b52019-04-10 11:17:58 -0700697#ifdef CONFIG_DPP2
698 if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
699 z = wpabuf_head(sm->dpp_z);
700 z_len = wpabuf_len(sm->dpp_z);
701 }
702#endif /* CONFIG_DPP2 */
703
Hai Shalomfdcde762020-04-02 11:19:20 -0700704 akmp = sm->key_mgmt;
705#ifdef CONFIG_OWE
706 if (sm->owe_ptk_workaround && akmp == WPA_KEY_MGMT_OWE &&
707 sm->pmk_len > 32) {
708 wpa_printf(MSG_DEBUG,
709 "OWE: Force SHA256 for PTK derivation");
710 akmp |= WPA_KEY_MGMT_PSK_SHA256;
711 }
712#endif /* CONFIG_OWE */
Hai Shalom60840252021-02-19 19:02:11 -0800713
714 if (sm->force_kdk_derivation ||
Hai Shalomc1a21442022-02-04 13:43:00 -0800715 (sm->secure_ltf &&
716 ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -0800717 kdk_len = WPA_KDK_MAX_LEN;
718 else
719 kdk_len = 0;
720
Sunil Ravi89eba102022-09-13 21:04:37 -0700721 ret = wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion",
Sunil Ravi77d572f2023-01-17 23:58:31 +0000722 sm->own_addr, wpa_sm_get_auth_addr(sm), sm->snonce,
Sunil Ravi89eba102022-09-13 21:04:37 -0700723 key->key_nonce, ptk, akmp,
724 sm->pairwise_cipher, z, z_len,
725 kdk_len);
726 if (ret) {
727 wpa_printf(MSG_ERROR, "WPA: PTK derivation failed");
728 return ret;
729 }
730
731#ifdef CONFIG_PASN
732 if (sm->secure_ltf &&
733 ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF))
734 ret = wpa_ltf_keyseed(ptk, akmp, sm->pairwise_cipher);
735#endif /* CONFIG_PASN */
736
737 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700738}
739
740
Hai Shalomfdcde762020-04-02 11:19:20 -0700741static int wpa_handle_ext_key_id(struct wpa_sm *sm,
742 struct wpa_eapol_ie_parse *kde)
743{
744 if (sm->ext_key_id) {
745 u16 key_id;
746
747 if (!kde->key_id) {
748 wpa_msg(sm->ctx->msg_ctx,
749 sm->use_ext_key_id ? MSG_INFO : MSG_DEBUG,
750 "RSN: No Key ID in Extended Key ID handshake");
751 sm->keyidx_active = 0;
752 return sm->use_ext_key_id ? -1 : 0;
753 }
754
755 key_id = kde->key_id[0] & 0x03;
756 if (key_id > 1) {
757 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
758 "RSN: Invalid Extended Key ID: %d", key_id);
759 return -1;
760 }
761 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
762 "RSN: Using Extended Key ID %d", key_id);
763 sm->keyidx_active = key_id;
764 sm->use_ext_key_id = 1;
765 } else {
766 if (kde->key_id && (kde->key_id[0] & 0x03)) {
767 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
768 "RSN: Non-zero Extended Key ID Key ID in PTK0 handshake");
769 return -1;
770 }
771
772 if (kde->key_id) {
773 /* This is not supposed to be included here, but ignore
774 * the case of matching Key ID 0 just in case. */
775 wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
776 "RSN: Extended Key ID Key ID 0 in PTK0 handshake");
777 }
778 sm->keyidx_active = 0;
779 sm->use_ext_key_id = 0;
780 }
781
782 return 0;
783}
784
785
Sunil Ravi77d572f2023-01-17 23:58:31 +0000786static u8 * rsn_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len)
787{
788 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
789 *pos++ = RSN_SELECTOR_LEN + data_len;
790 RSN_SELECTOR_PUT(pos, kde);
791 pos += RSN_SELECTOR_LEN;
792 os_memcpy(pos, data, data_len);
793 pos += data_len;
794
795 return pos;
796}
797
798
799static size_t wpa_mlo_link_kde_len(struct wpa_sm *sm)
800{
801 int i;
802 unsigned int num_links = 0;
803
Sunil Ravi88611412024-06-28 17:34:56 +0000804 for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
805 if (sm->mlo.assoc_link_id != i && (sm->mlo.req_links & BIT(i)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000806 num_links++;
807 }
808
809 return num_links * (RSN_SELECTOR_LEN + 1 + ETH_ALEN + 2);
810}
811
812
813static u8 * wpa_mlo_link_kde(struct wpa_sm *sm, u8 *pos)
814{
815 int i;
816 u8 hdr[1 + ETH_ALEN];
817
Sunil Ravi88611412024-06-28 17:34:56 +0000818 for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
819 if (sm->mlo.assoc_link_id == i || !(sm->mlo.req_links & BIT(i)))
Sunil Ravi77d572f2023-01-17 23:58:31 +0000820 continue;
821
822 wpa_printf(MSG_DEBUG,
823 "MLO: Add MLO Link %d KDE in EAPOL-Key 2/4", i);
824 hdr[0] = i & 0xF; /* LinkID; no RSNE or RSNXE */
825 os_memcpy(&hdr[1], sm->mlo.links[i].addr, ETH_ALEN);
826 pos = rsn_add_kde(pos, RSN_KEY_DATA_MLO_LINK, hdr, sizeof(hdr));
827 }
828
829 return pos;
830}
831
832
833static bool is_valid_ap_mld_mac_kde(struct wpa_sm *sm, const u8 *mac_kde)
834{
835 return mac_kde &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000836 ether_addr_equal(mac_kde, sm->mlo.ap_mld_addr);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000837}
838
839
840static void wpas_swap_tkip_mic_keys(struct wpa_ptk *ptk)
841{
842 u8 buf[8];
843
844 /* Supplicant: swap tx/rx Mic keys */
845 os_memcpy(buf, &ptk->tk[16], 8);
846 os_memcpy(&ptk->tk[16], &ptk->tk[24], 8);
847 os_memcpy(&ptk->tk[24], buf, 8);
848 forced_memzero(buf, sizeof(buf));
849}
850
851
852static void wpa_supplicant_process_1_of_4_wpa(struct wpa_sm *sm,
853 const unsigned char *src_addr,
854 const struct wpa_eapol_key *key,
855 u16 ver, const u8 *key_data,
856 size_t key_data_len,
857 enum frame_encryption encrypted)
858{
859 struct wpa_eapol_ie_parse ie;
860 struct wpa_ptk *ptk;
861 int res;
862
863 if (wpa_sm_get_network_ctx(sm) == NULL) {
864 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
865 "WPA: No SSID info found (msg 1 of 4)");
866 return;
867 }
868
869 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
870 "WPA: RX message 1 of 4-Way Handshake from " MACSTR
871 " (ver=%d)", MAC2STR(src_addr), ver);
872
873 os_memset(&ie, 0, sizeof(ie));
874
875 res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
876 if (res == -2) {
877 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
878 "WPA: Do not reply to msg 1/4 - requesting full EAP authentication");
879 return;
880 }
881 if (res)
882 goto failed;
883
884 wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
885
886 if (sm->renew_snonce) {
887 if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
888 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
889 "WPA: Failed to get random data for SNonce");
890 goto failed;
891 }
892 sm->renew_snonce = 0;
893 wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
894 sm->snonce, WPA_NONCE_LEN);
895 }
896
897 /* Calculate PTK which will be stored as a temporary PTK until it has
898 * been verified when processing message 3/4. */
899 ptk = &sm->tptk;
900 if (wpa_derive_ptk(sm, src_addr, key, ptk) < 0)
901 goto failed;
902 if (sm->pairwise_cipher == WPA_CIPHER_TKIP)
903 wpas_swap_tkip_mic_keys(ptk);
904 sm->tptk_set = 1;
905
906 if (wpa_supplicant_send_2_of_4(sm, wpa_sm_get_auth_addr(sm), key, ver,
907 sm->snonce, sm->assoc_wpa_ie,
908 sm->assoc_wpa_ie_len, ptk) < 0)
909 goto failed;
910
911 os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
912 return;
913
914failed:
915 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
916}
917
918
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700919static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
920 const unsigned char *src_addr,
921 const struct wpa_eapol_key *key,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700922 u16 ver, const u8 *key_data,
Sunil8cd6f4d2022-06-28 18:40:46 +0000923 size_t key_data_len,
924 enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700925{
926 struct wpa_eapol_ie_parse ie;
927 struct wpa_ptk *ptk;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700928 int res;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -0800929 u8 *kde, *kde_buf = NULL;
930 size_t kde_len;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000931 size_t mlo_kde_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700932
Sunil8cd6f4d2022-06-28 18:40:46 +0000933 if (encrypted == FRAME_NOT_ENCRYPTED && sm->tk_set &&
934 wpa_sm_pmf_enabled(sm)) {
935 wpa_printf(MSG_DEBUG,
936 "RSN: Discard unencrypted EAPOL-Key msg 1/4 when TK is set and PMF is enabled");
937 return;
938 }
939
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700940 if (wpa_sm_get_network_ctx(sm) == NULL) {
941 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info "
942 "found (msg 1 of 4)");
943 return;
944 }
945
Hai Shalomfdcde762020-04-02 11:19:20 -0700946 if (sm->wpa_deny_ptk0_rekey && !sm->use_ext_key_id &&
947 wpa_sm_get_state(sm) == WPA_COMPLETED) {
948 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
949 "WPA: PTK0 rekey not allowed, reconnecting");
950 wpa_sm_reconnect(sm);
951 return;
952 }
953
Roshan Pius5e7db942018-04-12 12:27:41 -0700954 wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: RX message 1 of 4-Way "
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700955 "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver);
956
957 os_memset(&ie, 0, sizeof(ie));
958
Sunil Ravi77d572f2023-01-17 23:58:31 +0000959 /* RSN: msg 1/4 should contain PMKID for the selected PMK */
960 wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", key_data, key_data_len);
961 if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) {
962 wpa_printf(MSG_DEBUG,
963 "RSN: Discard EAPOL-Key msg 1/4 with invalid IEs/KDEs");
964 return;
965 }
966 if (ie.pmkid) {
967 wpa_hexdump(MSG_DEBUG, "RSN: PMKID from Authenticator",
968 ie.pmkid, PMKID_LEN);
969 }
970
971 if (sm->mlo.valid_links && !is_valid_ap_mld_mac_kde(sm, ie.mac_addr)) {
972 wpa_printf(MSG_INFO,
973 "RSN: Discard EAPOL-Key msg 1/4 with invalid AP MLD MAC address KDE");
974 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700975 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700976
977 res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid);
978 if (res == -2) {
979 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to "
980 "msg 1/4 - requesting full EAP authentication");
981 return;
982 }
983 if (res)
984 goto failed;
985
Sunil8cd6f4d2022-06-28 18:40:46 +0000986 wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
987
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700988 if (sm->renew_snonce) {
989 if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) {
990 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
991 "WPA: Failed to get random data for SNonce");
992 goto failed;
993 }
994 sm->renew_snonce = 0;
995 wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce",
996 sm->snonce, WPA_NONCE_LEN);
997 }
998
999 /* Calculate PTK which will be stored as a temporary PTK until it has
1000 * been verified when processing message 3/4. */
1001 ptk = &sm->tptk;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001002 if (wpa_derive_ptk(sm, src_addr, key, ptk) < 0)
1003 goto failed;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001004 if (sm->pairwise_cipher == WPA_CIPHER_TKIP)
1005 wpas_swap_tkip_mic_keys(ptk);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006 sm->tptk_set = 1;
1007
Sunil Ravi77d572f2023-01-17 23:58:31 +00001008 /* Add MLO Link KDE and MAC KDE in M2 for ML connection */
1009 if (sm->mlo.valid_links)
1010 mlo_kde_len = wpa_mlo_link_kde_len(sm) +
1011 RSN_SELECTOR_LEN + ETH_ALEN + 2;
1012
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001013 kde = sm->assoc_wpa_ie;
1014 kde_len = sm->assoc_wpa_ie_len;
Hai Shalomc3565922019-10-28 11:58:20 -07001015 kde_buf = os_malloc(kde_len +
1016 2 + RSN_SELECTOR_LEN + 3 +
1017 sm->assoc_rsnxe_len +
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001018 2 + RSN_SELECTOR_LEN + 1 +
Sunil Ravi77d572f2023-01-17 23:58:31 +00001019 2 + RSN_SELECTOR_LEN + 2 + mlo_kde_len);
1020
Hai Shalomc3565922019-10-28 11:58:20 -07001021 if (!kde_buf)
1022 goto failed;
1023 os_memcpy(kde_buf, kde, kde_len);
1024 kde = kde_buf;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001025
Hai Shalom74f70d42019-02-11 14:42:39 -08001026#ifdef CONFIG_OCV
1027 if (wpa_sm_ocv_enabled(sm)) {
1028 struct wpa_channel_info ci;
1029 u8 *pos;
1030
Hai Shalomc3565922019-10-28 11:58:20 -07001031 pos = kde + kde_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08001032 if (wpa_sm_channel_info(sm, &ci) != 0) {
1033 wpa_printf(MSG_WARNING,
1034 "Failed to get channel info for OCI element in EAPOL-Key 2/4");
1035 goto failed;
1036 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001037#ifdef CONFIG_TESTING_OPTIONS
1038 if (sm->oci_freq_override_eapol) {
1039 wpa_printf(MSG_INFO,
1040 "TEST: Override OCI KDE frequency %d -> %d MHz",
1041 ci.frequency, sm->oci_freq_override_eapol);
1042 ci.frequency = sm->oci_freq_override_eapol;
1043 }
1044#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08001045
Hai Shalom74f70d42019-02-11 14:42:39 -08001046 if (ocv_insert_oci_kde(&ci, &pos) < 0)
1047 goto failed;
1048 kde_len = pos - kde;
1049 }
1050#endif /* CONFIG_OCV */
1051
Hai Shalomc3565922019-10-28 11:58:20 -07001052 if (sm->assoc_rsnxe && sm->assoc_rsnxe_len) {
1053 os_memcpy(kde + kde_len, sm->assoc_rsnxe, sm->assoc_rsnxe_len);
1054 kde_len += sm->assoc_rsnxe_len;
1055 }
1056
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001057#ifdef CONFIG_P2P
1058 if (sm->p2p) {
Hai Shalomc3565922019-10-28 11:58:20 -07001059 u8 *pos;
1060
1061 wpa_printf(MSG_DEBUG,
1062 "P2P: Add IP Address Request KDE into EAPOL-Key 2/4");
1063 pos = kde + kde_len;
1064 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
1065 *pos++ = RSN_SELECTOR_LEN + 1;
1066 RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_IP_ADDR_REQ);
1067 pos += RSN_SELECTOR_LEN;
1068 *pos++ = 0x01;
1069 kde_len = pos - kde;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001070 }
1071#endif /* CONFIG_P2P */
1072
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001073#ifdef CONFIG_DPP2
1074 if (DPP_VERSION > 1 && sm->key_mgmt == WPA_KEY_MGMT_DPP) {
1075 u8 *pos;
1076
1077 wpa_printf(MSG_DEBUG, "DPP: Add DPP KDE into EAPOL-Key 2/4");
1078 pos = kde + kde_len;
1079 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
1080 *pos++ = RSN_SELECTOR_LEN + 2;
1081 RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_DPP);
1082 pos += RSN_SELECTOR_LEN;
1083 *pos++ = DPP_VERSION; /* Protocol Version */
1084 *pos = 0; /* Flags */
1085 if (sm->dpp_pfs == 0)
1086 *pos |= DPP_KDE_PFS_ALLOWED;
1087 else if (sm->dpp_pfs == 1)
1088 *pos |= DPP_KDE_PFS_ALLOWED | DPP_KDE_PFS_REQUIRED;
1089 pos++;
1090 kde_len = pos - kde;
1091 }
1092#endif /* CONFIG_DPP2 */
1093
Sunil Ravi77d572f2023-01-17 23:58:31 +00001094 if (sm->mlo.valid_links) {
1095 u8 *pos;
1096
1097 /* Add MAC KDE */
1098 wpa_printf(MSG_DEBUG, "MLO: Add MAC KDE into EAPOL-Key 2/4");
1099 pos = kde + kde_len;
1100 pos = rsn_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->own_addr,
1101 ETH_ALEN);
1102
1103 /* Add MLO Link KDE */
1104 wpa_printf(MSG_DEBUG, "Add MLO Link KDE(s) into EAPOL-Key 2/4");
1105 pos = wpa_mlo_link_kde(sm, pos);
1106 kde_len = pos - kde;
1107 }
1108
1109 if (wpa_supplicant_send_2_of_4(sm, wpa_sm_get_auth_addr(sm), key, ver,
1110 sm->snonce, kde, kde_len, ptk) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001111 goto failed;
1112
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001113 os_free(kde_buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001114 os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN);
1115 return;
1116
1117failed:
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08001118 os_free(kde_buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
1120}
1121
1122
1123static void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx)
1124{
1125 struct wpa_sm *sm = eloop_ctx;
1126 rsn_preauth_candidate_process(sm);
1127}
1128
1129
1130static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
1131 const u8 *addr, int secure)
1132{
1133 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1134 "WPA: Key negotiation completed with "
1135 MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr),
1136 wpa_cipher_txt(sm->pairwise_cipher),
1137 wpa_cipher_txt(sm->group_cipher));
1138 wpa_sm_cancel_auth_timeout(sm);
1139 wpa_sm_set_state(sm, WPA_COMPLETED);
1140
1141 if (secure) {
1142 wpa_sm_mlme_setprotection(
1143 sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,
1144 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
Hai Shalome21d4e82020-04-29 16:34:06 -07001145 eapol_sm_notify_portValid(sm->eapol, true);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001146 if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) ||
1147 sm->key_mgmt == WPA_KEY_MGMT_DPP ||
1148 sm->key_mgmt == WPA_KEY_MGMT_OWE)
Hai Shalome21d4e82020-04-29 16:34:06 -07001149 eapol_sm_notify_eap_success(sm->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001150 /*
1151 * Start preauthentication after a short wait to avoid a
1152 * possible race condition between the data receive and key
1153 * configuration after the 4-Way Handshake. This increases the
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001154 * likelihood of the first preauth EAPOL-Start frame getting to
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001155 * the target AP.
1156 */
Hai Shalom74f70d42019-02-11 14:42:39 -08001157 if (!dl_list_empty(&sm->pmksa_candidates))
1158 eloop_register_timeout(1, 0, wpa_sm_start_preauth,
1159 sm, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001160 }
1161
1162 if (sm->cur_pmksa && sm->cur_pmksa->opportunistic) {
1163 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1164 "RSN: Authenticator accepted "
1165 "opportunistic PMKSA entry - marking it valid");
1166 sm->cur_pmksa->opportunistic = 0;
1167 }
1168
1169#ifdef CONFIG_IEEE80211R
1170 if (wpa_key_mgmt_ft(sm->key_mgmt)) {
1171 /* Prepare for the next transition */
1172 wpa_ft_prepare_auth_request(sm, NULL);
1173 }
1174#endif /* CONFIG_IEEE80211R */
1175}
1176
1177
1178static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
1179{
1180 struct wpa_sm *sm = eloop_ctx;
1181 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Request PTK rekeying");
1182 wpa_sm_key_request(sm, 0, 1);
1183}
1184
1185
1186static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
Hai Shalomfdcde762020-04-02 11:19:20 -07001187 const struct wpa_eapol_key *key,
1188 enum key_flag key_flag)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001189{
1190 int keylen, rsclen;
1191 enum wpa_alg alg;
1192 const u8 *key_rsc;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001193
Mathy Vanhoefc66556c2017-09-29 04:22:51 +02001194 if (sm->ptk.installed) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001195 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1196 "WPA: Do not re-install same PTK to the driver");
1197 return 0;
1198 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001199
1200 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1201 "WPA: Installing PTK to the driver");
1202
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001203 if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001204 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher "
1205 "Suite: NONE - do not use pairwise keys");
1206 return 0;
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001207 }
1208
1209 if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1211 "WPA: Unsupported pairwise cipher %d",
1212 sm->pairwise_cipher);
1213 return -1;
1214 }
1215
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001216 alg = wpa_cipher_to_alg(sm->pairwise_cipher);
1217 keylen = wpa_cipher_key_len(sm->pairwise_cipher);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001218 if (keylen <= 0 || (unsigned int) keylen != sm->ptk.tk_len) {
1219 wpa_printf(MSG_DEBUG, "WPA: TK length mismatch: %d != %lu",
1220 keylen, (long unsigned int) sm->ptk.tk_len);
1221 return -1;
1222 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001223 rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
1224
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001225 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001226 key_rsc = null_rsc;
1227 } else {
1228 key_rsc = key->key_rsc;
1229 wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen);
1230 }
1231
Sunil Ravi77d572f2023-01-17 23:58:31 +00001232 if (wpa_sm_set_key(sm, -1, alg, wpa_sm_get_auth_addr(sm),
1233 sm->keyidx_active, 1, key_rsc, rsclen, sm->ptk.tk,
1234 keylen, KEY_FLAG_PAIRWISE | key_flag) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001235 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001236 "WPA: Failed to set PTK to the driver (alg=%d keylen=%d auth_addr="
Hai Shalomfdcde762020-04-02 11:19:20 -07001237 MACSTR " idx=%d key_flag=0x%x)",
Sunil Ravi77d572f2023-01-17 23:58:31 +00001238 alg, keylen, MAC2STR(wpa_sm_get_auth_addr(sm)),
Hai Shalomfdcde762020-04-02 11:19:20 -07001239 sm->keyidx_active, key_flag);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001240 return -1;
1241 }
1242
Sunil Ravi89eba102022-09-13 21:04:37 -07001243#ifdef CONFIG_PASN
1244 if (sm->secure_ltf &&
1245 ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
1246 wpa_sm_set_ltf_keyseed(sm, sm->own_addr, sm->bssid,
1247 sm->ptk.ltf_keyseed_len,
1248 sm->ptk.ltf_keyseed) < 0) {
1249 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1250 "WPA: Failed to set LTF keyseed to the driver (keylen=%zu bssid="
1251 MACSTR ")", sm->ptk.ltf_keyseed_len,
1252 MAC2STR(sm->bssid));
1253 return -1;
1254 }
1255#endif /* CONFIG_PASN */
1256
Hai Shalom60840252021-02-19 19:02:11 -08001257 wpa_sm_store_ptk(sm, sm->bssid, sm->pairwise_cipher,
1258 sm->dot11RSNAConfigPMKLifetime, &sm->ptk);
1259
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001260 /* TK is not needed anymore in supplicant */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08001261 os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001262 sm->ptk.tk_len = 0;
Mathy Vanhoefc66556c2017-09-29 04:22:51 +02001263 sm->ptk.installed = 1;
Sunil8cd6f4d2022-06-28 18:40:46 +00001264 sm->tk_set = true;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001265
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001266 if (sm->wpa_ptk_rekey) {
1267 eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
1268 eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk,
1269 sm, NULL);
1270 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001271 return 0;
1272}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001273
Hai Shalomfdcde762020-04-02 11:19:20 -07001274
1275static int wpa_supplicant_activate_ptk(struct wpa_sm *sm)
1276{
1277 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001278 "WPA: Activate PTK (idx=%d auth_addr=" MACSTR ")",
1279 sm->keyidx_active, MAC2STR(wpa_sm_get_auth_addr(sm)));
Hai Shalomfdcde762020-04-02 11:19:20 -07001280
Sunil Ravi77d572f2023-01-17 23:58:31 +00001281 if (wpa_sm_set_key(sm, -1, 0, wpa_sm_get_auth_addr(sm),
1282 sm->keyidx_active, 0, NULL, 0, NULL, 0,
1283 KEY_FLAG_PAIRWISE_RX_TX_MODIFY) < 0) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001284 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001285 "WPA: Failed to activate PTK for TX (idx=%d auth_addr="
1286 MACSTR ")", sm->keyidx_active,
1287 MAC2STR(wpa_sm_get_auth_addr(sm)));
Hai Shalomfdcde762020-04-02 11:19:20 -07001288 return -1;
1289 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001290 return 0;
1291}
1292
1293
1294static int wpa_supplicant_check_group_cipher(struct wpa_sm *sm,
1295 int group_cipher,
1296 int keylen, int maxkeylen,
1297 int *key_rsc_len,
1298 enum wpa_alg *alg)
1299{
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001300 int klen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001301
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001302 *alg = wpa_cipher_to_alg(group_cipher);
1303 if (*alg == WPA_ALG_NONE) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001304 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1305 "WPA: Unsupported Group Cipher %d",
1306 group_cipher);
1307 return -1;
1308 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001309 *key_rsc_len = wpa_cipher_rsc_len(group_cipher);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001310
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001311 klen = wpa_cipher_key_len(group_cipher);
1312 if (keylen != klen || maxkeylen < klen) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001313 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1314 "WPA: Unsupported %s Group Cipher key length %d (%d)",
1315 wpa_cipher_txt(group_cipher), keylen, maxkeylen);
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001316 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001317 }
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07001318 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001319}
1320
1321
1322struct wpa_gtk_data {
1323 enum wpa_alg alg;
1324 int tx, key_rsc_len, keyidx;
1325 u8 gtk[32];
1326 int gtk_len;
1327};
1328
1329
1330static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
1331 const struct wpa_gtk_data *gd,
Jouni Malinen58c0e962017-10-01 12:12:24 +03001332 const u8 *key_rsc, int wnm_sleep)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001333{
1334 const u8 *_gtk = gd->gtk;
1335 u8 gtk_buf[32];
1336
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001337 /* Detect possible key reinstallation */
Jouni Malinen58c0e962017-10-01 12:12:24 +03001338 if ((sm->gtk.gtk_len == (size_t) gd->gtk_len &&
1339 os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) ||
1340 (sm->gtk_wnm_sleep.gtk_len == (size_t) gd->gtk_len &&
1341 os_memcmp(sm->gtk_wnm_sleep.gtk, gd->gtk,
1342 sm->gtk_wnm_sleep.gtk_len) == 0)) {
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001343 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1344 "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)",
1345 gd->keyidx, gd->tx, gd->gtk_len);
1346 return 0;
1347 }
1348
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001349 wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
1350 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1351 "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
1352 gd->keyidx, gd->tx, gd->gtk_len);
1353 wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len);
1354 if (sm->group_cipher == WPA_CIPHER_TKIP) {
1355 /* Swap Tx/Rx keys for Michael MIC */
1356 os_memcpy(gtk_buf, gd->gtk, 16);
1357 os_memcpy(gtk_buf + 16, gd->gtk + 24, 8);
1358 os_memcpy(gtk_buf + 24, gd->gtk + 16, 8);
1359 _gtk = gtk_buf;
1360 }
1361 if (sm->pairwise_cipher == WPA_CIPHER_NONE) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00001362 if (wpa_sm_set_key(sm, -1, gd->alg, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363 gd->keyidx, 1, key_rsc, gd->key_rsc_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07001364 _gtk, gd->gtk_len,
1365 KEY_FLAG_GROUP_RX_TX_DEFAULT) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1367 "WPA: Failed to set GTK to the driver "
1368 "(Group only)");
Hai Shalom81f62d82019-07-22 12:10:00 -07001369 forced_memzero(gtk_buf, sizeof(gtk_buf));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370 return -1;
1371 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00001372 } else if (wpa_sm_set_key(sm, -1, gd->alg, broadcast_ether_addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001373 gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len,
Hai Shalomfdcde762020-04-02 11:19:20 -07001374 _gtk, gd->gtk_len, KEY_FLAG_GROUP_RX) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001375 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1376 "WPA: Failed to set GTK to "
1377 "the driver (alg=%d keylen=%d keyidx=%d)",
1378 gd->alg, gd->gtk_len, gd->keyidx);
Hai Shalom81f62d82019-07-22 12:10:00 -07001379 forced_memzero(gtk_buf, sizeof(gtk_buf));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001380 return -1;
1381 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001382 forced_memzero(gtk_buf, sizeof(gtk_buf));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001383
Jouni Malinen58c0e962017-10-01 12:12:24 +03001384 if (wnm_sleep) {
1385 sm->gtk_wnm_sleep.gtk_len = gd->gtk_len;
1386 os_memcpy(sm->gtk_wnm_sleep.gtk, gd->gtk,
1387 sm->gtk_wnm_sleep.gtk_len);
1388 } else {
1389 sm->gtk.gtk_len = gd->gtk_len;
1390 os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
1391 }
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001392
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001393 return 0;
1394}
1395
1396
Sunil Ravi77d572f2023-01-17 23:58:31 +00001397static int wpa_supplicant_install_mlo_gtk(struct wpa_sm *sm, u8 link_id,
1398 const struct wpa_gtk_data *gd,
1399 const u8 *key_rsc, int wnm_sleep)
1400{
1401 const u8 *gtk = gd->gtk;
1402
1403 /* Detect possible key reinstallation */
1404 if ((sm->mlo.links[link_id].gtk.gtk_len == (size_t) gd->gtk_len &&
1405 os_memcmp(sm->mlo.links[link_id].gtk.gtk, gd->gtk,
1406 sm->mlo.links[link_id].gtk.gtk_len) == 0) ||
1407 (sm->mlo.links[link_id].gtk_wnm_sleep.gtk_len ==
1408 (size_t) gd->gtk_len &&
1409 os_memcmp(sm->mlo.links[link_id].gtk_wnm_sleep.gtk, gd->gtk,
1410 sm->mlo.links[link_id].gtk_wnm_sleep.gtk_len) == 0)) {
1411 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1412 "RSN: Not reinstalling already in-use GTK to the driver (link_id=%d keyidx=%d tx=%d len=%d)",
1413 link_id, gd->keyidx, gd->tx, gd->gtk_len);
1414 return 0;
1415 }
1416
1417 wpa_hexdump_link_key(MSG_DEBUG, link_id, "RSN: Group Key", gd->gtk,
1418 gd->gtk_len);
1419 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1420 "RSN: Installing GTK to the driver (link_id=%d keyidx=%d tx=%d len=%d)",
1421 link_id, gd->keyidx, gd->tx, gd->gtk_len);
1422 wpa_hexdump_link(MSG_DEBUG, link_id, "RSN: RSC",
1423 key_rsc, gd->key_rsc_len);
1424 if (wpa_sm_set_key(sm, link_id, gd->alg, broadcast_ether_addr,
1425 gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, gtk,
1426 gd->gtk_len, KEY_FLAG_GROUP_RX) < 0) {
1427 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1428 "RSN: Failed to set GTK to the driver (link_id=%d alg=%d keylen=%d keyidx=%d)",
1429 link_id, gd->alg, gd->gtk_len, gd->keyidx);
1430 return -1;
1431 }
1432
1433 if (wnm_sleep) {
1434 sm->mlo.links[link_id].gtk_wnm_sleep.gtk_len = gd->gtk_len;
1435 os_memcpy(sm->mlo.links[link_id].gtk_wnm_sleep.gtk, gd->gtk,
1436 sm->mlo.links[link_id].gtk_wnm_sleep.gtk_len);
1437 } else {
1438 sm->mlo.links[link_id].gtk.gtk_len = gd->gtk_len;
1439 os_memcpy(sm->mlo.links[link_id].gtk.gtk, gd->gtk,
1440 sm->mlo.links[link_id].gtk.gtk_len);
1441 }
1442
1443 return 0;
1444}
1445
1446
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001447static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm,
1448 int tx)
1449{
1450 if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) {
1451 /* Ignore Tx bit for GTK if a pairwise key is used. One AP
1452 * seemed to set this bit (incorrectly, since Tx is only when
1453 * doing Group Key only APs) and without this workaround, the
1454 * data connection does not work because wpa_supplicant
1455 * configured non-zero keyidx to be used for unicast. */
1456 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1457 "WPA: Tx bit set for GTK, but pairwise "
1458 "keys are used - ignore Tx bit");
1459 return 0;
1460 }
1461 return tx;
1462}
1463
1464
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001465static int wpa_supplicant_rsc_relaxation(const struct wpa_sm *sm,
1466 const u8 *rsc)
1467{
1468 int rsclen;
1469
1470 if (!sm->wpa_rsc_relaxation)
1471 return 0;
1472
1473 rsclen = wpa_cipher_rsc_len(sm->group_cipher);
1474
1475 /*
1476 * Try to detect RSC (endian) corruption issue where the AP sends
1477 * the RSC bytes in EAPOL-Key message in the wrong order, both if
1478 * it's actually a 6-byte field (as it should be) and if it treats
1479 * it as an 8-byte field.
1480 * An AP model known to have this bug is the Sapido RB-1632.
1481 */
1482 if (rsclen == 6 && ((rsc[5] && !rsc[0]) || rsc[6] || rsc[7])) {
1483 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1484 "RSC %02x%02x%02x%02x%02x%02x%02x%02x is likely bogus, using 0",
1485 rsc[0], rsc[1], rsc[2], rsc[3],
1486 rsc[4], rsc[5], rsc[6], rsc[7]);
1487
1488 return 1;
1489 }
1490
1491 return 0;
1492}
1493
1494
Sunil Ravi77d572f2023-01-17 23:58:31 +00001495static int wpa_supplicant_mlo_gtk(struct wpa_sm *sm, u8 link_id, const u8 *gtk,
1496 size_t gtk_len, int key_info)
1497{
1498 struct wpa_gtk_data gd;
1499 const u8 *key_rsc;
1500 int ret;
1501
1502 /*
1503 * MLO GTK KDE format:
1504 * KeyID[bits 0-1], Tx [bit 2], Reserved [bit 3], link id [4-7]
1505 * PN
1506 * GTK
1507 */
1508 os_memset(&gd, 0, sizeof(gd));
1509 wpa_hexdump_link_key(MSG_DEBUG, link_id,
1510 "RSN: received GTK in pairwise handshake",
1511 gtk, gtk_len);
1512
1513 if (gtk_len < RSN_MLO_GTK_KDE_PREFIX_LENGTH ||
1514 gtk_len - RSN_MLO_GTK_KDE_PREFIX_LENGTH > sizeof(gd.gtk))
1515 return -1;
1516
1517 gd.keyidx = gtk[0] & 0x3;
1518 gtk += 1;
1519 gtk_len -= 1;
1520
1521 key_rsc = gtk;
1522
1523 gtk += 6;
1524 gtk_len -= 6;
1525
1526 os_memcpy(gd.gtk, gtk, gtk_len);
1527 gd.gtk_len = gtk_len;
1528
1529 ret = 0;
1530 if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, gtk_len,
1531 gtk_len, &gd.key_rsc_len,
1532 &gd.alg) ||
1533 wpa_supplicant_install_mlo_gtk(sm, link_id, &gd, key_rsc, 0)) {
1534 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1535 "RSN: Failed to install GTK for MLO Link ID %u",
1536 link_id);
1537 ret = -1;
1538 goto out;
1539 }
1540
1541out:
1542 forced_memzero(&gd, sizeof(gd));
1543 return ret;
1544}
1545
1546
1547static int wpa_supplicant_pairwise_mlo_gtk(struct wpa_sm *sm,
1548 const struct wpa_eapol_key *key,
1549 struct wpa_eapol_ie_parse *ie,
1550 int key_info)
1551{
1552 u8 i;
1553
Sunil Ravi88611412024-06-28 17:34:56 +00001554 for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
1555 if (!(sm->mlo.valid_links & BIT(i)))
1556 continue;
1557
Sunil Ravi77d572f2023-01-17 23:58:31 +00001558 if (!ie->mlo_gtk[i]) {
1559 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
1560 "MLO RSN: GTK not found for link ID %u", i);
1561 return -1;
1562 }
1563
1564 if (wpa_supplicant_mlo_gtk(sm, i, ie->mlo_gtk[i],
1565 ie->mlo_gtk_len[i], key_info))
1566 return -1;
1567 }
1568
1569 return 0;
1570}
1571
1572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001573static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm,
1574 const struct wpa_eapol_key *key,
1575 const u8 *gtk, size_t gtk_len,
1576 int key_info)
1577{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001578 struct wpa_gtk_data gd;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001579 const u8 *key_rsc;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001580
1581 /*
1582 * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x
1583 * GTK KDE format:
1584 * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7]
1585 * Reserved [bits 0-7]
1586 * GTK
1587 */
1588
1589 os_memset(&gd, 0, sizeof(gd));
1590 wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake",
1591 gtk, gtk_len);
1592
1593 if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk))
1594 return -1;
1595
1596 gd.keyidx = gtk[0] & 0x3;
1597 gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
1598 !!(gtk[0] & BIT(2)));
1599 gtk += 2;
1600 gtk_len -= 2;
1601
1602 os_memcpy(gd.gtk, gtk, gtk_len);
1603 gd.gtk_len = gtk_len;
1604
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001605 key_rsc = key->key_rsc;
1606 if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
1607 key_rsc = null_rsc;
1608
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001609 if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED &&
1610 (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
1611 gtk_len, gtk_len,
1612 &gd.key_rsc_len, &gd.alg) ||
Jouni Malinen58c0e962017-10-01 12:12:24 +03001613 wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001614 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1615 "RSN: Failed to install GTK");
Hai Shalom81f62d82019-07-22 12:10:00 -07001616 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001617 return -1;
1618 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001619 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001620
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001621 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622}
1623
1624
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001625static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
Jouni Malinen58c0e962017-10-01 12:12:24 +03001626 const struct wpa_igtk_kde *igtk,
1627 int wnm_sleep)
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001628{
1629 size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1630 u16 keyidx = WPA_GET_LE16(igtk->keyid);
1631
1632 /* Detect possible key reinstallation */
Jouni Malinen58c0e962017-10-01 12:12:24 +03001633 if ((sm->igtk.igtk_len == len &&
1634 os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) ||
1635 (sm->igtk_wnm_sleep.igtk_len == len &&
1636 os_memcmp(sm->igtk_wnm_sleep.igtk, igtk->igtk,
1637 sm->igtk_wnm_sleep.igtk_len) == 0)) {
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001638 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1639 "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)",
1640 keyidx);
1641 return 0;
1642 }
1643
1644 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001645 "WPA: IGTK keyid %d pn " COMPACT_MACSTR,
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001646 keyidx, MAC2STR(igtk->pn));
1647 wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len);
1648 if (keyidx > 4095) {
1649 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1650 "WPA: Invalid IGTK KeyID %d", keyidx);
1651 return -1;
1652 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00001653 if (wpa_sm_set_key(sm, -1, wpa_cipher_to_alg(sm->mgmt_group_cipher),
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001654 broadcast_ether_addr,
1655 keyidx, 0, igtk->pn, sizeof(igtk->pn),
Hai Shalomfdcde762020-04-02 11:19:20 -07001656 igtk->igtk, len, KEY_FLAG_GROUP_RX) < 0) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07001657 if (keyidx == 0x0400 || keyidx == 0x0500) {
1658 /* Assume the AP has broken PMF implementation since it
1659 * seems to have swapped the KeyID bytes. The AP cannot
1660 * be trusted to implement BIP correctly or provide a
1661 * valid IGTK, so do not try to configure this key with
1662 * swapped KeyID bytes. Instead, continue without
1663 * configuring the IGTK so that the driver can drop any
1664 * received group-addressed robust management frames due
1665 * to missing keys.
1666 *
1667 * Normally, this error behavior would result in us
1668 * disconnecting, but there are number of deployed APs
1669 * with this broken behavior, so as an interoperability
1670 * workaround, allow the connection to proceed. */
1671 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1672 "WPA: Ignore IGTK configuration error due to invalid IGTK KeyID byte order");
1673 } else {
1674 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1675 "WPA: Failed to configure IGTK to the driver");
1676 return -1;
1677 }
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001678 }
1679
Jouni Malinen58c0e962017-10-01 12:12:24 +03001680 if (wnm_sleep) {
1681 sm->igtk_wnm_sleep.igtk_len = len;
1682 os_memcpy(sm->igtk_wnm_sleep.igtk, igtk->igtk,
1683 sm->igtk_wnm_sleep.igtk_len);
1684 } else {
1685 sm->igtk.igtk_len = len;
1686 os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
1687 }
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001688
1689 return 0;
1690}
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001691
1692
Hai Shalomfdcde762020-04-02 11:19:20 -07001693static int wpa_supplicant_install_bigtk(struct wpa_sm *sm,
1694 const struct wpa_bigtk_kde *bigtk,
1695 int wnm_sleep)
1696{
1697 size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1698 u16 keyidx = WPA_GET_LE16(bigtk->keyid);
1699
1700 /* Detect possible key reinstallation */
1701 if ((sm->bigtk.bigtk_len == len &&
1702 os_memcmp(sm->bigtk.bigtk, bigtk->bigtk,
1703 sm->bigtk.bigtk_len) == 0) ||
1704 (sm->bigtk_wnm_sleep.bigtk_len == len &&
1705 os_memcmp(sm->bigtk_wnm_sleep.bigtk, bigtk->bigtk,
1706 sm->bigtk_wnm_sleep.bigtk_len) == 0)) {
1707 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1708 "WPA: Not reinstalling already in-use BIGTK to the driver (keyidx=%d)",
1709 keyidx);
1710 return 0;
1711 }
1712
1713 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1714 "WPA: BIGTK keyid %d pn " COMPACT_MACSTR,
1715 keyidx, MAC2STR(bigtk->pn));
1716 wpa_hexdump_key(MSG_DEBUG, "WPA: BIGTK", bigtk->bigtk, len);
1717 if (keyidx < 6 || keyidx > 7) {
1718 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1719 "WPA: Invalid BIGTK KeyID %d", keyidx);
1720 return -1;
1721 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00001722 if (wpa_sm_set_key(sm, -1, wpa_cipher_to_alg(sm->mgmt_group_cipher),
Hai Shalomfdcde762020-04-02 11:19:20 -07001723 broadcast_ether_addr,
1724 keyidx, 0, bigtk->pn, sizeof(bigtk->pn),
1725 bigtk->bigtk, len, KEY_FLAG_GROUP_RX) < 0) {
1726 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1727 "WPA: Failed to configure BIGTK to the driver");
1728 return -1;
1729 }
1730
1731 if (wnm_sleep) {
1732 sm->bigtk_wnm_sleep.bigtk_len = len;
1733 os_memcpy(sm->bigtk_wnm_sleep.bigtk, bigtk->bigtk,
1734 sm->bigtk_wnm_sleep.bigtk_len);
1735 } else {
1736 sm->bigtk.bigtk_len = len;
1737 os_memcpy(sm->bigtk.bigtk, bigtk->bigtk, sm->bigtk.bigtk_len);
1738 }
1739
1740 return 0;
1741}
1742
1743
Sunil Ravi77d572f2023-01-17 23:58:31 +00001744static int wpa_supplicant_install_mlo_igtk(struct wpa_sm *sm, u8 link_id,
1745 const struct rsn_mlo_igtk_kde *igtk,
1746 int wnm_sleep)
1747{
1748 size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1749 u16 keyidx = WPA_GET_LE16(igtk->keyid);
1750
1751 /* Detect possible key reinstallation */
1752 if ((sm->mlo.links[link_id].igtk.igtk_len == len &&
1753 os_memcmp(sm->mlo.links[link_id].igtk.igtk, igtk->igtk,
1754 sm->mlo.links[link_id].igtk.igtk_len) == 0) ||
1755 (sm->mlo.links[link_id].igtk_wnm_sleep.igtk_len == len &&
1756 os_memcmp(sm->mlo.links[link_id].igtk_wnm_sleep.igtk, igtk->igtk,
1757 sm->mlo.links[link_id].igtk_wnm_sleep.igtk_len) == 0)) {
1758 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1759 "RSN: Not reinstalling already in-use IGTK to the driver (link_id=%d keyidx=%d)",
1760 link_id, keyidx);
1761 return 0;
1762 }
1763
1764 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1765 "RSN: MLO Link %u IGTK keyid %d pn " COMPACT_MACSTR,
1766 link_id, keyidx, MAC2STR(igtk->pn));
1767 wpa_hexdump_link_key(MSG_DEBUG, link_id, "RSN: IGTK", igtk->igtk, len);
1768 if (keyidx > 4095) {
1769 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1770 "RSN: Invalid MLO Link %d IGTK KeyID %d", link_id,
1771 keyidx);
1772 return -1;
1773 }
1774 if (wpa_sm_set_key(sm, link_id,
1775 wpa_cipher_to_alg(sm->mgmt_group_cipher),
1776 broadcast_ether_addr, keyidx, 0, igtk->pn,
1777 sizeof(igtk->pn), igtk->igtk, len,
1778 KEY_FLAG_GROUP_RX) < 0) {
1779 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1780 "RSN: Failed to configure MLO Link %d IGTK to the driver",
1781 link_id);
1782 return -1;
1783 }
1784
1785 if (wnm_sleep) {
1786 sm->mlo.links[link_id].igtk_wnm_sleep.igtk_len = len;
1787 os_memcpy(sm->mlo.links[link_id].igtk_wnm_sleep.igtk,
1788 igtk->igtk,
1789 sm->mlo.links[link_id].igtk_wnm_sleep.igtk_len);
1790 } else {
1791 sm->mlo.links[link_id].igtk.igtk_len = len;
1792 os_memcpy(sm->mlo.links[link_id].igtk.igtk, igtk->igtk,
1793 sm->mlo.links[link_id].igtk.igtk_len);
1794 }
1795
1796 return 0;
1797}
1798
1799
1800static int
1801wpa_supplicant_install_mlo_bigtk(struct wpa_sm *sm, u8 link_id,
1802 const struct rsn_mlo_bigtk_kde *bigtk,
1803 int wnm_sleep)
1804{
1805 size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1806 u16 keyidx = WPA_GET_LE16(bigtk->keyid);
1807
1808 /* Detect possible key reinstallation */
1809 if ((sm->mlo.links[link_id].bigtk.bigtk_len == len &&
1810 os_memcmp(sm->mlo.links[link_id].bigtk.bigtk, bigtk->bigtk,
1811 sm->mlo.links[link_id].bigtk.bigtk_len) == 0) ||
1812 (sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk_len == len &&
1813 os_memcmp(sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk,
1814 bigtk->bigtk,
1815 sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk_len) ==
1816 0)) {
1817 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1818 "RSN: Not reinstalling already in-use BIGTK to the driver (link_id=%d keyidx=%d)",
1819 link_id, keyidx);
1820 return 0;
1821 }
1822
1823 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
1824 "RSN: MLO Link %u BIGTK keyid %d pn " COMPACT_MACSTR,
1825 link_id, keyidx, MAC2STR(bigtk->pn));
1826 wpa_hexdump_link_key(MSG_DEBUG, link_id, "RSN: BIGTK", bigtk->bigtk,
1827 len);
1828 if (keyidx < 6 || keyidx > 7) {
1829 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1830 "RSN: Invalid MLO Link %d BIGTK KeyID %d", link_id,
1831 keyidx);
1832 return -1;
1833 }
1834 if (wpa_sm_set_key(sm, link_id,
1835 wpa_cipher_to_alg(sm->mgmt_group_cipher),
1836 broadcast_ether_addr, keyidx, 0, bigtk->pn,
1837 sizeof(bigtk->pn), bigtk->bigtk, len,
1838 KEY_FLAG_GROUP_RX) < 0) {
1839 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1840 "RSN: Failed to configure MLO Link %d BIGTK to the driver",
1841 link_id);
1842 return -1;
1843 }
1844
1845 if (wnm_sleep) {
1846 sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk_len = len;
1847 os_memcpy(sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk,
1848 bigtk->bigtk,
1849 sm->mlo.links[link_id].bigtk_wnm_sleep.bigtk_len);
1850 } else {
1851 sm->mlo.links[link_id].bigtk.bigtk_len = len;
1852 os_memcpy(sm->mlo.links[link_id].bigtk.bigtk, bigtk->bigtk,
1853 sm->mlo.links[link_id].bigtk.bigtk_len);
1854 }
1855
1856 return 0;
1857}
1858
1859
1860static int _mlo_ieee80211w_set_keys(struct wpa_sm *sm, u8 link_id,
1861 struct wpa_eapol_ie_parse *ie)
1862{
1863 size_t len;
1864
1865 if (ie->mlo_igtk[link_id]) {
1866 len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1867 if (ie->mlo_igtk_len[link_id] !=
1868 RSN_MLO_IGTK_KDE_PREFIX_LENGTH + len)
1869 return -1;
1870
1871 if (wpa_supplicant_install_mlo_igtk(
1872 sm, link_id,
1873 (const struct rsn_mlo_igtk_kde *)
1874 ie->mlo_igtk[link_id],
1875 0) < 0)
1876 return -1;
1877 }
1878
1879 if (ie->mlo_bigtk[link_id] && sm->beacon_prot) {
1880 len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1881 if (ie->mlo_bigtk_len[link_id] !=
1882 RSN_MLO_BIGTK_KDE_PREFIX_LENGTH + len)
1883 return -1;
1884
1885 if (wpa_supplicant_install_mlo_bigtk(
1886 sm, link_id,
1887 (const struct rsn_mlo_bigtk_kde *)
1888 ie->mlo_bigtk[link_id],
1889 0) < 0)
1890 return -1;
1891 }
1892
1893 return 0;
1894}
1895
1896
1897static int mlo_ieee80211w_set_keys(struct wpa_sm *sm,
1898 struct wpa_eapol_ie_parse *ie)
1899{
1900 u8 i;
1901
1902 if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) ||
1903 sm->mgmt_group_cipher == WPA_CIPHER_GTK_NOT_USED)
1904 return 0;
1905
Sunil Ravi88611412024-06-28 17:34:56 +00001906 for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
1907 if (!(sm->mlo.valid_links & BIT(i)))
1908 continue;
1909
Sunil Ravi77d572f2023-01-17 23:58:31 +00001910 if (_mlo_ieee80211w_set_keys(sm, i, ie))
1911 return -1;
1912 }
1913
1914 return 0;
1915}
1916
1917
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001918static int ieee80211w_set_keys(struct wpa_sm *sm,
1919 struct wpa_eapol_ie_parse *ie)
1920{
Hai Shalomfdcde762020-04-02 11:19:20 -07001921 size_t len;
1922
Hai Shalom60840252021-02-19 19:02:11 -08001923 if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) ||
1924 sm->mgmt_group_cipher == WPA_CIPHER_GTK_NOT_USED)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001925 return 0;
1926
1927 if (ie->igtk) {
1928 const struct wpa_igtk_kde *igtk;
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001929
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001930 len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1931 if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001932 return -1;
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02001933
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001934 igtk = (const struct wpa_igtk_kde *) ie->igtk;
Jouni Malinen58c0e962017-10-01 12:12:24 +03001935 if (wpa_supplicant_install_igtk(sm, igtk, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001937 }
1938
Hai Shalomfdcde762020-04-02 11:19:20 -07001939 if (ie->bigtk && sm->beacon_prot) {
1940 const struct wpa_bigtk_kde *bigtk;
1941
1942 len = wpa_cipher_key_len(sm->mgmt_group_cipher);
1943 if (ie->bigtk_len != WPA_BIGTK_KDE_PREFIX_LEN + len)
1944 return -1;
1945
1946 bigtk = (const struct wpa_bigtk_kde *) ie->bigtk;
1947 if (wpa_supplicant_install_bigtk(sm, bigtk, 0) < 0)
1948 return -1;
1949 }
1950
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001951 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001952}
1953
1954
1955static void wpa_report_ie_mismatch(struct wpa_sm *sm,
1956 const char *reason, const u8 *src_addr,
1957 const u8 *wpa_ie, size_t wpa_ie_len,
1958 const u8 *rsn_ie, size_t rsn_ie_len)
1959{
1960 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")",
1961 reason, MAC2STR(src_addr));
1962
1963 if (sm->ap_wpa_ie) {
1964 wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp",
1965 sm->ap_wpa_ie, sm->ap_wpa_ie_len);
1966 }
1967 if (wpa_ie) {
1968 if (!sm->ap_wpa_ie) {
1969 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1970 "WPA: No WPA IE in Beacon/ProbeResp");
1971 }
1972 wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg",
1973 wpa_ie, wpa_ie_len);
1974 }
1975
1976 if (sm->ap_rsn_ie) {
1977 wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp",
1978 sm->ap_rsn_ie, sm->ap_rsn_ie_len);
1979 }
1980 if (rsn_ie) {
1981 if (!sm->ap_rsn_ie) {
1982 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
1983 "WPA: No RSN IE in Beacon/ProbeResp");
1984 }
1985 wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg",
1986 rsn_ie, rsn_ie_len);
1987 }
1988
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001989 wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001990}
1991
1992
1993#ifdef CONFIG_IEEE80211R
1994
1995static int ft_validate_mdie(struct wpa_sm *sm,
1996 const unsigned char *src_addr,
1997 struct wpa_eapol_ie_parse *ie,
1998 const u8 *assoc_resp_mdie)
1999{
2000 struct rsn_mdie *mdie;
2001
2002 mdie = (struct rsn_mdie *) (ie->mdie + 2);
2003 if (ie->mdie == NULL || ie->mdie_len < 2 + sizeof(*mdie) ||
2004 os_memcmp(mdie->mobility_domain, sm->mobility_domain,
2005 MOBILITY_DOMAIN_ID_LEN) != 0) {
2006 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE in msg 3/4 did "
2007 "not match with the current mobility domain");
2008 return -1;
2009 }
2010
2011 if (assoc_resp_mdie &&
2012 (assoc_resp_mdie[1] != ie->mdie[1] ||
2013 os_memcmp(assoc_resp_mdie, ie->mdie, 2 + ie->mdie[1]) != 0)) {
2014 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: MDIE mismatch");
2015 wpa_hexdump(MSG_DEBUG, "FT: MDIE in EAPOL-Key msg 3/4",
2016 ie->mdie, 2 + ie->mdie[1]);
2017 wpa_hexdump(MSG_DEBUG, "FT: MDIE in (Re)Association Response",
2018 assoc_resp_mdie, 2 + assoc_resp_mdie[1]);
2019 return -1;
2020 }
2021
2022 return 0;
2023}
2024
2025
2026static int ft_validate_ftie(struct wpa_sm *sm,
2027 const unsigned char *src_addr,
2028 struct wpa_eapol_ie_parse *ie,
2029 const u8 *assoc_resp_ftie)
2030{
2031 if (ie->ftie == NULL) {
2032 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2033 "FT: No FTIE in EAPOL-Key msg 3/4");
2034 return -1;
2035 }
2036
2037 if (assoc_resp_ftie == NULL)
2038 return 0;
2039
2040 if (assoc_resp_ftie[1] != ie->ftie[1] ||
2041 os_memcmp(assoc_resp_ftie, ie->ftie, 2 + ie->ftie[1]) != 0) {
2042 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: FTIE mismatch");
2043 wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 3/4",
2044 ie->ftie, 2 + ie->ftie[1]);
2045 wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)Association Response",
2046 assoc_resp_ftie, 2 + assoc_resp_ftie[1]);
2047 return -1;
2048 }
2049
2050 return 0;
2051}
2052
2053
2054static int ft_validate_rsnie(struct wpa_sm *sm,
2055 const unsigned char *src_addr,
2056 struct wpa_eapol_ie_parse *ie)
2057{
2058 struct wpa_ie_data rsn;
2059
2060 if (!ie->rsn_ie)
2061 return 0;
2062
2063 /*
2064 * Verify that PMKR1Name from EAPOL-Key message 3/4
2065 * matches with the value we derived.
2066 */
2067 if (wpa_parse_wpa_ie_rsn(ie->rsn_ie, ie->rsn_ie_len, &rsn) < 0 ||
2068 rsn.num_pmkid != 1 || rsn.pmkid == NULL) {
2069 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "FT: No PMKR1Name in "
2070 "FT 4-way handshake message 3/4");
2071 return -1;
2072 }
2073
Dmitry Shmidtc2817022014-07-02 10:32:10 -07002074 if (os_memcmp_const(rsn.pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0)
2075 {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002076 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2077 "FT: PMKR1Name mismatch in "
2078 "FT 4-way handshake message 3/4");
2079 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Authenticator",
2080 rsn.pmkid, WPA_PMK_NAME_LEN);
2081 wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name",
2082 sm->pmk_r1_name, WPA_PMK_NAME_LEN);
2083 return -1;
2084 }
2085
2086 return 0;
2087}
2088
2089
2090static int wpa_supplicant_validate_ie_ft(struct wpa_sm *sm,
2091 const unsigned char *src_addr,
2092 struct wpa_eapol_ie_parse *ie)
2093{
2094 const u8 *pos, *end, *mdie = NULL, *ftie = NULL;
2095
2096 if (sm->assoc_resp_ies) {
2097 pos = sm->assoc_resp_ies;
2098 end = pos + sm->assoc_resp_ies_len;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002099 while (end - pos > 2) {
2100 if (2 + pos[1] > end - pos)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002101 break;
2102 switch (*pos) {
2103 case WLAN_EID_MOBILITY_DOMAIN:
2104 mdie = pos;
2105 break;
2106 case WLAN_EID_FAST_BSS_TRANSITION:
2107 ftie = pos;
2108 break;
2109 }
2110 pos += 2 + pos[1];
2111 }
2112 }
2113
2114 if (ft_validate_mdie(sm, src_addr, ie, mdie) < 0 ||
2115 ft_validate_ftie(sm, src_addr, ie, ftie) < 0 ||
2116 ft_validate_rsnie(sm, src_addr, ie) < 0)
2117 return -1;
2118
2119 return 0;
2120}
2121
2122#endif /* CONFIG_IEEE80211R */
2123
2124
2125static int wpa_supplicant_validate_ie(struct wpa_sm *sm,
2126 const unsigned char *src_addr,
2127 struct wpa_eapol_ie_parse *ie)
2128{
2129 if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) {
2130 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2131 "WPA: No WPA/RSN IE for this AP known. "
2132 "Trying to get from scan results");
2133 if (wpa_sm_get_beacon_ie(sm) < 0) {
2134 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2135 "WPA: Could not find AP from "
2136 "the scan results");
Hai Shalomfdcde762020-04-02 11:19:20 -07002137 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002138 }
Hai Shalomfdcde762020-04-02 11:19:20 -07002139 wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
2140 "WPA: Found the current AP from updated scan results");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002141 }
2142
2143 if (ie->wpa_ie == NULL && ie->rsn_ie == NULL &&
2144 (sm->ap_wpa_ie || sm->ap_rsn_ie)) {
2145 wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
2146 "with IE in Beacon/ProbeResp (no IE?)",
2147 src_addr, ie->wpa_ie, ie->wpa_ie_len,
2148 ie->rsn_ie, ie->rsn_ie_len);
2149 return -1;
2150 }
2151
2152 if ((ie->wpa_ie && sm->ap_wpa_ie &&
2153 (ie->wpa_ie_len != sm->ap_wpa_ie_len ||
2154 os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) ||
2155 (ie->rsn_ie && sm->ap_rsn_ie &&
2156 wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
2157 sm->ap_rsn_ie, sm->ap_rsn_ie_len,
2158 ie->rsn_ie, ie->rsn_ie_len))) {
2159 wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match "
2160 "with IE in Beacon/ProbeResp",
2161 src_addr, ie->wpa_ie, ie->wpa_ie_len,
2162 ie->rsn_ie, ie->rsn_ie_len);
2163 return -1;
2164 }
2165
2166 if (sm->proto == WPA_PROTO_WPA &&
2167 ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) {
2168 wpa_report_ie_mismatch(sm, "Possible downgrade attack "
2169 "detected - RSN was enabled and RSN IE "
2170 "was in msg 3/4, but not in "
2171 "Beacon/ProbeResp",
2172 src_addr, ie->wpa_ie, ie->wpa_ie_len,
2173 ie->rsn_ie, ie->rsn_ie_len);
2174 return -1;
2175 }
2176
Hai Shalom60840252021-02-19 19:02:11 -08002177 if (sm->proto == WPA_PROTO_RSN &&
2178 ((sm->ap_rsnxe && !ie->rsnxe) ||
2179 (!sm->ap_rsnxe && ie->rsnxe) ||
2180 (sm->ap_rsnxe && ie->rsnxe &&
2181 (sm->ap_rsnxe_len != ie->rsnxe_len ||
2182 os_memcmp(sm->ap_rsnxe, ie->rsnxe, sm->ap_rsnxe_len) != 0)))) {
Hai Shalomc3565922019-10-28 11:58:20 -07002183 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2184 "WPA: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4");
Hai Shalomfdcde762020-04-02 11:19:20 -07002185 wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp",
2186 sm->ap_rsnxe, sm->ap_rsnxe_len);
2187 wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4",
2188 ie->rsnxe, ie->rsnxe_len);
2189 wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
Hai Shalomc3565922019-10-28 11:58:20 -07002190 return -1;
2191 }
2192
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002193#ifdef CONFIG_IEEE80211R
2194 if (wpa_key_mgmt_ft(sm->key_mgmt) &&
2195 wpa_supplicant_validate_ie_ft(sm, src_addr, ie) < 0)
2196 return -1;
2197#endif /* CONFIG_IEEE80211R */
2198
2199 return 0;
2200}
2201
2202
2203/**
2204 * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake
2205 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2206 * @dst: Destination address for the frame
2207 * @key: Pointer to the EAPOL-Key frame header
2208 * @ver: Version bits from EAPOL-Key Key Info
2209 * @key_info: Key Info
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002210 * @ptk: PTK to use for keyed hash and encryption
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002211 * Returns: >= 0 on success, < 0 on failure
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002212 */
2213int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst,
2214 const struct wpa_eapol_key *key,
2215 u16 ver, u16 key_info,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002216 struct wpa_ptk *ptk)
2217{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002218 size_t mic_len, hdrlen, rlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002219 struct wpa_eapol_key *reply;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002220 u8 *rbuf, *key_mic;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002221 u8 *kde = NULL;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002222 size_t kde_len = 0, extra_len = 0;
2223#ifdef CONFIG_TESTING_OPTIONS
2224 size_t pad_len = 0;
2225#endif /* CONFIG_TESTING_OPTIONS */
Sunil Ravi77d572f2023-01-17 23:58:31 +00002226
2227 if (sm->mlo.valid_links) {
2228 u8 *pos;
2229
2230 kde = os_malloc(RSN_SELECTOR_LEN + ETH_ALEN + 2);
2231 if (!kde)
2232 return -1;
2233
2234 /* Add MAC KDE */
2235 wpa_printf(MSG_DEBUG, "MLO: Add MAC KDE into EAPOL-Key 4/4");
2236 pos = kde;
2237 pos = rsn_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, sm->own_addr,
2238 ETH_ALEN);
2239 kde_len = pos - kde;
2240 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002242#ifdef CONFIG_TESTING_OPTIONS
2243 if (sm->test_eapol_m4_elems)
2244 extra_len = wpabuf_len(sm->test_eapol_m4_elems);
2245 if (sm->encrypt_eapol_m4) {
2246 pad_len = (kde_len + extra_len) % 8;
2247 if (pad_len)
2248 pad_len = 8 - pad_len;
2249 extra_len += pad_len + 8;
2250 }
2251#endif /* CONFIG_TESTING_OPTIONS */
2252
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002253 mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002254 hdrlen = sizeof(*reply) + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002255 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002256 hdrlen + kde_len + extra_len, &rlen,
2257 (void *) &reply);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002258 if (!rbuf) {
2259 os_free(kde);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002260 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002261 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002262
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002263 reply->type = (sm->proto == WPA_PROTO_RSN ||
2264 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002265 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
2266 key_info &= WPA_KEY_INFO_SECURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002267 key_info |= ver | WPA_KEY_INFO_KEY_TYPE;
2268 if (mic_len)
2269 key_info |= WPA_KEY_INFO_MIC;
2270 else
2271 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002272#ifdef CONFIG_TESTING_OPTIONS
2273 if (sm->encrypt_eapol_m4)
2274 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
2275#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276 WPA_PUT_BE16(reply->key_info, key_info);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002277 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002278 WPA_PUT_BE16(reply->key_length, 0);
2279 else
2280 os_memcpy(reply->key_length, key->key_length, 2);
2281 os_memcpy(reply->replay_counter, key->replay_counter,
2282 WPA_REPLAY_COUNTER_LEN);
2283
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002284 key_mic = (u8 *) (reply + 1);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002285 /* Key Data length */
2286 WPA_PUT_BE16(key_mic + mic_len, kde_len + extra_len);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002287 if (kde) {
2288 os_memcpy(key_mic + mic_len + 2, kde, kde_len); /* Key Data */
2289 os_free(kde);
2290 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002291
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002292#ifdef CONFIG_TESTING_OPTIONS
2293 if (sm->test_eapol_m4_elems) {
2294 os_memcpy(key_mic + mic_len + 2 + kde_len,
2295 wpabuf_head(sm->test_eapol_m4_elems),
2296 wpabuf_len(sm->test_eapol_m4_elems));
2297 }
2298
2299 if (sm->encrypt_eapol_m4) {
2300 u8 *plain;
2301 size_t plain_len;
2302
2303 if (sm->test_eapol_m4_elems)
2304 extra_len = wpabuf_len(sm->test_eapol_m4_elems);
2305 else
2306 extra_len = 0;
2307 plain_len = kde_len + extra_len + pad_len;
2308 plain = os_memdup(key_mic + mic_len + 2, plain_len);
2309 if (!plain) {
2310 os_free(rbuf);
2311 return -1;
2312 }
2313 if (pad_len)
2314 plain[plain_len - pad_len] = 0xdd;
2315
2316 wpa_hexdump_key(MSG_DEBUG, "RSN: AES-WRAP using KEK",
2317 ptk->kek, ptk->kek_len);
2318 if (aes_wrap(ptk->kek, ptk->kek_len, plain_len / 8, plain,
2319 key_mic + mic_len + 2)) {
2320 os_free(plain);
2321 os_free(rbuf);
2322 return -1;
2323 }
2324 wpa_hexdump(MSG_DEBUG,
2325 "RSN: Encrypted Key Data from AES-WRAP",
2326 key_mic + mic_len + 2, plain_len + 8);
2327 os_free(plain);
2328 }
2329#endif /* CONFIG_TESTING_OPTIONS */
2330
Roshan Pius5e7db942018-04-12 12:27:41 -07002331 wpa_dbg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Sending EAPOL-Key 4/4");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002332 return wpa_eapol_key_send(sm, ptk, ver, dst, ETH_P_EAPOL, rbuf, rlen,
2333 key_mic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002334}
2335
2336
Sunil Ravi77d572f2023-01-17 23:58:31 +00002337static int wpa_supplicant_validate_link_kde(struct wpa_sm *sm, u8 link_id,
2338 const u8 *link_kde,
2339 size_t link_kde_len)
2340{
2341 size_t rsne_len = 0, rsnxe_len = 0;
2342 const u8 *rsne = NULL, *rsnxe = NULL;
2343
2344 if (!link_kde ||
2345 link_kde_len < RSN_MLO_LINK_KDE_LINK_MAC_INDEX + ETH_ALEN) {
2346 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2347 "RSN: MLO Link KDE is not found for link ID %d",
2348 link_id);
2349 return -1;
2350 }
2351
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002352 if (!ether_addr_equal(sm->mlo.links[link_id].bssid,
2353 &link_kde[RSN_MLO_LINK_KDE_LINK_MAC_INDEX])) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002354 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2355 "RSN: MLO Link %u MAC address (" MACSTR
2356 ") not matching association response (" MACSTR ")",
2357 link_id,
2358 MAC2STR(&link_kde[RSN_MLO_LINK_KDE_LINK_MAC_INDEX]),
2359 MAC2STR(sm->mlo.links[link_id].bssid));
2360 return -1;
2361 }
2362
2363 if (link_kde[0] & RSN_MLO_LINK_KDE_LI_RSNE_INFO) {
2364 rsne = link_kde + RSN_MLO_LINK_KDE_FIXED_LENGTH;
2365 if (link_kde_len < RSN_MLO_LINK_KDE_FIXED_LENGTH + 2 ||
2366 link_kde_len <
2367 (size_t) (RSN_MLO_LINK_KDE_FIXED_LENGTH + 2 + rsne[1])) {
2368 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2369 "RSN: No room for link %u RSNE in MLO Link KDE",
2370 link_id);
2371 return -1;
2372 }
2373
2374 rsne_len = rsne[1] + 2;
2375 }
2376
2377 if (!rsne) {
2378 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2379 "RSN: RSNE not present in MLO Link %u KDE", link_id);
2380 return -1;
2381 }
2382
2383 if (link_kde[0] & RSN_MLO_LINK_KDE_LI_RSNXE_INFO) {
2384 rsnxe = link_kde + RSN_MLO_LINK_KDE_FIXED_LENGTH + rsne_len;
2385 if (link_kde_len <
2386 (RSN_MLO_LINK_KDE_FIXED_LENGTH + rsne_len + 2) ||
2387 link_kde_len <
2388 (RSN_MLO_LINK_KDE_FIXED_LENGTH + rsne_len + 2 + rsnxe[1])) {
2389 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2390 "RSN: No room for link %u RSNXE in MLO Link KDE",
2391 link_id);
2392 return -1;
2393 }
2394
2395 rsnxe_len = rsnxe[1] + 2;
2396 }
2397
2398 if (wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
2399 sm->mlo.links[link_id].ap_rsne,
2400 sm->mlo.links[link_id].ap_rsne_len,
2401 rsne, rsne_len)) {
2402 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2403 "RSN MLO: IE in 3/4 msg does not match with IE in Beacon/ProbeResp for link ID %u",
2404 link_id);
2405 wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp",
2406 sm->mlo.links[link_id].ap_rsne,
2407 sm->mlo.links[link_id].ap_rsne_len);
2408 wpa_hexdump(MSG_INFO, "RSNE in EAPOL-Key msg 3/4",
2409 rsne, rsne_len);
2410 return -1;
2411 }
2412
2413 if ((sm->mlo.links[link_id].ap_rsnxe && !rsnxe) ||
2414 (!sm->mlo.links[link_id].ap_rsnxe && rsnxe) ||
2415 (sm->mlo.links[link_id].ap_rsnxe && rsnxe &&
2416 (sm->mlo.links[link_id].ap_rsnxe_len != rsnxe_len ||
2417 os_memcmp(sm->mlo.links[link_id].ap_rsnxe, rsnxe,
2418 sm->mlo.links[link_id].ap_rsnxe_len) != 0))) {
2419 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2420 "RSN MLO: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4 for link ID %u",
2421 link_id);
2422 wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp",
2423 sm->mlo.links[link_id].ap_rsnxe,
2424 sm->mlo.links[link_id].ap_rsnxe_len);
2425 wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4",
2426 rsnxe, rsnxe_len);
2427 wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS);
2428 return -1;
2429 }
2430
2431 return 0;
2432}
2433
2434
2435static int wpa_validate_mlo_ieee80211w_kdes(struct wpa_sm *sm,
2436 u8 link_id,
2437 struct wpa_eapol_ie_parse *ie)
2438{
2439 if (ie->mlo_igtk[link_id] &&
2440 ie->mlo_igtk_len[link_id] != RSN_MLO_IGTK_KDE_PREFIX_LENGTH +
2441 (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
2442 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2443 "RSN MLO: Invalid IGTK KDE length %lu for link ID %u",
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002444 (unsigned long) ie->mlo_igtk_len[link_id], link_id);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002445 return -1;
2446 }
2447
2448 if (!sm->beacon_prot)
2449 return 0;
2450
2451 if (ie->mlo_bigtk[link_id] &&
2452 ie->mlo_bigtk_len[link_id] != RSN_MLO_BIGTK_KDE_PREFIX_LENGTH +
2453 (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
2454 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2455 "RSN MLO: Invalid BIGTK KDE length %lu for link ID %u",
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002456 (unsigned long) ie->mlo_bigtk_len[link_id], link_id);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002457 return -1;
2458 }
2459
2460 return 0;
2461}
2462
2463
2464static void wpa_supplicant_process_3_of_4_wpa(struct wpa_sm *sm,
2465 const struct wpa_eapol_key *key,
2466 u16 ver, const u8 *key_data,
2467 size_t key_data_len)
2468{
2469 u16 key_info, keylen;
2470 struct wpa_eapol_ie_parse ie;
2471
2472 wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
2473 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2474 "WPA: RX message 3 of 4-Way Handshake from " MACSTR
2475 " (ver=%d)", MAC2STR(sm->bssid), ver);
2476
2477 key_info = WPA_GET_BE16(key->key_info);
2478
2479 wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len);
2480 if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
2481 goto failed;
2482
2483 if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
2484 goto failed;
2485
2486 if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
2487 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2488 "WPA: ANonce from message 1 of 4-Way Handshake differs from 3 of 4-Way Handshake - drop packet (src="
2489 MACSTR ")", MAC2STR(sm->bssid));
2490 goto failed;
2491 }
2492
2493 keylen = WPA_GET_BE16(key->key_length);
2494 if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) {
2495 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2496 "WPA: Invalid %s key length %d (src=" MACSTR ")",
2497 wpa_cipher_txt(sm->pairwise_cipher), keylen,
2498 MAC2STR(sm->bssid));
2499 goto failed;
2500 }
2501
2502 if (wpa_supplicant_send_4_of_4(sm, wpa_sm_get_auth_addr(sm), key, ver,
2503 key_info, &sm->ptk) < 0)
2504 goto failed;
2505
2506 /* SNonce was successfully used in msg 3/4, so mark it to be renewed
2507 * for the next 4-Way Handshake. If msg 3 is received again, the old
2508 * SNonce will still be used to avoid changing PTK. */
2509 sm->renew_snonce = 1;
2510
2511 if ((key_info & WPA_KEY_INFO_INSTALL) &&
2512 wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX_TX))
2513 goto failed;
2514
2515 if (key_info & WPA_KEY_INFO_SECURE) {
2516 wpa_sm_mlme_setprotection(
2517 sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
2518 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
2519 eapol_sm_notify_portValid(sm->eapol, true);
2520 }
2521 wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
2522
2523 sm->msg_3_of_4_ok = 1;
2524 return;
2525
2526failed:
2527 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
2528}
2529
2530
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
2532 const struct wpa_eapol_key *key,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002533 u16 ver, const u8 *key_data,
2534 size_t key_data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002535{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002536 u16 key_info, keylen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537 struct wpa_eapol_ie_parse ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002538 bool mlo = sm->mlo.valid_links;
2539 int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002540
2541 wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE);
Sunil Ravi77d572f2023-01-17 23:58:31 +00002542 wpa_dbg(sm->ctx->msg_ctx, MSG_INFO,
2543 "RSN: RX message 3 of 4-Way Handshake from " MACSTR
2544 " (ver=%d)%s", MAC2STR(sm->bssid), ver, mlo ? " (MLO)" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002545
2546 key_info = WPA_GET_BE16(key->key_info);
2547
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002548 wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len);
2549 if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002550 goto failed;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002551
2552 if (mlo && !ie.valid_mlo_gtks) {
2553 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2554 "MLO RSN: No GTK KDE included in EAPOL-Key msg 3/4");
2555 goto failed;
2556 }
2557 if (mlo &&
2558 (key_info &
2559 (WPA_KEY_INFO_ENCR_KEY_DATA | WPA_KEY_INFO_INSTALL |
2560 WPA_KEY_INFO_SECURE)) !=
2561 (WPA_KEY_INFO_ENCR_KEY_DATA | WPA_KEY_INFO_INSTALL |
2562 WPA_KEY_INFO_SECURE)) {
2563 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2564 "RSN MLO: Invalid key info (0x%x) in EAPOL-Key msg 3/4",
2565 key_info);
2566 goto failed;
2567 }
2568
2569 if (mlo && !is_valid_ap_mld_mac_kde(sm, ie.mac_addr)) {
2570 wpa_printf(MSG_DEBUG, "RSN: Invalid AP MLD MAC address KDE");
2571 goto failed;
2572 }
2573
2574 for (i = 0; mlo && i < MAX_NUM_MLD_LINKS; i++) {
2575 if (!(sm->mlo.req_links & BIT(i)))
2576 continue;
2577
2578 if (wpa_supplicant_validate_link_kde(sm, i, ie.mlo_link[i],
2579 ie.mlo_link_len[i]) < 0)
2580 goto failed;
2581
2582 if (!(sm->mlo.valid_links & BIT(i)))
2583 continue;
2584
2585 if (!ie.mlo_gtk[i]) {
2586 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
2587 "RSN: GTK not found for link ID %u", i);
2588 goto failed;
2589 }
2590
2591 if (sm->mgmt_group_cipher != WPA_CIPHER_GTK_NOT_USED &&
2592 wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) &&
2593 wpa_validate_mlo_ieee80211w_kdes(sm, i, &ie) < 0)
2594 goto failed;
2595 }
2596
2597#ifdef CONFIG_IEEE80211R
2598 if (mlo && wpa_key_mgmt_ft(sm->key_mgmt) &&
2599 wpa_supplicant_validate_ie_ft(sm, sm->bssid, &ie) < 0)
2600 goto failed;
2601#endif /* CONFIG_IEEE80211R */
2602
2603 if (!mlo && ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2605 "WPA: GTK IE in unencrypted key data");
2606 goto failed;
2607 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00002608 if (!mlo && ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2610 "WPA: IGTK KDE in unencrypted key data");
2611 goto failed;
2612 }
2613
Sunil Ravi77d572f2023-01-17 23:58:31 +00002614 if (!mlo && ie.igtk &&
Hai Shalom60840252021-02-19 19:02:11 -08002615 sm->mgmt_group_cipher != WPA_CIPHER_GTK_NOT_USED &&
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002616 wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) &&
2617 ie.igtk_len != WPA_IGTK_KDE_PREFIX_LEN +
2618 (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002619 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2620 "WPA: Invalid IGTK KDE length %lu",
2621 (unsigned long) ie.igtk_len);
2622 goto failed;
2623 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624
Sunil Ravi77d572f2023-01-17 23:58:31 +00002625 if (!mlo && wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626 goto failed;
2627
Hai Shalomfdcde762020-04-02 11:19:20 -07002628 if (wpa_handle_ext_key_id(sm, &ie))
2629 goto failed;
2630
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631 if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
2632 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2633 "WPA: ANonce from message 1 of 4-Way Handshake "
2634 "differs from 3 of 4-Way Handshake - drop packet (src="
2635 MACSTR ")", MAC2STR(sm->bssid));
2636 goto failed;
2637 }
2638
2639 keylen = WPA_GET_BE16(key->key_length);
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07002640 if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) {
2641 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2642 "WPA: Invalid %s key length %d (src=" MACSTR
2643 ")", wpa_cipher_txt(sm->pairwise_cipher), keylen,
2644 MAC2STR(sm->bssid));
2645 goto failed;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 }
2647
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08002648#ifdef CONFIG_P2P
2649 if (ie.ip_addr_alloc) {
2650 os_memcpy(sm->p2p_ip_addr, ie.ip_addr_alloc, 3 * 4);
2651 wpa_hexdump(MSG_DEBUG, "P2P: IP address info",
2652 sm->p2p_ip_addr, sizeof(sm->p2p_ip_addr));
2653 }
2654#endif /* CONFIG_P2P */
2655
Hai Shalom74f70d42019-02-11 14:42:39 -08002656#ifdef CONFIG_OCV
2657 if (wpa_sm_ocv_enabled(sm)) {
2658 struct wpa_channel_info ci;
2659
2660 if (wpa_sm_channel_info(sm, &ci) != 0) {
2661 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2662 "Failed to get channel info to validate received OCI in EAPOL-Key 3/4");
2663 return;
2664 }
2665
2666 if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
2667 channel_width_to_int(ci.chanwidth),
Hai Shalom899fcc72020-10-19 14:38:18 -07002668 ci.seg1_idx) != OCI_SUCCESS) {
2669 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE
2670 "addr=" MACSTR " frame=eapol-key-m3 error=%s",
2671 MAC2STR(sm->bssid), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08002672 return;
2673 }
2674 }
2675#endif /* CONFIG_OCV */
2676
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002677#ifdef CONFIG_DPP2
2678 if (DPP_VERSION > 1 && ie.dpp_kde) {
2679 wpa_printf(MSG_DEBUG,
2680 "DPP: peer Protocol Version %u Flags 0x%x",
2681 ie.dpp_kde[0], ie.dpp_kde[1]);
2682 if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_pfs != 2 &&
2683 (ie.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) && !sm->dpp_z) {
2684 wpa_printf(MSG_INFO,
2685 "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association");
2686 goto failed;
2687 }
2688 }
2689#endif /* CONFIG_DPP2 */
2690
Hai Shalomfdcde762020-04-02 11:19:20 -07002691 if (sm->use_ext_key_id &&
2692 wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX))
2693 goto failed;
2694
Sunil Ravi77d572f2023-01-17 23:58:31 +00002695 if (wpa_supplicant_send_4_of_4(sm, wpa_sm_get_auth_addr(sm), key, ver,
2696 key_info, &sm->ptk) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002697 goto failed;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698
2699 /* SNonce was successfully used in msg 3/4, so mark it to be renewed
2700 * for the next 4-Way Handshake. If msg 3 is received again, the old
2701 * SNonce will still be used to avoid changing PTK. */
2702 sm->renew_snonce = 1;
2703
2704 if (key_info & WPA_KEY_INFO_INSTALL) {
Hai Shalomfdcde762020-04-02 11:19:20 -07002705 int res;
2706
2707 if (sm->use_ext_key_id)
2708 res = wpa_supplicant_activate_ptk(sm);
2709 else
2710 res = wpa_supplicant_install_ptk(sm, key,
2711 KEY_FLAG_RX_TX);
2712 if (res)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 goto failed;
2714 }
2715
2716 if (key_info & WPA_KEY_INFO_SECURE) {
2717 wpa_sm_mlme_setprotection(
2718 sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX,
2719 MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
Hai Shalome21d4e82020-04-29 16:34:06 -07002720 eapol_sm_notify_portValid(sm->eapol, true);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002721 }
2722 wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
2723
Sunil Ravi77d572f2023-01-17 23:58:31 +00002724 if (mlo) {
2725 if (wpa_supplicant_pairwise_mlo_gtk(sm, key, &ie,
2726 key_info) < 0) {
2727 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2728 "MLO RSN: Failed to configure MLO GTKs");
2729 goto failed;
2730 }
2731 } else if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) {
Hai Shalom5f92bc92019-04-18 11:54:11 -07002732 /* No GTK to be set to the driver */
2733 } else if (!ie.gtk && sm->proto == WPA_PROTO_RSN) {
2734 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2735 "RSN: No GTK KDE included in EAPOL-Key msg 3/4");
2736 goto failed;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002737 } else if (ie.gtk &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738 wpa_supplicant_pairwise_gtk(sm, key,
2739 ie.gtk, ie.gtk_len, key_info) < 0) {
2740 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2741 "RSN: Failed to configure GTK");
2742 goto failed;
2743 }
2744
Sunil Ravi77d572f2023-01-17 23:58:31 +00002745 if ((mlo && mlo_ieee80211w_set_keys(sm, &ie) < 0) ||
2746 (!mlo && ieee80211w_set_keys(sm, &ie) < 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002747 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2748 "RSN: Failed to configure IGTK");
2749 goto failed;
2750 }
2751
Sunil Ravi77d572f2023-01-17 23:58:31 +00002752 if (mlo || sm->group_cipher == WPA_CIPHER_GTK_NOT_USED || ie.gtk)
Hai Shalom5f92bc92019-04-18 11:54:11 -07002753 wpa_supplicant_key_neg_complete(sm, sm->bssid,
2754 key_info & WPA_KEY_INFO_SECURE);
2755
Sunil Ravi77d572f2023-01-17 23:58:31 +00002756 if (mlo || ie.gtk)
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002757 wpa_sm_set_rekey_offload(sm);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002758
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002759 /* Add PMKSA cache entry for Suite B AKMs here since PMKID can be
2760 * calculated only after KCK has been derived. Though, do not replace an
2761 * existing PMKSA entry after each 4-way handshake (i.e., new KCK/PMKID)
2762 * to avoid unnecessary changes of PMKID while continuing to use the
2763 * same PMK. */
2764 if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt) &&
2765 !sm->cur_pmksa) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002766 struct rsn_pmksa_cache_entry *sa;
2767
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002768 sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, NULL,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002769 sm->ptk.kck, sm->ptk.kck_len,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002770 wpa_sm_get_auth_addr(sm), sm->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002771 sm->network_ctx, sm->key_mgmt, NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002772 if (!sm->cur_pmksa)
2773 sm->cur_pmksa = sa;
2774 }
2775
Hai Shalomfdcde762020-04-02 11:19:20 -07002776 if (ie.transition_disable)
2777 wpa_sm_transition_disable(sm, ie.transition_disable[0]);
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07002778 sm->msg_3_of_4_ok = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002779 return;
2780
2781failed:
2782 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
2783}
2784
2785
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm,
2787 const struct wpa_eapol_key *key,
2788 int ver, u16 key_info)
2789{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002790 size_t mic_len, hdrlen, rlen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002791 struct wpa_eapol_key *reply;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002792 u8 *rbuf, *key_mic;
Hai Shalom74f70d42019-02-11 14:42:39 -08002793 size_t kde_len = 0;
2794
Sunil Ravia04bd252022-05-02 22:54:18 -07002795#ifdef CONFIG_TESTING_OPTIONS
2796 if (sm->disable_eapol_g2_tx) {
2797 wpa_printf(MSG_INFO, "TEST: Disable sending EAPOL-Key 2/2");
2798 return 0;
2799 }
2800#endif /* CONFIG_TESTING_OPTIONS */
2801
Hai Shalom74f70d42019-02-11 14:42:39 -08002802#ifdef CONFIG_OCV
2803 if (wpa_sm_ocv_enabled(sm))
2804 kde_len = OCV_OCI_KDE_LEN;
2805#endif /* CONFIG_OCV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002807 mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002808 hdrlen = sizeof(*reply) + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002809 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
Hai Shalom74f70d42019-02-11 14:42:39 -08002810 hdrlen + kde_len, &rlen, (void *) &reply);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002811 if (rbuf == NULL)
2812 return -1;
2813
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002814 reply->type = (sm->proto == WPA_PROTO_RSN ||
2815 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002816 EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA;
2817 key_info &= WPA_KEY_INFO_KEY_INDEX_MASK;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002818 key_info |= ver | WPA_KEY_INFO_SECURE;
2819 if (mic_len)
2820 key_info |= WPA_KEY_INFO_MIC;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002821 else
2822 key_info |= WPA_KEY_INFO_ENCR_KEY_DATA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002823 WPA_PUT_BE16(reply->key_info, key_info);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002824 if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002825 WPA_PUT_BE16(reply->key_length, 0);
2826 else
2827 os_memcpy(reply->key_length, key->key_length, 2);
2828 os_memcpy(reply->replay_counter, key->replay_counter,
2829 WPA_REPLAY_COUNTER_LEN);
2830
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002831 key_mic = (u8 *) (reply + 1);
Hai Shalom74f70d42019-02-11 14:42:39 -08002832 WPA_PUT_BE16(key_mic + mic_len, kde_len); /* Key Data Length */
2833
2834#ifdef CONFIG_OCV
2835 if (wpa_sm_ocv_enabled(sm)) {
2836 struct wpa_channel_info ci;
2837 u8 *pos;
2838
2839 if (wpa_sm_channel_info(sm, &ci) != 0) {
2840 wpa_printf(MSG_WARNING,
2841 "Failed to get channel info for OCI element in EAPOL-Key 2/2");
2842 os_free(rbuf);
2843 return -1;
2844 }
Hai Shalom899fcc72020-10-19 14:38:18 -07002845#ifdef CONFIG_TESTING_OPTIONS
2846 if (sm->oci_freq_override_eapol_g2) {
2847 wpa_printf(MSG_INFO,
2848 "TEST: Override OCI KDE frequency %d -> %d MHz",
2849 ci.frequency,
2850 sm->oci_freq_override_eapol_g2);
2851 ci.frequency = sm->oci_freq_override_eapol_g2;
2852 }
2853#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08002854
2855 pos = key_mic + mic_len + 2; /* Key Data */
2856 if (ocv_insert_oci_kde(&ci, &pos) < 0) {
2857 os_free(rbuf);
2858 return -1;
2859 }
2860 }
2861#endif /* CONFIG_OCV */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002862
2863 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2");
Sunil Ravi2a14cf12023-11-21 00:54:38 +00002864 return wpa_eapol_key_send(sm, &sm->ptk, ver, wpa_sm_get_auth_addr(sm),
2865 ETH_P_EAPOL, rbuf, rlen, key_mic);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002866}
2867
2868
Sunil Ravi77d572f2023-01-17 23:58:31 +00002869static void wpa_supplicant_process_mlo_1_of_2(struct wpa_sm *sm,
2870 const unsigned char *src_addr,
2871 const struct wpa_eapol_key *key,
2872 const u8 *key_data,
2873 size_t key_data_len, u16 ver)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002874{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002875 u16 key_info;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002876 u8 i;
2877 struct wpa_eapol_ie_parse ie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002878
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002879 if (!sm->msg_3_of_4_ok && !wpa_fils_is_completed(sm)) {
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07002880 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002881 "MLO RSN: Group Key Handshake started prior to completion of 4-way handshake");
2882 goto failed;
2883 }
2884
2885 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "MLO RSN: RX message 1 of Group "
2886 "Key Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr),
2887 ver);
2888
2889 key_info = WPA_GET_BE16(key->key_info);
2890
2891 wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
2892
2893 wpa_hexdump_key(MSG_DEBUG, "MLO RSN: msg 1/2 key data", key_data,
2894 key_data_len);
2895 if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
2896 goto failed;
2897
2898 if (!ie.valid_mlo_gtks) {
2899 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2900 "MLO RSN: No MLO GTK KDE in Group Key msg 1/2");
2901 goto failed;
2902 }
2903
2904 if (!(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
2905 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2906 "MLO RSN: MLO GTK KDE in unencrypted key data");
2907 goto failed;
2908 }
2909
2910#ifdef CONFIG_OCV
2911 if (wpa_sm_ocv_enabled(sm)) {
2912 struct wpa_channel_info ci;
2913
2914 if (wpa_sm_channel_info(sm, &ci) != 0) {
2915 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
2916 "Failed to get channel info to validate received OCI in EAPOL-Key group msg 1/2");
2917 goto failed;
2918 }
2919
2920 if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
2921 channel_width_to_int(ci.chanwidth),
2922 ci.seg1_idx) != OCI_SUCCESS) {
2923 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE
2924 "addr=" MACSTR " frame=eapol-key-g1 error=%s",
2925 MAC2STR(sm->bssid), ocv_errorstr);
2926 goto failed;
2927 }
2928 }
2929#endif /* CONFIG_OCV */
2930
2931 if (mlo_ieee80211w_set_keys(sm, &ie) < 0)
2932 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
2933 "MLO RSN: Failed to configure MLO IGTK");
2934
Sunil Ravi88611412024-06-28 17:34:56 +00002935 for (i = 0; i < MAX_NUM_MLO_LINKS; i++) {
2936 if (!(sm->mlo.valid_links & BIT(i)))
2937 continue;
2938
Sunil Ravi77d572f2023-01-17 23:58:31 +00002939 /*
2940 * AP may send group keys for subset of the all links during
2941 * rekey
2942 */
2943 if (!ie.mlo_gtk[i])
2944 continue;
2945
2946 if (wpa_supplicant_mlo_gtk(sm, i, ie.mlo_gtk[i],
2947 ie.mlo_gtk_len[i], key_info))
2948 goto failed;
2949 }
2950
2951 if (wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
2952 goto failed;
2953
2954 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "MLO RSN: Group rekeying completed "
2955 "with " MACSTR " [GTK=%s]", MAC2STR(sm->mlo.ap_mld_addr),
2956 wpa_cipher_txt(sm->group_cipher));
2957 wpa_sm_cancel_auth_timeout(sm);
2958 wpa_sm_set_state(sm, WPA_COMPLETED);
2959
2960 wpa_sm_set_rekey_offload(sm);
2961
2962 return;
2963
2964failed:
2965 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
2966}
2967
2968
2969static void wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm,
2970 const unsigned char *src_addr,
2971 const struct wpa_eapol_key *key,
2972 const u8 *key_data,
2973 size_t key_data_len, u16 ver)
2974{
2975 u16 key_info;
2976 int rekey;
2977 struct wpa_gtk_data gd;
2978 const u8 *key_rsc;
2979 size_t maxkeylen;
2980 u16 gtk_len;
2981
2982 if (!sm->msg_3_of_4_ok) {
2983 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07002984 "WPA: Group Key Handshake started prior to completion of 4-way handshake");
2985 goto failed;
2986 }
2987
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002988 os_memset(&gd, 0, sizeof(gd));
2989
2990 rekey = wpa_sm_get_state(sm) == WPA_COMPLETED;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002991 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
2992 "WPA: RX message 1 of Group Key Handshake from " MACSTR
2993 " (ver=%d)", MAC2STR(src_addr), ver);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002994
2995 key_info = WPA_GET_BE16(key->key_info);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002996
Sunil Ravi77d572f2023-01-17 23:58:31 +00002997 gtk_len = WPA_GET_BE16(key->key_length);
2998 maxkeylen = key_data_len;
2999 if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
3000 if (maxkeylen < 8) {
3001 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3002 "WPA: Too short maxkeylen (%lu)",
3003 (unsigned long) maxkeylen);
3004 goto failed;
3005 }
3006 maxkeylen -= 8;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007 }
3008
Sunil Ravi77d572f2023-01-17 23:58:31 +00003009 if (gtk_len > maxkeylen ||
3010 wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
3011 gtk_len, maxkeylen,
3012 &gd.key_rsc_len, &gd.alg))
3013 goto failed;
3014
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003015 wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
3016
Sunil Ravi77d572f2023-01-17 23:58:31 +00003017 gd.gtk_len = gtk_len;
3018 gd.keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
3019 WPA_KEY_INFO_KEY_INDEX_SHIFT;
3020 if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) {
3021#if defined(CONFIG_NO_RC4) || defined(CONFIG_FIPS)
3022 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3023 "WPA: RC4 not supported in the build");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003024 goto failed;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003025#else /* CONFIG_NO_RC4 || CONFIG_FIPS */
3026 u8 ek[32];
3027 if (key_data_len > sizeof(gd.gtk)) {
3028 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3029 "WPA: RC4 key data too long (%lu)",
3030 (unsigned long) key_data_len);
3031 goto failed;
3032 }
3033 os_memcpy(ek, key->key_iv, 16);
3034 os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
3035 os_memcpy(gd.gtk, key_data, key_data_len);
3036 if (rc4_skip(ek, 32, 256, gd.gtk, key_data_len)) {
3037 forced_memzero(ek, sizeof(ek));
3038 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
3039 "WPA: RC4 failed");
3040 goto failed;
3041 }
3042 forced_memzero(ek, sizeof(ek));
3043#endif /* CONFIG_NO_RC4 || CONFIG_FIPS */
3044 } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
3045 if (maxkeylen % 8) {
3046 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3047 "WPA: Unsupported AES-WRAP len %lu",
3048 (unsigned long) maxkeylen);
3049 goto failed;
3050 }
3051 if (maxkeylen > sizeof(gd.gtk)) {
3052 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3053 "WPA: AES-WRAP key data "
3054 "too long (keydatalen=%lu maxkeylen=%lu)",
3055 (unsigned long) key_data_len,
3056 (unsigned long) maxkeylen);
3057 goto failed;
3058 }
3059 if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, maxkeylen / 8,
3060 key_data, gd.gtk)) {
3061 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3062 "WPA: AES unwrap failed - could not decrypt "
3063 "GTK");
3064 goto failed;
3065 }
3066 } else {
3067 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3068 "WPA: Unsupported key_info type %d", ver);
3069 goto failed;
3070 }
3071 gd.tx = wpa_supplicant_gtk_tx_bit_workaround(
3072 sm, !!(key_info & WPA_KEY_INFO_TXRX));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003073
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003074 key_rsc = key->key_rsc;
3075 if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
3076 key_rsc = null_rsc;
3077
Jouni Malinen58c0e962017-10-01 12:12:24 +03003078 if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003079 wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003080 goto failed;
Hai Shalom81f62d82019-07-22 12:10:00 -07003081 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003082
3083 if (rekey) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00003084 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3085 "WPA: Group rekeying completed with " MACSTR
3086 " [GTK=%s]",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003087 MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
3088 wpa_sm_cancel_auth_timeout(sm);
3089 wpa_sm_set_state(sm, WPA_COMPLETED);
3090 } else {
3091 wpa_supplicant_key_neg_complete(sm, sm->bssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003092 key_info & WPA_KEY_INFO_SECURE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003093 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003094
3095 wpa_sm_set_rekey_offload(sm);
3096
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003097 return;
3098
3099failed:
Hai Shalom81f62d82019-07-22 12:10:00 -07003100 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003101 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
3102}
3103
3104
Sunil Ravi77d572f2023-01-17 23:58:31 +00003105static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
3106 const unsigned char *src_addr,
3107 const struct wpa_eapol_key *key,
3108 const u8 *key_data,
3109 size_t key_data_len, u16 ver)
3110{
3111 u16 key_info;
3112 struct wpa_gtk_data gd;
3113 const u8 *key_rsc;
3114 int maxkeylen;
3115 struct wpa_eapol_ie_parse ie;
3116 u16 gtk_len;
3117
3118 if (!sm->msg_3_of_4_ok && !wpa_fils_is_completed(sm)) {
3119 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3120 "RSN: Group Key Handshake started prior to completion of 4-way handshake");
3121 goto failed;
3122 }
3123
3124 os_memset(&gd, 0, sizeof(gd));
3125
3126 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3127 "RSN: RX message 1 of Group Key Handshake from " MACSTR
3128 " (ver=%d)", MAC2STR(src_addr), ver);
3129
3130 key_info = WPA_GET_BE16(key->key_info);
3131
3132 wpa_hexdump_key(MSG_DEBUG, "RSN: msg 1/2 key data",
3133 key_data, key_data_len);
3134 if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0)
3135 goto failed;
3136
3137 wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE);
3138
3139 if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
3140 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3141 "RSN: GTK KDE in unencrypted key data");
3142 goto failed;
3143 }
3144 if (!ie.gtk) {
3145 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3146 "RSN: No GTK KDE in Group Key msg 1/2");
3147 goto failed;
3148 }
3149 gtk_len = ie.gtk_len;
3150 if (gtk_len < 2) {
3151 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3152 "RSN: Invalid GTK KDE length (%u) in Group Key msg 1/2",
3153 gtk_len);
3154 goto failed;
3155 }
3156 gtk_len -= 2;
3157 if (gtk_len > sizeof(gd.gtk)) {
3158 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3159 "RSN: Too long GTK in GTK KDE (len=%u)", gtk_len);
3160 goto failed;
3161 }
3162 maxkeylen = gd.gtk_len = gtk_len;
3163
3164#ifdef CONFIG_OCV
3165 if (wpa_sm_ocv_enabled(sm)) {
3166 struct wpa_channel_info ci;
3167
3168 if (wpa_sm_channel_info(sm, &ci) != 0) {
3169 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3170 "Failed to get channel info to validate received OCI in EAPOL-Key group msg 1/2");
3171 goto failed;
3172 }
3173
3174 if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci,
3175 channel_width_to_int(ci.chanwidth),
3176 ci.seg1_idx) != OCI_SUCCESS) {
3177 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE
3178 "addr=" MACSTR " frame=eapol-key-g1 error=%s",
3179 MAC2STR(sm->bssid), ocv_errorstr);
3180 goto failed;
3181 }
3182 }
3183#endif /* CONFIG_OCV */
3184
3185 if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
3186 gtk_len, maxkeylen,
3187 &gd.key_rsc_len, &gd.alg))
3188 goto failed;
3189
3190 wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in group key handshake",
3191 ie.gtk, 2 + gtk_len);
3192 gd.keyidx = ie.gtk[0] & 0x3;
3193 gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
3194 !!(ie.gtk[0] & BIT(2)));
3195 os_memcpy(gd.gtk, ie.gtk + 2, gtk_len);
3196
3197 if (ieee80211w_set_keys(sm, &ie) < 0)
3198 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3199 "RSN: Failed to configure IGTK");
3200
3201 key_rsc = key->key_rsc;
3202 if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc))
3203 key_rsc = null_rsc;
3204
3205 if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) ||
3206 wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0)
3207 goto failed;
3208 forced_memzero(&gd, sizeof(gd));
3209
3210 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3211 "RSN: Group rekeying completed with " MACSTR " [GTK=%s]",
3212 MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher));
3213 wpa_sm_cancel_auth_timeout(sm);
3214 wpa_sm_set_state(sm, WPA_COMPLETED);
3215
3216 wpa_sm_set_rekey_offload(sm);
3217
3218 return;
3219
3220failed:
3221 forced_memzero(&gd, sizeof(gd));
3222 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
3223}
3224
3225
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003226static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003227 struct wpa_eapol_key *key,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003228 u16 ver,
3229 const u8 *buf, size_t len)
3230{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003231 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003232 int ok = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003233 size_t mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003234
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003235 os_memcpy(mic, key + 1, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003236 if (sm->tptk_set) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003237 os_memset(key + 1, 0, mic_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003238 if (wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len,
3239 sm->key_mgmt,
3240 ver, buf, len, (u8 *) (key + 1)) < 0 ||
3241 os_memcmp_const(mic, key + 1, mic_len) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003242 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3243 "WPA: Invalid EAPOL-Key MIC "
3244 "when using TPTK - ignoring TPTK");
Hai Shalom74f70d42019-02-11 14:42:39 -08003245#ifdef TEST_FUZZ
3246 wpa_printf(MSG_INFO,
3247 "TEST: Ignore Key MIC failure for fuzz testing");
3248 goto continue_fuzz;
3249#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003250 } else {
Hai Shalom74f70d42019-02-11 14:42:39 -08003251#ifdef TEST_FUZZ
3252 continue_fuzz:
3253#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003254 ok = 1;
3255 sm->tptk_set = 0;
3256 sm->ptk_set = 1;
3257 os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
Dmitry Shmidt61593f02014-04-21 16:27:35 -07003258 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003259 /*
3260 * This assures the same TPTK in sm->tptk can never be
Roshan Pius3a1667e2018-07-03 15:17:14 -07003261 * copied twice to sm->ptk as the new PTK. In
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003262 * combination with the installed flag in the wpa_ptk
3263 * struct, this assures the same PTK is only installed
3264 * once.
3265 */
3266 sm->renew_snonce = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003267 }
3268 }
3269
3270 if (!ok && sm->ptk_set) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003271 os_memset(key + 1, 0, mic_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003272 if (wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len,
3273 sm->key_mgmt,
3274 ver, buf, len, (u8 *) (key + 1)) < 0 ||
3275 os_memcmp_const(mic, key + 1, mic_len) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003276 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3277 "WPA: Invalid EAPOL-Key MIC - "
3278 "dropping packet");
Hai Shalom74f70d42019-02-11 14:42:39 -08003279#ifdef TEST_FUZZ
3280 wpa_printf(MSG_INFO,
3281 "TEST: Ignore Key MIC failure for fuzz testing");
3282 goto continue_fuzz2;
3283#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003284 return -1;
3285 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003286#ifdef TEST_FUZZ
3287 continue_fuzz2:
3288#endif /* TEST_FUZZ */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003289 ok = 1;
3290 }
3291
3292 if (!ok) {
3293 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3294 "WPA: Could not verify EAPOL-Key MIC - "
3295 "dropping packet");
3296 return -1;
3297 }
3298
3299 os_memcpy(sm->rx_replay_counter, key->replay_counter,
3300 WPA_REPLAY_COUNTER_LEN);
3301 sm->rx_replay_counter_set = 1;
3302 return 0;
3303}
3304
3305
3306/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */
3307static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003308 struct wpa_eapol_key *key,
3309 size_t mic_len, u16 ver,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003310 u8 *key_data, size_t *key_data_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003312 wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003313 key_data, *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003314 if (!sm->ptk_set) {
3315 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3316 "WPA: PTK not available, cannot decrypt EAPOL-Key Key "
3317 "Data");
3318 return -1;
3319 }
3320
3321 /* Decrypt key data here so that this operation does not need
3322 * to be implemented separately for each message type. */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003323 if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00003324#if defined(CONFIG_NO_RC4) || defined(CONFIG_FIPS)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003325 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3326 "WPA: RC4 not supported in the build");
3327 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003328#else /* CONFIG_NO_RC4 || CONFIG_FIPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003329 u8 ek[32];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003330
3331 wpa_printf(MSG_DEBUG, "WPA: Decrypt Key Data using RC4");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003332 os_memcpy(ek, key->key_iv, 16);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003333 os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003334 if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) {
Hai Shalom81f62d82019-07-22 12:10:00 -07003335 forced_memzero(ek, sizeof(ek));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003336 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
3337 "WPA: RC4 failed");
3338 return -1;
3339 }
Hai Shalom81f62d82019-07-22 12:10:00 -07003340 forced_memzero(ek, sizeof(ek));
Sunil Ravi77d572f2023-01-17 23:58:31 +00003341#endif /* CONFIG_NO_RC4 || CONFIG_FIPS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342 } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES ||
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003343 ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
Roshan Pius3a1667e2018-07-03 15:17:14 -07003344 wpa_use_aes_key_wrap(sm->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003345 u8 *buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003346
3347 wpa_printf(MSG_DEBUG,
3348 "WPA: Decrypt Key Data using AES-UNWRAP (KEK length %u)",
3349 (unsigned int) sm->ptk.kek_len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003350 if (*key_data_len < 8 || *key_data_len % 8) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003351 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003352 "WPA: Unsupported AES-WRAP len %u",
3353 (unsigned int) *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003354 return -1;
3355 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003356 *key_data_len -= 8; /* AES-WRAP adds 8 bytes */
3357 buf = os_malloc(*key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003358 if (buf == NULL) {
3359 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3360 "WPA: No memory for AES-UNWRAP buffer");
3361 return -1;
3362 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003363#ifdef TEST_FUZZ
3364 os_memset(buf, 0x11, *key_data_len);
3365#endif /* TEST_FUZZ */
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003366 if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003367 key_data, buf)) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003368#ifdef TEST_FUZZ
3369 wpa_printf(MSG_INFO,
3370 "TEST: Ignore AES unwrap failure for fuzz testing");
3371 goto continue_fuzz;
3372#endif /* TEST_FUZZ */
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08003373 bin_clear_free(buf, *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003374 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3375 "WPA: AES unwrap failed - "
3376 "could not decrypt EAPOL-Key key data");
3377 return -1;
3378 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003379#ifdef TEST_FUZZ
3380 continue_fuzz:
3381#endif /* TEST_FUZZ */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003382 os_memcpy(key_data, buf, *key_data_len);
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08003383 bin_clear_free(buf, *key_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003384 WPA_PUT_BE16(((u8 *) (key + 1)) + mic_len, *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003385 } else {
3386 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3387 "WPA: Unsupported key_info type %d", ver);
3388 return -1;
3389 }
3390 wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data",
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003391 key_data, *key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003392 return 0;
3393}
3394
3395
3396/**
3397 * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted
3398 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3399 */
3400void wpa_sm_aborted_cached(struct wpa_sm *sm)
3401{
3402 if (sm && sm->cur_pmksa) {
3403 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3404 "RSN: Cancelling PMKSA caching attempt");
3405 sm->cur_pmksa = NULL;
3406 }
3407}
3408
3409
Hai Shalomc1a21442022-02-04 13:43:00 -08003410void wpa_sm_aborted_external_cached(struct wpa_sm *sm)
3411{
3412 if (sm && sm->cur_pmksa && sm->cur_pmksa->external) {
3413 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3414 "RSN: Cancelling external PMKSA caching attempt");
3415 sm->cur_pmksa = NULL;
3416 }
3417}
3418
3419
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003420static void wpa_eapol_key_dump(struct wpa_sm *sm,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003421 const struct wpa_eapol_key *key,
3422 unsigned int key_data_len,
3423 const u8 *mic, unsigned int mic_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003424{
3425#ifndef CONFIG_NO_STDOUT_DEBUG
3426 u16 key_info = WPA_GET_BE16(key->key_info);
3427
3428 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, " EAPOL-Key type=%d", key->type);
3429 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3430 " key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)",
3431 key_info, key_info & WPA_KEY_INFO_TYPE_MASK,
3432 (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >>
3433 WPA_KEY_INFO_KEY_INDEX_SHIFT,
3434 (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13,
3435 key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group",
3436 key_info & WPA_KEY_INFO_INSTALL ? " Install" : "",
3437 key_info & WPA_KEY_INFO_ACK ? " Ack" : "",
3438 key_info & WPA_KEY_INFO_MIC ? " MIC" : "",
3439 key_info & WPA_KEY_INFO_SECURE ? " Secure" : "",
3440 key_info & WPA_KEY_INFO_ERROR ? " Error" : "",
3441 key_info & WPA_KEY_INFO_REQUEST ? " Request" : "",
3442 key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : "");
3443 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3444 " key_length=%u key_data_length=%u",
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003445 WPA_GET_BE16(key->key_length), key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003446 wpa_hexdump(MSG_DEBUG, " replay_counter",
3447 key->replay_counter, WPA_REPLAY_COUNTER_LEN);
3448 wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN);
3449 wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16);
3450 wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8);
3451 wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003452 wpa_hexdump(MSG_DEBUG, " key_mic", mic, mic_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003453#endif /* CONFIG_NO_STDOUT_DEBUG */
3454}
3455
3456
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003457#ifdef CONFIG_FILS
3458static int wpa_supp_aead_decrypt(struct wpa_sm *sm, u8 *buf, size_t buf_len,
3459 size_t *key_data_len)
3460{
3461 struct wpa_ptk *ptk;
3462 struct ieee802_1x_hdr *hdr;
3463 struct wpa_eapol_key *key;
3464 u8 *pos, *tmp;
3465 const u8 *aad[1];
3466 size_t aad_len[1];
3467
3468 if (*key_data_len < AES_BLOCK_SIZE) {
3469 wpa_printf(MSG_INFO, "No room for AES-SIV data in the frame");
3470 return -1;
3471 }
3472
3473 if (sm->tptk_set)
3474 ptk = &sm->tptk;
3475 else if (sm->ptk_set)
3476 ptk = &sm->ptk;
3477 else
3478 return -1;
3479
3480 hdr = (struct ieee802_1x_hdr *) buf;
3481 key = (struct wpa_eapol_key *) (hdr + 1);
3482 pos = (u8 *) (key + 1);
3483 pos += 2; /* Pointing at the Encrypted Key Data field */
3484
3485 tmp = os_malloc(*key_data_len);
3486 if (!tmp)
3487 return -1;
3488
3489 /* AES-SIV AAD from EAPOL protocol version field (inclusive) to
3490 * to Key Data (exclusive). */
3491 aad[0] = buf;
3492 aad_len[0] = pos - buf;
3493 if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, *key_data_len,
3494 1, aad, aad_len, tmp) < 0) {
3495 wpa_printf(MSG_INFO, "Invalid AES-SIV data in the frame");
3496 bin_clear_free(tmp, *key_data_len);
3497 return -1;
3498 }
3499
3500 /* AEAD decryption and validation completed successfully */
3501 (*key_data_len) -= AES_BLOCK_SIZE;
3502 wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data",
3503 tmp, *key_data_len);
3504
3505 /* Replace Key Data field with the decrypted version */
3506 os_memcpy(pos, tmp, *key_data_len);
3507 pos -= 2; /* Key Data Length field */
3508 WPA_PUT_BE16(pos, *key_data_len);
3509 bin_clear_free(tmp, *key_data_len);
3510
3511 if (sm->tptk_set) {
3512 sm->tptk_set = 0;
3513 sm->ptk_set = 1;
3514 os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk));
3515 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
3516 }
3517
3518 os_memcpy(sm->rx_replay_counter, key->replay_counter,
3519 WPA_REPLAY_COUNTER_LEN);
3520 sm->rx_replay_counter_set = 1;
3521
3522 return 0;
3523}
3524#endif /* CONFIG_FILS */
3525
3526
Sunil Ravi77d572f2023-01-17 23:58:31 +00003527static int wpa_sm_rx_eapol_wpa(struct wpa_sm *sm, const u8 *src_addr,
3528 struct wpa_eapol_key *key,
3529 enum frame_encryption encrypted,
3530 const u8 *tmp, size_t data_len,
3531 u8 *key_data, size_t key_data_len)
3532{
3533 u16 key_info, ver;
3534
3535 key_info = WPA_GET_BE16(key->key_info);
3536
3537 if (key->type != EAPOL_KEY_TYPE_WPA) {
3538 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3539 "WPA: Unsupported EAPOL-Key type %d", key->type);
3540 return -1;
3541 }
3542
3543 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
3544 if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
3545 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
3546 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3547 "WPA: Unsupported EAPOL-Key descriptor version %d",
3548 ver);
3549 return -1;
3550 }
3551
3552 if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
3553 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
3554 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3555 "WPA: CCMP is used, but EAPOL-Key descriptor version (%d) is not 2",
3556 ver);
3557 if (sm->group_cipher != WPA_CIPHER_CCMP &&
3558 !(key_info & WPA_KEY_INFO_KEY_TYPE)) {
3559 /* Earlier versions of IEEE 802.11i did not explicitly
3560 * require version 2 descriptor for all EAPOL-Key
3561 * packets, so allow group keys to use version 1 if
3562 * CCMP is not used for them. */
3563 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3564 "WPA: Backwards compatibility: allow invalid version for non-CCMP group keys");
3565 } else
3566 return -1;
3567 }
3568
3569 if ((key_info & WPA_KEY_INFO_MIC) &&
3570 wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
3571 return -1;
3572
3573 if (key_info & WPA_KEY_INFO_KEY_TYPE) {
3574 if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
3575 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3576 "WPA: Ignored EAPOL-Key (Pairwise) with non-zero key index");
3577 return -1;
3578 }
3579 if (key_info & (WPA_KEY_INFO_MIC |
3580 WPA_KEY_INFO_ENCR_KEY_DATA)) {
3581 /* 3/4 4-Way Handshake */
3582 wpa_supplicant_process_3_of_4_wpa(sm, key, ver,
3583 key_data,
3584 key_data_len);
3585 } else {
3586 /* 1/4 4-Way Handshake */
3587 wpa_supplicant_process_1_of_4_wpa(sm, src_addr, key,
3588 ver, key_data,
3589 key_data_len,
3590 encrypted);
3591 }
3592 } else {
3593 if (key_info & WPA_KEY_INFO_MIC) {
3594 /* 1/2 Group Key Handshake */
3595 wpa_supplicant_process_1_of_2_wpa(sm, src_addr, key,
3596 key_data,
3597 key_data_len,
3598 ver);
3599 } else {
3600 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3601 "WPA: EAPOL-Key (Group) without Mic/Encr bit - dropped");
3602 }
3603 }
3604
3605 return 1;
3606}
3607
3608
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003609/**
3610 * wpa_sm_rx_eapol - Process received WPA EAPOL frames
3611 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3612 * @src_addr: Source MAC address of the EAPOL packet
3613 * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
3614 * @len: Length of the EAPOL frame
Sunil8cd6f4d2022-06-28 18:40:46 +00003615 * @encrypted: Whether the frame was encrypted
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003616 * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure
3617 *
3618 * This function is called for each received EAPOL frame. Other than EAPOL-Key
3619 * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is
3620 * only processing WPA and WPA2 EAPOL-Key frames.
3621 *
3622 * The received EAPOL-Key packets are validated and valid packets are replied
3623 * to. In addition, key material (PTK, GTK) is configured at the end of a
3624 * successful key handshake.
3625 */
3626int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
Sunil8cd6f4d2022-06-28 18:40:46 +00003627 const u8 *buf, size_t len, enum frame_encryption encrypted)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003628{
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003629 size_t plen, data_len, key_data_len;
3630 const struct ieee802_1x_hdr *hdr;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003631 struct wpa_eapol_key *key;
3632 u16 key_info, ver;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003633 u8 *tmp = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003634 int ret = -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003635 u8 *mic, *key_data;
Hai Shalom899fcc72020-10-19 14:38:18 -07003636 size_t mic_len, keyhdrlen, pmk_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003637
3638#ifdef CONFIG_IEEE80211R
3639 sm->ft_completed = 0;
3640#endif /* CONFIG_IEEE80211R */
3641
Hai Shalom899fcc72020-10-19 14:38:18 -07003642 pmk_len = sm->pmk_len;
3643 if (!pmk_len && sm->cur_pmksa)
3644 pmk_len = sm->cur_pmksa->pmk_len;
3645 mic_len = wpa_mic_len(sm->key_mgmt, pmk_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003646 keyhdrlen = sizeof(*key) + mic_len + 2;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003647
3648 if (len < sizeof(*hdr) + keyhdrlen) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003649 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3650 "WPA: EAPOL frame too short to be a WPA "
3651 "EAPOL-Key (len %lu, expecting at least %lu)",
3652 (unsigned long) len,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003653 (unsigned long) sizeof(*hdr) + keyhdrlen);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003654 return 0;
3655 }
3656
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003657 hdr = (const struct ieee802_1x_hdr *) buf;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003658 plen = be_to_host16(hdr->length);
3659 data_len = plen + sizeof(*hdr);
3660 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3661 "IEEE 802.1X RX: version=%d type=%d length=%lu",
3662 hdr->version, hdr->type, (unsigned long) plen);
3663
3664 if (hdr->version < EAPOL_VERSION) {
3665 /* TODO: backwards compatibility */
3666 }
3667 if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) {
3668 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3669 "WPA: EAPOL frame (type %u) discarded, "
3670 "not a Key frame", hdr->type);
3671 ret = 0;
3672 goto out;
3673 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003674 wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003675 if (plen > len - sizeof(*hdr) || plen < keyhdrlen) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003676 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3677 "WPA: EAPOL frame payload size %lu "
3678 "invalid (frame size %lu)",
3679 (unsigned long) plen, (unsigned long) len);
3680 ret = 0;
3681 goto out;
3682 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003683 if (data_len < len) {
3684 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3685 "WPA: ignoring %lu bytes after the IEEE 802.1X data",
3686 (unsigned long) len - data_len);
3687 }
3688
3689 /*
3690 * Make a copy of the frame since we need to modify the buffer during
3691 * MAC validation and Key Data decryption.
3692 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003693 tmp = os_memdup(buf, data_len);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003694 if (tmp == NULL)
3695 goto out;
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003696 key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003697 mic = (u8 *) (key + 1);
3698 key_data = mic + mic_len + 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003699
3700 if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN)
3701 {
3702 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
3703 "WPA: EAPOL-Key type (%d) unknown, discarded",
3704 key->type);
3705 ret = 0;
3706 goto out;
3707 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003709 key_data_len = WPA_GET_BE16(mic + mic_len);
3710 wpa_eapol_key_dump(sm, key, key_data_len, mic, mic_len);
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003711
3712 if (key_data_len > plen - keyhdrlen) {
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003713 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key "
3714 "frame - key_data overflow (%u > %u)",
3715 (unsigned int) key_data_len,
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003716 (unsigned int) (plen - keyhdrlen));
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003717 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003718 }
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003719
Sunil Ravi77d572f2023-01-17 23:58:31 +00003720 if (sm->rx_replay_counter_set &&
3721 os_memcmp(key->replay_counter, sm->rx_replay_counter,
3722 WPA_REPLAY_COUNTER_LEN) <= 0) {
3723 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3724 "WPA: EAPOL-Key Replay Counter did not increase - dropping packet");
3725 goto out;
3726 }
3727
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003728 eapol_sm_notify_lower_layer_success(sm->eapol, 0);
Sunil Ravi77d572f2023-01-17 23:58:31 +00003729
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003730 key_info = WPA_GET_BE16(key->key_info);
Sunil Ravi77d572f2023-01-17 23:58:31 +00003731
3732 if (key_info & WPA_KEY_INFO_SMK_MESSAGE) {
3733 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3734 "WPA: Unsupported SMK bit in key_info");
3735 goto out;
3736 }
3737
3738 if (!(key_info & WPA_KEY_INFO_ACK)) {
3739 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3740 "WPA: No Ack bit in key_info");
3741 goto out;
3742 }
3743
3744 if (key_info & WPA_KEY_INFO_REQUEST) {
3745 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3746 "WPA: EAPOL-Key with Request bit - dropped");
3747 goto out;
3748 }
3749
3750 if (sm->proto == WPA_PROTO_WPA) {
3751 ret = wpa_sm_rx_eapol_wpa(sm, src_addr, key, encrypted,
3752 tmp, data_len,
3753 key_data, key_data_len);
3754 goto out;
3755 }
3756
3757 if (key->type != EAPOL_KEY_TYPE_RSN) {
3758 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3759 "RSN: Unsupported EAPOL-Key type %d", key->type);
3760 goto out;
3761 }
3762
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003763 ver = key_info & WPA_KEY_INFO_TYPE_MASK;
3764 if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003765 ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003766 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07003767 !wpa_use_akm_defined(sm->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003768 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003769 "RSN: Unsupported EAPOL-Key descriptor version %d",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003770 ver);
3771 goto out;
3772 }
3773
Sunil Ravi77d572f2023-01-17 23:58:31 +00003774 if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
3775 sm->pairwise_cipher != WPA_CIPHER_TKIP) {
3776 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3777 "RSN: EAPOL-Key descriptor version %d not allowed without TKIP as the pairwise cipher",
3778 ver);
3779 goto out;
3780 }
3781
3782 if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
3783 (sm->key_mgmt != WPA_KEY_MGMT_IEEE8021X &&
3784 sm->key_mgmt != WPA_KEY_MGMT_PSK)) {
3785 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3786 "RSN: EAPOL-Key descriptor version %d not allowed due to negotiated AKM (0x%x)",
3787 ver, sm->key_mgmt);
3788 goto out;
3789 }
3790
Roshan Pius3a1667e2018-07-03 15:17:14 -07003791 if (wpa_use_akm_defined(sm->key_mgmt) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003792 ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) {
3793 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3794 "RSN: Unsupported EAPOL-Key descriptor version %d (expected AKM defined = 0)",
3795 ver);
3796 goto out;
3797 }
3798
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003799#ifdef CONFIG_IEEE80211R
3800 if (wpa_key_mgmt_ft(sm->key_mgmt)) {
3801 /* IEEE 802.11r uses a new key_info type (AES-128-CMAC). */
Roshan Pius3a1667e2018-07-03 15:17:14 -07003802 if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
3803 !wpa_use_akm_defined(sm->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
3805 "FT: AP did not use AES-128-CMAC");
3806 goto out;
3807 }
3808 } else
3809#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003810 if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003811 if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07003812 !wpa_use_akm_defined(sm->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003813 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003814 "RSN: AP did not use the negotiated AES-128-CMAC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003815 goto out;
3816 }
Hai Shalomc3565922019-10-28 11:58:20 -07003817 } else if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
3818 !wpa_use_akm_defined(sm->key_mgmt) &&
3819 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003820 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003821 "RSN: CCMP is used, but EAPOL-Key descriptor version (%d) is not 2", ver);
3822 if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003823 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003824 "RSN: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used");
3825 } else {
Jouni Malinen658fb4a2014-11-14 20:57:05 +02003826 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003827 "RSN: Unexpected descriptor version %u", ver);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003828 goto out;
Sunil Ravi77d572f2023-01-17 23:58:31 +00003829 }
Dmitry Shmidt71757432014-06-02 13:50:35 -07003830 } else if (sm->pairwise_cipher == WPA_CIPHER_GCMP &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07003831 !wpa_use_akm_defined(sm->key_mgmt) &&
Dmitry Shmidt71757432014-06-02 13:50:35 -07003832 ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003833 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003834 "RSN: GCMP is used, but EAPOL-Key descriptor version (%d) is not 2",
3835 ver);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003836 goto out;
3837 }
3838
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003839 if ((key_info & WPA_KEY_INFO_MIC) &&
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003840 wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003841 goto out;
3842
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003843#ifdef CONFIG_FILS
3844 if (!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) {
3845 if (wpa_supp_aead_decrypt(sm, tmp, data_len, &key_data_len))
3846 goto out;
3847 }
3848#endif /* CONFIG_FILS */
3849
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003850 if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) &&
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003851 (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) && mic_len) {
Hai Shalomce48b4a2018-09-05 11:41:35 -07003852 /*
3853 * Only decrypt the Key Data field if the frame's authenticity
3854 * was verified. When using AES-SIV (FILS), the MIC flag is not
3855 * set, so this check should only be performed if mic_len != 0
3856 * which is the case in this code branch.
3857 */
3858 if (!(key_info & WPA_KEY_INFO_MIC)) {
3859 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
3860 "WPA: Ignore EAPOL-Key with encrypted but unauthenticated data");
3861 goto out;
3862 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003863 if (wpa_supplicant_decrypt_key_data(sm, key, mic_len,
3864 ver, key_data,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003865 &key_data_len))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003866 goto out;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003867 }
3868
3869 if (key_info & WPA_KEY_INFO_KEY_TYPE) {
3870 if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) {
3871 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003872 "RSN: Ignored EAPOL-Key (Pairwise) with non-zero key index");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003873 goto out;
3874 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003875 if (key_info & (WPA_KEY_INFO_MIC |
3876 WPA_KEY_INFO_ENCR_KEY_DATA)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003877 /* 3/4 4-Way Handshake */
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003878 wpa_supplicant_process_3_of_4(sm, key, ver, key_data,
3879 key_data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003880 } else {
3881 /* 1/4 4-Way Handshake */
3882 wpa_supplicant_process_1_of_4(sm, src_addr, key,
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07003883 ver, key_data,
Sunil8cd6f4d2022-06-28 18:40:46 +00003884 key_data_len,
3885 encrypted);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003886 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003887 } else {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003888 if ((mic_len && (key_info & WPA_KEY_INFO_MIC)) ||
3889 (!mic_len && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003890 /* 1/2 Group Key Handshake */
Sunil Ravi77d572f2023-01-17 23:58:31 +00003891 if (sm->mlo.valid_links)
3892 wpa_supplicant_process_mlo_1_of_2(sm, src_addr,
3893 key, key_data,
3894 key_data_len,
3895 ver);
3896 else
3897 wpa_supplicant_process_1_of_2(sm, src_addr, key,
3898 key_data,
3899 key_data_len,
3900 ver);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003901 } else {
3902 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
Sunil Ravi77d572f2023-01-17 23:58:31 +00003903 "RSN: EAPOL-Key (Group) without Mic/Encr bit - dropped");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003904 }
3905 }
3906
3907 ret = 1;
3908
3909out:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003910 bin_clear_free(tmp, data_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003911 return ret;
3912}
3913
3914
3915#ifdef CONFIG_CTRL_IFACE
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003916static u32 wpa_key_mgmt_suite(struct wpa_sm *sm)
3917{
3918 switch (sm->key_mgmt) {
3919 case WPA_KEY_MGMT_IEEE8021X:
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003920 return ((sm->proto == WPA_PROTO_RSN ||
3921 sm->proto == WPA_PROTO_OSEN) ?
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003922 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X :
3923 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X);
3924 case WPA_KEY_MGMT_PSK:
3925 return (sm->proto == WPA_PROTO_RSN ?
3926 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X :
3927 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X);
3928#ifdef CONFIG_IEEE80211R
3929 case WPA_KEY_MGMT_FT_IEEE8021X:
3930 return RSN_AUTH_KEY_MGMT_FT_802_1X;
3931 case WPA_KEY_MGMT_FT_PSK:
3932 return RSN_AUTH_KEY_MGMT_FT_PSK;
3933#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003934 case WPA_KEY_MGMT_IEEE8021X_SHA256:
3935 return RSN_AUTH_KEY_MGMT_802_1X_SHA256;
3936 case WPA_KEY_MGMT_PSK_SHA256:
3937 return RSN_AUTH_KEY_MGMT_PSK_SHA256;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003938 case WPA_KEY_MGMT_CCKM:
3939 return (sm->proto == WPA_PROTO_RSN ?
3940 RSN_AUTH_KEY_MGMT_CCKM:
3941 WPA_AUTH_KEY_MGMT_CCKM);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003942 case WPA_KEY_MGMT_WPA_NONE:
3943 return WPA_AUTH_KEY_MGMT_NONE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003944 case WPA_KEY_MGMT_IEEE8021X_SUITE_B:
3945 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003946 case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192:
3947 return RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003948 case WPA_KEY_MGMT_IEEE8021X_SHA384:
3949 return RSN_AUTH_KEY_MGMT_802_1X_SHA384;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003950 default:
3951 return 0;
3952 }
3953}
3954
3955
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003956#define RSN_SUITE "%02x-%02x-%02x-%d"
3957#define RSN_SUITE_ARG(s) \
3958((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
3959
3960/**
3961 * wpa_sm_get_mib - Dump text list of MIB entries
3962 * @sm: Pointer to WPA state machine data from wpa_sm_init()
3963 * @buf: Buffer for the list
3964 * @buflen: Length of the buffer
3965 * Returns: Number of bytes written to buffer
3966 *
3967 * This function is used fetch dot11 MIB variables.
3968 */
3969int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen)
3970{
3971 char pmkid_txt[PMKID_LEN * 2 + 1];
Hai Shalome21d4e82020-04-29 16:34:06 -07003972 bool rsna;
3973 int ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003974 size_t len;
3975
3976 if (sm->cur_pmksa) {
3977 wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt),
3978 sm->cur_pmksa->pmkid, PMKID_LEN);
3979 } else
3980 pmkid_txt[0] = '\0';
3981
Hai Shalome21d4e82020-04-29 16:34:06 -07003982 rsna = (wpa_key_mgmt_wpa_psk(sm->key_mgmt) ||
3983 wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) &&
3984 sm->proto == WPA_PROTO_RSN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003985
3986 ret = os_snprintf(buf, buflen,
3987 "dot11RSNAOptionImplemented=TRUE\n"
3988 "dot11RSNAPreauthenticationImplemented=TRUE\n"
3989 "dot11RSNAEnabled=%s\n"
3990 "dot11RSNAPreauthenticationEnabled=%s\n"
3991 "dot11RSNAConfigVersion=%d\n"
3992 "dot11RSNAConfigPairwiseKeysSupported=5\n"
3993 "dot11RSNAConfigGroupCipherSize=%d\n"
3994 "dot11RSNAConfigPMKLifetime=%d\n"
3995 "dot11RSNAConfigPMKReauthThreshold=%d\n"
3996 "dot11RSNAConfigNumberOfPTKSAReplayCounters=1\n"
3997 "dot11RSNAConfigSATimeout=%d\n",
3998 rsna ? "TRUE" : "FALSE",
3999 rsna ? "TRUE" : "FALSE",
4000 RSN_VERSION,
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07004001 wpa_cipher_key_len(sm->group_cipher) * 8,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004002 sm->dot11RSNAConfigPMKLifetime,
4003 sm->dot11RSNAConfigPMKReauthThreshold,
4004 sm->dot11RSNAConfigSATimeout);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004005 if (os_snprintf_error(buflen, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004006 return 0;
4007 len = ret;
4008
4009 ret = os_snprintf(
4010 buf + len, buflen - len,
4011 "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n"
4012 "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n"
4013 "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n"
4014 "dot11RSNAPMKIDUsed=%s\n"
4015 "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n"
4016 "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n"
4017 "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n"
4018 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n"
4019 "dot11RSNA4WayHandshakeFailures=%u\n",
4020 RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07004021 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
4022 sm->pairwise_cipher)),
4023 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
4024 sm->group_cipher)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004025 pmkid_txt,
4026 RSN_SUITE_ARG(wpa_key_mgmt_suite(sm)),
Dmitry Shmidt4530cfd2012-09-09 15:20:40 -07004027 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
4028 sm->pairwise_cipher)),
4029 RSN_SUITE_ARG(wpa_cipher_to_suite(sm->proto,
4030 sm->group_cipher)),
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004031 sm->dot11RSNA4WayHandshakeFailures);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004032 if (!os_snprintf_error(buflen - len, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004033 len += ret;
4034
4035 return (int) len;
4036}
4037#endif /* CONFIG_CTRL_IFACE */
4038
4039
4040static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004041 void *ctx, enum pmksa_free_reason reason)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004042{
4043 struct wpa_sm *sm = ctx;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004044 int deauth = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004045
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004046 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA cache entry free_cb: "
4047 MACSTR " reason=%d", MAC2STR(entry->aa), reason);
4048
4049 if (sm->cur_pmksa == entry) {
4050 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
4051 "RSN: %s current PMKSA entry",
4052 reason == PMKSA_REPLACE ? "replaced" : "removed");
4053 pmksa_cache_clear_current(sm);
4054
4055 /*
4056 * If an entry is simply being replaced, there's no need to
4057 * deauthenticate because it will be immediately re-added.
4058 * This happens when EAP authentication is completed again
4059 * (reauth or failed PMKSA caching attempt).
4060 */
4061 if (reason != PMKSA_REPLACE)
4062 deauth = 1;
4063 }
4064
4065 if (reason == PMKSA_EXPIRE &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004066 (sm->pmk_len == entry->pmk_len &&
4067 os_memcmp(sm->pmk, entry->pmk, sm->pmk_len) == 0)) {
4068 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004069 "RSN: deauthenticating due to expired PMK");
4070 pmksa_cache_clear_current(sm);
4071 deauth = 1;
4072 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004073
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004074 if (deauth) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07004075 sm->pmk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004076 os_memset(sm->pmk, 0, sizeof(sm->pmk));
4077 wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED);
4078 }
4079}
4080
4081
Hai Shalomc1a21442022-02-04 13:43:00 -08004082static bool wpa_sm_pmksa_is_current_cb(struct rsn_pmksa_cache_entry *entry,
4083 void *ctx)
4084{
4085 struct wpa_sm *sm = ctx;
4086
4087 return sm->cur_pmksa == entry;
4088}
4089
4090
Sunil Ravi77d572f2023-01-17 23:58:31 +00004091static void wpa_sm_pmksa_notify_cb(struct rsn_pmksa_cache_entry *entry,
4092 void *ctx)
4093{
4094 struct wpa_sm *sm = ctx;
4095
4096 wpa_sm_notify_pmksa_cache_entry(sm, entry);
4097}
4098
4099
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004100/**
4101 * wpa_sm_init - Initialize WPA state machine
4102 * @ctx: Context pointer for callbacks; this needs to be an allocated buffer
4103 * Returns: Pointer to the allocated WPA state machine data
4104 *
4105 * This function is used to allocate a new WPA state machine and the returned
4106 * value is passed to all WPA state machine calls.
4107 */
4108struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx)
4109{
4110 struct wpa_sm *sm;
4111
4112 sm = os_zalloc(sizeof(*sm));
4113 if (sm == NULL)
4114 return NULL;
4115 dl_list_init(&sm->pmksa_candidates);
4116 sm->renew_snonce = 1;
4117 sm->ctx = ctx;
4118
4119 sm->dot11RSNAConfigPMKLifetime = 43200;
4120 sm->dot11RSNAConfigPMKReauthThreshold = 70;
4121 sm->dot11RSNAConfigSATimeout = 60;
4122
Hai Shalomc1a21442022-02-04 13:43:00 -08004123 sm->pmksa = pmksa_cache_init(wpa_sm_pmksa_free_cb,
Sunil Ravi77d572f2023-01-17 23:58:31 +00004124 wpa_sm_pmksa_is_current_cb,
4125 wpa_sm_pmksa_notify_cb, sm, sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004126 if (sm->pmksa == NULL) {
4127 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
4128 "RSN: PMKSA cache initialization failed");
4129 os_free(sm);
4130 return NULL;
4131 }
4132
4133 return sm;
4134}
4135
4136
4137/**
4138 * wpa_sm_deinit - Deinitialize WPA state machine
4139 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4140 */
4141void wpa_sm_deinit(struct wpa_sm *sm)
4142{
Sunil Ravi77d572f2023-01-17 23:58:31 +00004143 int i;
4144
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004145 if (sm == NULL)
4146 return;
4147 pmksa_cache_deinit(sm->pmksa);
4148 eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
4149 eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
4150 os_free(sm->assoc_wpa_ie);
Hai Shalomc3565922019-10-28 11:58:20 -07004151 os_free(sm->assoc_rsnxe);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004152 os_free(sm->ap_wpa_ie);
4153 os_free(sm->ap_rsn_ie);
Hai Shalomc3565922019-10-28 11:58:20 -07004154 os_free(sm->ap_rsnxe);
Sunil Ravi77d572f2023-01-17 23:58:31 +00004155 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
4156 os_free(sm->mlo.links[i].ap_rsne);
4157 os_free(sm->mlo.links[i].ap_rsnxe);
4158 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004159 wpa_sm_drop_sa(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160 os_free(sm->ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004161#ifdef CONFIG_IEEE80211R
4162 os_free(sm->assoc_resp_ies);
4163#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004164#ifdef CONFIG_TESTING_OPTIONS
4165 wpabuf_free(sm->test_assoc_ie);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004166 wpabuf_free(sm->test_eapol_m2_elems);
4167 wpabuf_free(sm->test_eapol_m4_elems);
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004168#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004169#ifdef CONFIG_FILS_SK_PFS
4170 crypto_ecdh_deinit(sm->fils_ecdh);
4171#endif /* CONFIG_FILS_SK_PFS */
4172#ifdef CONFIG_FILS
4173 wpabuf_free(sm->fils_ft_ies);
4174#endif /* CONFIG_FILS */
4175#ifdef CONFIG_OWE
4176 crypto_ecdh_deinit(sm->owe_ecdh);
4177#endif /* CONFIG_OWE */
Hai Shalom021b0b52019-04-10 11:17:58 -07004178#ifdef CONFIG_DPP2
4179 wpabuf_clear_free(sm->dpp_z);
4180#endif /* CONFIG_DPP2 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004181 os_free(sm);
4182}
4183
4184
Sunil Ravi77d572f2023-01-17 23:58:31 +00004185static void wpa_sm_clear_ptk(struct wpa_sm *sm)
4186{
4187 int i;
4188
4189 sm->ptk_set = 0;
4190 os_memset(&sm->ptk, 0, sizeof(sm->ptk));
4191 sm->tptk_set = 0;
4192 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
4193 os_memset(&sm->gtk, 0, sizeof(sm->gtk));
4194 os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
4195 os_memset(&sm->igtk, 0, sizeof(sm->igtk));
4196 os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004197 os_memset(&sm->bigtk, 0, sizeof(sm->bigtk));
4198 os_memset(&sm->bigtk_wnm_sleep, 0, sizeof(sm->bigtk_wnm_sleep));
Sunil Ravi77d572f2023-01-17 23:58:31 +00004199 sm->tk_set = false;
4200 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
4201 os_memset(&sm->mlo.links[i].gtk, 0,
4202 sizeof(sm->mlo.links[i].gtk));
4203 os_memset(&sm->mlo.links[i].gtk_wnm_sleep, 0,
4204 sizeof(sm->mlo.links[i].gtk_wnm_sleep));
4205 os_memset(&sm->mlo.links[i].igtk, 0,
4206 sizeof(sm->mlo.links[i].igtk));
4207 os_memset(&sm->mlo.links[i].igtk_wnm_sleep, 0,
4208 sizeof(sm->mlo.links[i].igtk_wnm_sleep));
Sunil Ravi2a14cf12023-11-21 00:54:38 +00004209 os_memset(&sm->mlo.links[i].bigtk, 0,
4210 sizeof(sm->mlo.links[i].bigtk));
4211 os_memset(&sm->mlo.links[i].bigtk_wnm_sleep, 0,
4212 sizeof(sm->mlo.links[i].bigtk_wnm_sleep));
Sunil Ravi77d572f2023-01-17 23:58:31 +00004213 }
4214}
4215
4216
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004217/**
4218 * wpa_sm_notify_assoc - Notify WPA state machine about association
4219 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4220 * @bssid: The BSSID of the new association
4221 *
4222 * This function is called to let WPA state machine know that the connection
4223 * was established.
4224 */
4225void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
4226{
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02004227 int clear_keys = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004228
4229 if (sm == NULL)
4230 return;
4231
4232 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
4233 "WPA: Association event - clear replay counter");
4234 os_memcpy(sm->bssid, bssid, ETH_ALEN);
4235 os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
4236 sm->rx_replay_counter_set = 0;
4237 sm->renew_snonce = 1;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004238 if (ether_addr_equal(sm->preauth_bssid, bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004239 rsn_preauth_deinit(sm);
4240
4241#ifdef CONFIG_IEEE80211R
4242 if (wpa_ft_is_completed(sm)) {
4243 /*
4244 * Clear portValid to kick EAPOL state machine to re-enter
4245 * AUTHENTICATED state to get the EAPOL port Authorized.
4246 */
Hai Shalome21d4e82020-04-29 16:34:06 -07004247 eapol_sm_notify_portValid(sm->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004248 wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
4249
4250 /* Prepare for the next transition */
4251 wpa_ft_prepare_auth_request(sm, NULL);
4252
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02004253 clear_keys = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07004254 sm->ft_protocol = 1;
4255 } else {
4256 sm->ft_protocol = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004257 }
4258#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004259#ifdef CONFIG_FILS
4260 if (sm->fils_completed) {
4261 /*
4262 * Clear portValid to kick EAPOL state machine to re-enter
4263 * AUTHENTICATED state to get the EAPOL port Authorized.
4264 */
4265 wpa_supplicant_key_neg_complete(sm, sm->bssid, 1);
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02004266 clear_keys = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004267 }
4268#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004269
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02004270 if (clear_keys) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004271 /*
4272 * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
4273 * this is not part of a Fast BSS Transition.
4274 */
4275 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK");
Sunil Ravi77d572f2023-01-17 23:58:31 +00004276 wpa_sm_clear_ptk(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004277 }
4278
4279#ifdef CONFIG_TDLS
4280 wpa_tdls_assoc(sm);
4281#endif /* CONFIG_TDLS */
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004282
4283#ifdef CONFIG_P2P
4284 os_memset(sm->p2p_ip_addr, 0, sizeof(sm->p2p_ip_addr));
4285#endif /* CONFIG_P2P */
Hai Shalomfdcde762020-04-02 11:19:20 -07004286
4287 sm->keyidx_active = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004288}
4289
4290
4291/**
4292 * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation
4293 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4294 *
4295 * This function is called to let WPA state machine know that the connection
4296 * was lost. This will abort any existing pre-authentication session.
4297 */
4298void wpa_sm_notify_disassoc(struct wpa_sm *sm)
4299{
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07004300 eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL);
4301 eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004302 rsn_preauth_deinit(sm);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004303 pmksa_cache_clear_current(sm);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004304 if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE)
4305 sm->dot11RSNA4WayHandshakeFailures++;
4306#ifdef CONFIG_TDLS
4307 wpa_tdls_disassoc(sm);
4308#endif /* CONFIG_TDLS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004309#ifdef CONFIG_FILS
4310 sm->fils_completed = 0;
4311#endif /* CONFIG_FILS */
Jouni Malinen4283f9e2017-09-22 12:06:37 +03004312#ifdef CONFIG_IEEE80211R
4313 sm->ft_reassoc_completed = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07004314 sm->ft_protocol = 0;
Jouni Malinen4283f9e2017-09-22 12:06:37 +03004315#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004316
4317 /* Keys are not needed in the WPA state machine anymore */
4318 wpa_sm_drop_sa(sm);
Hai Shalomfdcde762020-04-02 11:19:20 -07004319 sm->keyidx_active = 0;
Dmitry Shmidt4dd28dc2015-03-10 11:21:43 -07004320
4321 sm->msg_3_of_4_ok = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004322 os_memset(sm->bssid, 0, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004323}
4324
4325
4326/**
4327 * wpa_sm_set_pmk - Set PMK
4328 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4329 * @pmk: The new PMK
4330 * @pmk_len: The length of the new PMK in bytes
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004331 * @pmkid: Calculated PMKID
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004332 * @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004333 *
4334 * Configure the PMK for WPA state machine.
4335 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004336void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004337 const u8 *pmkid, const u8 *bssid)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004338{
4339 if (sm == NULL)
4340 return;
4341
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004342 wpa_hexdump_key(MSG_DEBUG, "WPA: Set PMK based on external data",
4343 pmk, pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004344 sm->pmk_len = pmk_len;
4345 os_memcpy(sm->pmk, pmk, pmk_len);
4346
4347#ifdef CONFIG_IEEE80211R
4348 /* Set XXKey to be PSK for FT key derivation */
4349 sm->xxkey_len = pmk_len;
4350 os_memcpy(sm->xxkey, pmk, pmk_len);
4351#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004352
4353 if (bssid) {
Hai Shalomc1a21442022-02-04 13:43:00 -08004354 sm->cur_pmksa = pmksa_cache_add(sm->pmksa, pmk, pmk_len,
4355 pmkid, NULL, 0, bssid,
4356 sm->own_addr,
4357 sm->network_ctx, sm->key_mgmt,
4358 NULL);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004359 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004360}
4361
4362
4363/**
4364 * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA
4365 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4366 *
4367 * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK
4368 * will be cleared.
4369 */
4370void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm)
4371{
4372 if (sm == NULL)
4373 return;
4374
4375 if (sm->cur_pmksa) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004376 wpa_hexdump_key(MSG_DEBUG,
4377 "WPA: Set PMK based on current PMKSA",
4378 sm->cur_pmksa->pmk, sm->cur_pmksa->pmk_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004379 sm->pmk_len = sm->cur_pmksa->pmk_len;
4380 os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len);
4381 } else {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004382 wpa_printf(MSG_DEBUG, "WPA: No current PMKSA - clear PMK");
4383 sm->pmk_len = 0;
4384 os_memset(sm->pmk, 0, PMK_LEN_MAX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004385 }
4386}
4387
4388
4389/**
4390 * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled
4391 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4392 * @fast_reauth: Whether fast reauthentication (EAP) is allowed
4393 */
4394void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth)
4395{
4396 if (sm)
4397 sm->fast_reauth = fast_reauth;
4398}
4399
4400
4401/**
4402 * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks
4403 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4404 * @scard_ctx: Context pointer for smartcard related callback functions
4405 */
4406void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx)
4407{
4408 if (sm == NULL)
4409 return;
4410 sm->scard_ctx = scard_ctx;
4411 if (sm->preauth_eapol)
4412 eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx);
4413}
4414
4415
4416/**
Hai Shalomfdcde762020-04-02 11:19:20 -07004417 * wpa_sm_set_config - Notification of current configuration change
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004418 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4419 * @config: Pointer to current network configuration
4420 *
4421 * Notify WPA state machine that configuration has changed. config will be
4422 * stored as a backpointer to network configuration. This can be %NULL to clear
4423 * the stored pointed.
4424 */
4425void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
4426{
4427 if (!sm)
4428 return;
4429
4430 if (config) {
4431 sm->network_ctx = config->network_ctx;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004432 sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher;
4433 sm->proactive_key_caching = config->proactive_key_caching;
4434 sm->eap_workaround = config->eap_workaround;
4435 sm->eap_conf_ctx = config->eap_conf_ctx;
4436 if (config->ssid) {
4437 os_memcpy(sm->ssid, config->ssid, config->ssid_len);
4438 sm->ssid_len = config->ssid_len;
4439 } else
4440 sm->ssid_len = 0;
4441 sm->wpa_ptk_rekey = config->wpa_ptk_rekey;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004442 sm->p2p = config->p2p;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004443 sm->wpa_rsc_relaxation = config->wpa_rsc_relaxation;
Hai Shalomfdcde762020-04-02 11:19:20 -07004444 sm->owe_ptk_workaround = config->owe_ptk_workaround;
Hai Shalom60840252021-02-19 19:02:11 -08004445 sm->force_kdk_derivation = config->force_kdk_derivation;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004446#ifdef CONFIG_FILS
4447 if (config->fils_cache_id) {
4448 sm->fils_cache_id_set = 1;
4449 os_memcpy(sm->fils_cache_id, config->fils_cache_id,
4450 FILS_CACHE_ID_LEN);
4451 } else {
4452 sm->fils_cache_id_set = 0;
4453 }
4454#endif /* CONFIG_FILS */
Hai Shalomfdcde762020-04-02 11:19:20 -07004455 sm->beacon_prot = config->beacon_prot;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004456 } else {
4457 sm->network_ctx = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004458 sm->allowed_pairwise_cipher = 0;
4459 sm->proactive_key_caching = 0;
4460 sm->eap_workaround = 0;
4461 sm->eap_conf_ctx = NULL;
4462 sm->ssid_len = 0;
4463 sm->wpa_ptk_rekey = 0;
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08004464 sm->p2p = 0;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004465 sm->wpa_rsc_relaxation = 0;
Hai Shalomfdcde762020-04-02 11:19:20 -07004466 sm->owe_ptk_workaround = 0;
4467 sm->beacon_prot = 0;
Hai Shalom60840252021-02-19 19:02:11 -08004468 sm->force_kdk_derivation = false;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004469 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004470}
4471
4472
Sunil Ravi77d572f2023-01-17 23:58:31 +00004473int wpa_sm_set_mlo_params(struct wpa_sm *sm, const struct wpa_sm_mlo *mlo)
4474{
4475 int i;
4476
4477 if (!sm)
4478 return -1;
4479
4480 os_memcpy(sm->mlo.ap_mld_addr, mlo->ap_mld_addr, ETH_ALEN);
4481 sm->mlo.assoc_link_id = mlo->assoc_link_id;
4482 sm->mlo.valid_links = mlo->valid_links;
4483 sm->mlo.req_links = mlo->req_links;
4484
4485 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
4486 const u8 *ie;
4487 size_t len;
4488
4489 if (sm->mlo.req_links & BIT(i)) {
4490 if (!mlo->links[i].ap_rsne ||
4491 mlo->links[i].ap_rsne_len == 0) {
4492 wpa_dbg(sm->ctx->msg_ctx, MSG_INFO,
4493 "RSN: No RSNE for AP MLO link %d with BSSID "
4494 MACSTR,
4495 i, MAC2STR(mlo->links[i].bssid));
4496 return -1;
4497
4498 }
4499 os_memcpy(sm->mlo.links[i].addr, mlo->links[i].addr,
4500 ETH_ALEN);
4501 os_memcpy(sm->mlo.links[i].bssid, mlo->links[i].bssid,
4502 ETH_ALEN);
4503 }
4504
4505 ie = mlo->links[i].ap_rsne;
4506 len = mlo->links[i].ap_rsne_len;
4507 os_free(sm->mlo.links[i].ap_rsne);
4508 if (!ie || len == 0) {
4509 if (sm->mlo.links[i].ap_rsne)
4510 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
4511 "RSN: Clearing MLO link[%u] AP RSNE",
4512 i);
4513 sm->mlo.links[i].ap_rsne = NULL;
4514 sm->mlo.links[i].ap_rsne_len = 0;
4515 } else {
4516 wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNE",
4517 ie, len);
4518 sm->mlo.links[i].ap_rsne = os_memdup(ie, len);
4519 if (!sm->mlo.links[i].ap_rsne) {
4520 sm->mlo.links[i].ap_rsne_len = 0;
4521 return -1;
4522 }
4523 sm->mlo.links[i].ap_rsne_len = len;
4524 }
4525
4526 ie = mlo->links[i].ap_rsnxe;
4527 len = mlo->links[i].ap_rsnxe_len;
4528 os_free(sm->mlo.links[i].ap_rsnxe);
4529 if (!ie || len == 0) {
4530 if (sm->mlo.links[i].ap_rsnxe)
4531 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
4532 "RSN: Clearing MLO link[%u] AP RSNXE",
4533 i);
4534 sm->mlo.links[i].ap_rsnxe = NULL;
4535 sm->mlo.links[i].ap_rsnxe_len = 0;
4536 } else {
4537 wpa_hexdump_link(MSG_DEBUG, i, "RSN: Set AP RSNXE", ie,
4538 len);
4539 sm->mlo.links[i].ap_rsnxe = os_memdup(ie, len);
4540 if (!sm->mlo.links[i].ap_rsnxe) {
4541 sm->mlo.links[i].ap_rsnxe_len = 0;
4542 return -1;
4543 }
4544 sm->mlo.links[i].ap_rsnxe_len = len;
4545 }
4546 }
4547
4548 return 0;
4549}
4550
4551
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004552/**
4553 * wpa_sm_set_own_addr - Set own MAC address
4554 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4555 * @addr: Own MAC address
4556 */
4557void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr)
4558{
4559 if (sm)
4560 os_memcpy(sm->own_addr, addr, ETH_ALEN);
4561}
4562
4563
4564/**
4565 * wpa_sm_set_ifname - Set network interface name
4566 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4567 * @ifname: Interface name
4568 * @bridge_ifname: Optional bridge interface name (for pre-auth)
4569 */
4570void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname,
4571 const char *bridge_ifname)
4572{
4573 if (sm) {
4574 sm->ifname = ifname;
4575 sm->bridge_ifname = bridge_ifname;
4576 }
4577}
4578
4579
4580/**
4581 * wpa_sm_set_eapol - Set EAPOL state machine pointer
4582 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4583 * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init()
4584 */
4585void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol)
4586{
4587 if (sm)
4588 sm->eapol = eapol;
4589}
4590
4591
4592/**
4593 * wpa_sm_set_param - Set WPA state machine parameters
4594 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4595 * @param: Parameter field
4596 * @value: Parameter value
4597 * Returns: 0 on success, -1 on failure
4598 */
4599int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param,
4600 unsigned int value)
4601{
4602 int ret = 0;
4603
4604 if (sm == NULL)
4605 return -1;
4606
4607 switch (param) {
4608 case RSNA_PMK_LIFETIME:
4609 if (value > 0)
4610 sm->dot11RSNAConfigPMKLifetime = value;
4611 else
4612 ret = -1;
4613 break;
4614 case RSNA_PMK_REAUTH_THRESHOLD:
4615 if (value > 0 && value <= 100)
4616 sm->dot11RSNAConfigPMKReauthThreshold = value;
4617 else
4618 ret = -1;
4619 break;
4620 case RSNA_SA_TIMEOUT:
4621 if (value > 0)
4622 sm->dot11RSNAConfigSATimeout = value;
4623 else
4624 ret = -1;
4625 break;
4626 case WPA_PARAM_PROTO:
4627 sm->proto = value;
4628 break;
4629 case WPA_PARAM_PAIRWISE:
4630 sm->pairwise_cipher = value;
4631 break;
4632 case WPA_PARAM_GROUP:
4633 sm->group_cipher = value;
4634 break;
4635 case WPA_PARAM_KEY_MGMT:
4636 sm->key_mgmt = value;
4637 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004638 case WPA_PARAM_MGMT_GROUP:
4639 sm->mgmt_group_cipher = value;
4640 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004641 case WPA_PARAM_RSN_ENABLED:
4642 sm->rsn_enabled = value;
4643 break;
4644 case WPA_PARAM_MFP:
4645 sm->mfp = value;
4646 break;
Hai Shalom74f70d42019-02-11 14:42:39 -08004647 case WPA_PARAM_OCV:
4648 sm->ocv = value;
4649 break;
Hai Shalomc3565922019-10-28 11:58:20 -07004650 case WPA_PARAM_SAE_PWE:
4651 sm->sae_pwe = value;
4652 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07004653 case WPA_PARAM_SAE_PK:
4654 sm->sae_pk = value;
4655 break;
Hai Shalomfdcde762020-04-02 11:19:20 -07004656 case WPA_PARAM_DENY_PTK0_REKEY:
4657 sm->wpa_deny_ptk0_rekey = value;
4658 break;
4659 case WPA_PARAM_EXT_KEY_ID:
4660 sm->ext_key_id = value;
4661 break;
4662 case WPA_PARAM_USE_EXT_KEY_ID:
4663 sm->use_ext_key_id = value;
4664 break;
Hai Shalomb755a2a2020-04-23 21:49:02 -07004665#ifdef CONFIG_TESTING_OPTIONS
4666 case WPA_PARAM_FT_RSNXE_USED:
4667 sm->ft_rsnxe_used = value;
4668 break;
Hai Shalom899fcc72020-10-19 14:38:18 -07004669 case WPA_PARAM_OCI_FREQ_EAPOL:
4670 sm->oci_freq_override_eapol = value;
4671 break;
4672 case WPA_PARAM_OCI_FREQ_EAPOL_G2:
4673 sm->oci_freq_override_eapol_g2 = value;
4674 break;
4675 case WPA_PARAM_OCI_FREQ_FT_ASSOC:
4676 sm->oci_freq_override_ft_assoc = value;
4677 break;
4678 case WPA_PARAM_OCI_FREQ_FILS_ASSOC:
4679 sm->oci_freq_override_fils_assoc = value;
4680 break;
Sunil Ravia04bd252022-05-02 22:54:18 -07004681 case WPA_PARAM_DISABLE_EAPOL_G2_TX:
4682 sm->disable_eapol_g2_tx = value;
4683 break;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004684 case WPA_PARAM_ENCRYPT_EAPOL_M2:
4685 sm->encrypt_eapol_m2 = value;
4686 break;
4687 case WPA_PARAM_ENCRYPT_EAPOL_M4:
4688 sm->encrypt_eapol_m4 = value;
4689 break;
Hai Shalomb755a2a2020-04-23 21:49:02 -07004690#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004691#ifdef CONFIG_DPP2
4692 case WPA_PARAM_DPP_PFS:
4693 sm->dpp_pfs = value;
4694 break;
4695#endif /* CONFIG_DPP2 */
Sunil Ravi640215c2023-06-28 23:08:09 +00004696 case WPA_PARAM_WMM_ENABLED:
4697 sm->wmm_enabled = value;
4698 break;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00004699 case WPA_PARAM_FT_PREPEND_PMKID:
4700 sm->ft_prepend_pmkid = value;
4701 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004702 default:
4703 break;
4704 }
4705
4706 return ret;
4707}
4708
4709
4710/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004711 * wpa_sm_get_status - Get WPA state machine
4712 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4713 * @buf: Buffer for status information
4714 * @buflen: Maximum buffer length
4715 * @verbose: Whether to include verbose status information
4716 * Returns: Number of bytes written to buf.
4717 *
4718 * Query WPA state machine for status information. This function fills in
4719 * a text area with current status information. If the buffer (buf) is not
4720 * large enough, status information will be truncated to fit the buffer.
4721 */
4722int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen,
4723 int verbose)
4724{
4725 char *pos = buf, *end = buf + buflen;
4726 int ret;
4727
4728 ret = os_snprintf(pos, end - pos,
4729 "pairwise_cipher=%s\n"
4730 "group_cipher=%s\n"
4731 "key_mgmt=%s\n",
4732 wpa_cipher_txt(sm->pairwise_cipher),
4733 wpa_cipher_txt(sm->group_cipher),
4734 wpa_key_mgmt_txt(sm->key_mgmt, sm->proto));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004735 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004736 return pos - buf;
4737 pos += ret;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004738
Hai Shalom4fbc08f2020-05-18 12:37:00 -07004739#ifdef CONFIG_DPP2
4740 if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) {
4741 ret = os_snprintf(pos, end - pos, "dpp_pfs=1\n");
4742 if (os_snprintf_error(end - pos, ret))
4743 return pos - buf;
4744 pos += ret;
4745 }
4746#endif /* CONFIG_DPP2 */
4747
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004748 if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) {
4749 struct wpa_ie_data rsn;
4750 if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn)
4751 >= 0 &&
4752 rsn.capabilities & (WPA_CAPABILITY_MFPR |
4753 WPA_CAPABILITY_MFPC)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004754 ret = os_snprintf(pos, end - pos, "pmf=%d\n"
4755 "mgmt_group_cipher=%s\n",
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004756 (rsn.capabilities &
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004757 WPA_CAPABILITY_MFPR) ? 2 : 1,
4758 wpa_cipher_txt(
4759 sm->mgmt_group_cipher));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004760 if (os_snprintf_error(end - pos, ret))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08004761 return pos - buf;
4762 pos += ret;
4763 }
4764 }
4765
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004766 return pos - buf;
4767}
4768
4769
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07004770int wpa_sm_pmf_enabled(struct wpa_sm *sm)
4771{
4772 struct wpa_ie_data rsn;
4773
4774 if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie)
4775 return 0;
4776
4777 if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 &&
4778 rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC))
4779 return 1;
4780
4781 return 0;
4782}
4783
4784
Hai Shalomfdcde762020-04-02 11:19:20 -07004785int wpa_sm_ext_key_id(struct wpa_sm *sm)
4786{
4787 return sm ? sm->ext_key_id : 0;
4788}
4789
4790
4791int wpa_sm_ext_key_id_active(struct wpa_sm *sm)
4792{
4793 return sm ? sm->use_ext_key_id : 0;
4794}
4795
4796
Hai Shalom74f70d42019-02-11 14:42:39 -08004797int wpa_sm_ocv_enabled(struct wpa_sm *sm)
4798{
4799 struct wpa_ie_data rsn;
4800
4801 if (!sm->ocv || !sm->ap_rsn_ie)
4802 return 0;
4803
4804 return wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len,
4805 &rsn) >= 0 &&
4806 (rsn.capabilities & WPA_CAPABILITY_OCVC);
4807}
4808
4809
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004810/**
4811 * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration
4812 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4813 * @wpa_ie: Pointer to buffer for WPA/RSN IE
4814 * @wpa_ie_len: Pointer to the length of the wpa_ie buffer
4815 * Returns: 0 on success, -1 on failure
4816 */
4817int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie,
4818 size_t *wpa_ie_len)
4819{
4820 int res;
4821
4822 if (sm == NULL)
4823 return -1;
4824
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08004825#ifdef CONFIG_TESTING_OPTIONS
4826 if (sm->test_assoc_ie) {
4827 wpa_printf(MSG_DEBUG,
4828 "TESTING: Replace association WPA/RSN IE");
4829 if (*wpa_ie_len < wpabuf_len(sm->test_assoc_ie))
4830 return -1;
4831 os_memcpy(wpa_ie, wpabuf_head(sm->test_assoc_ie),
4832 wpabuf_len(sm->test_assoc_ie));
4833 res = wpabuf_len(sm->test_assoc_ie);
4834 } else
4835#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004836 res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len);
4837 if (res < 0)
4838 return -1;
4839 *wpa_ie_len = res;
4840
4841 wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default",
4842 wpa_ie, *wpa_ie_len);
4843
4844 if (sm->assoc_wpa_ie == NULL) {
4845 /*
4846 * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets
4847 * the correct version of the IE even if PMKSA caching is
4848 * aborted (which would remove PMKID from IE generation).
4849 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004850 sm->assoc_wpa_ie = os_memdup(wpa_ie, *wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004851 if (sm->assoc_wpa_ie == NULL)
4852 return -1;
4853
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004854 sm->assoc_wpa_ie_len = *wpa_ie_len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004855 } else {
4856 wpa_hexdump(MSG_DEBUG,
4857 "WPA: Leave previously set WPA IE default",
4858 sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004859 }
4860
4861 return 0;
4862}
4863
4864
4865/**
4866 * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq
4867 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4868 * @ie: Pointer to IE data (starting from id)
4869 * @len: IE length
4870 * Returns: 0 on success, -1 on failure
4871 *
4872 * Inform WPA state machine about the WPA/RSN IE used in (Re)Association
4873 * Request frame. The IE will be used to override the default value generated
4874 * with wpa_sm_set_assoc_wpa_ie_default().
4875 */
4876int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
4877{
4878 if (sm == NULL)
4879 return -1;
4880
4881 os_free(sm->assoc_wpa_ie);
4882 if (ie == NULL || len == 0) {
4883 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
4884 "WPA: clearing own WPA/RSN IE");
4885 sm->assoc_wpa_ie = NULL;
4886 sm->assoc_wpa_ie_len = 0;
4887 } else {
4888 wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004889 sm->assoc_wpa_ie = os_memdup(ie, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004890 if (sm->assoc_wpa_ie == NULL)
4891 return -1;
4892
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004893 sm->assoc_wpa_ie_len = len;
4894 }
4895
4896 return 0;
4897}
4898
4899
4900/**
Hai Shalomc3565922019-10-28 11:58:20 -07004901 * wpa_sm_set_assoc_rsnxe_default - Generate own RSNXE from configuration
4902 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4903 * @rsnxe: Pointer to buffer for RSNXE
4904 * @rsnxe_len: Pointer to the length of the rsne buffer
4905 * Returns: 0 on success, -1 on failure
4906 */
4907int wpa_sm_set_assoc_rsnxe_default(struct wpa_sm *sm, u8 *rsnxe,
4908 size_t *rsnxe_len)
4909{
4910 int res;
4911
4912 if (!sm)
4913 return -1;
4914
4915 res = wpa_gen_rsnxe(sm, rsnxe, *rsnxe_len);
4916 if (res < 0)
4917 return -1;
4918 *rsnxe_len = res;
4919
4920 wpa_hexdump(MSG_DEBUG, "RSN: Set own RSNXE default", rsnxe, *rsnxe_len);
4921
4922 if (sm->assoc_rsnxe) {
4923 wpa_hexdump(MSG_DEBUG,
4924 "RSN: Leave previously set RSNXE default",
4925 sm->assoc_rsnxe, sm->assoc_rsnxe_len);
4926 } else if (*rsnxe_len > 0) {
4927 /*
4928 * Make a copy of the RSNXE so that 4-Way Handshake gets the
4929 * correct version of the IE even if it gets changed.
4930 */
4931 sm->assoc_rsnxe = os_memdup(rsnxe, *rsnxe_len);
4932 if (!sm->assoc_rsnxe)
4933 return -1;
4934
4935 sm->assoc_rsnxe_len = *rsnxe_len;
4936 }
4937
4938 return 0;
4939}
4940
4941
4942/**
4943 * wpa_sm_set_assoc_rsnxe - Set own RSNXE from (Re)AssocReq
4944 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4945 * @ie: Pointer to IE data (starting from id)
4946 * @len: IE length
4947 * Returns: 0 on success, -1 on failure
4948 *
4949 * Inform WPA state machine about the RSNXE used in (Re)Association Request
4950 * frame. The IE will be used to override the default value generated
4951 * with wpa_sm_set_assoc_rsnxe_default().
4952 */
4953int wpa_sm_set_assoc_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
4954{
4955 if (!sm)
4956 return -1;
4957
4958 os_free(sm->assoc_rsnxe);
4959 if (!ie || len == 0) {
4960 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
4961 "RSN: clearing own RSNXE");
4962 sm->assoc_rsnxe = NULL;
4963 sm->assoc_rsnxe_len = 0;
4964 } else {
4965 wpa_hexdump(MSG_DEBUG, "RSN: set own RSNXE", ie, len);
4966 sm->assoc_rsnxe = os_memdup(ie, len);
4967 if (!sm->assoc_rsnxe)
4968 return -1;
4969
4970 sm->assoc_rsnxe_len = len;
4971 }
4972
4973 return 0;
4974}
4975
4976
4977/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004978 * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp
4979 * @sm: Pointer to WPA state machine data from wpa_sm_init()
4980 * @ie: Pointer to IE data (starting from id)
4981 * @len: IE length
4982 * Returns: 0 on success, -1 on failure
4983 *
4984 * Inform WPA state machine about the WPA IE used in Beacon / Probe Response
4985 * frame.
4986 */
4987int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
4988{
4989 if (sm == NULL)
4990 return -1;
4991
4992 os_free(sm->ap_wpa_ie);
4993 if (ie == NULL || len == 0) {
4994 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
4995 "WPA: clearing AP WPA IE");
4996 sm->ap_wpa_ie = NULL;
4997 sm->ap_wpa_ie_len = 0;
4998 } else {
4999 wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005000 sm->ap_wpa_ie = os_memdup(ie, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005001 if (sm->ap_wpa_ie == NULL)
5002 return -1;
5003
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005004 sm->ap_wpa_ie_len = len;
5005 }
5006
5007 return 0;
5008}
5009
5010
5011/**
5012 * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp
5013 * @sm: Pointer to WPA state machine data from wpa_sm_init()
5014 * @ie: Pointer to IE data (starting from id)
5015 * @len: IE length
5016 * Returns: 0 on success, -1 on failure
5017 *
5018 * Inform WPA state machine about the RSN IE used in Beacon / Probe Response
5019 * frame.
5020 */
5021int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len)
5022{
5023 if (sm == NULL)
5024 return -1;
5025
5026 os_free(sm->ap_rsn_ie);
5027 if (ie == NULL || len == 0) {
5028 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
5029 "WPA: clearing AP RSN IE");
5030 sm->ap_rsn_ie = NULL;
5031 sm->ap_rsn_ie_len = 0;
5032 } else {
5033 wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005034 sm->ap_rsn_ie = os_memdup(ie, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005035 if (sm->ap_rsn_ie == NULL)
5036 return -1;
5037
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005038 sm->ap_rsn_ie_len = len;
5039 }
5040
5041 return 0;
5042}
5043
5044
5045/**
Hai Shalomc3565922019-10-28 11:58:20 -07005046 * wpa_sm_set_ap_rsnxe - Set AP RSNXE from Beacon/ProbeResp
5047 * @sm: Pointer to WPA state machine data from wpa_sm_init()
5048 * @ie: Pointer to IE data (starting from id)
5049 * @len: IE length
5050 * Returns: 0 on success, -1 on failure
5051 *
5052 * Inform WPA state machine about the RSNXE used in Beacon / Probe Response
5053 * frame.
5054 */
5055int wpa_sm_set_ap_rsnxe(struct wpa_sm *sm, const u8 *ie, size_t len)
5056{
5057 if (!sm)
5058 return -1;
5059
5060 os_free(sm->ap_rsnxe);
5061 if (!ie || len == 0) {
5062 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: clearing AP RSNXE");
5063 sm->ap_rsnxe = NULL;
5064 sm->ap_rsnxe_len = 0;
5065 } else {
5066 wpa_hexdump(MSG_DEBUG, "WPA: set AP RSNXE", ie, len);
5067 sm->ap_rsnxe = os_memdup(ie, len);
5068 if (!sm->ap_rsnxe)
5069 return -1;
5070
5071 sm->ap_rsnxe_len = len;
5072 }
5073
5074 return 0;
5075}
5076
5077
5078/**
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005079 * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE
5080 * @sm: Pointer to WPA state machine data from wpa_sm_init()
5081 * @data: Pointer to data area for parsing results
5082 * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure
5083 *
5084 * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the
5085 * parsed data into data.
5086 */
5087int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data)
5088{
5089 if (sm == NULL)
5090 return -1;
5091
5092 if (sm->assoc_wpa_ie == NULL) {
5093 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
5094 "WPA: No WPA/RSN IE available from association info");
5095 return -1;
5096 }
5097 if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data))
5098 return -2;
5099 return 0;
5100}
5101
5102
5103int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
5104{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005105 return pmksa_cache_list(sm->pmksa, buf, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005106}
5107
5108
Dmitry Shmidt29333592017-01-09 12:27:11 -08005109struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_head(struct wpa_sm *sm)
5110{
5111 return pmksa_cache_head(sm->pmksa);
5112}
5113
5114
5115struct rsn_pmksa_cache_entry *
5116wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm,
5117 struct rsn_pmksa_cache_entry * entry)
5118{
5119 return pmksa_cache_add_entry(sm->pmksa, entry);
5120}
5121
5122
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005123void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
5124 const u8 *pmkid, const u8 *bssid,
5125 const u8 *fils_cache_id)
5126{
5127 sm->cur_pmksa = pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0,
5128 bssid, sm->own_addr, sm->network_ctx,
5129 sm->key_mgmt, fils_cache_id);
5130}
5131
5132
Sunil Ravi77d572f2023-01-17 23:58:31 +00005133int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, const u8 *own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005134 const void *network_ctx)
5135{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005136 return pmksa_cache_get(sm->pmksa, bssid, own_addr, NULL, network_ctx,
5137 0) != NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005138}
5139
5140
Hai Shalom60840252021-02-19 19:02:11 -08005141struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_get(struct wpa_sm *sm,
5142 const u8 *aa,
5143 const u8 *pmkid,
5144 const void *network_ctx,
5145 int akmp)
5146{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005147 return pmksa_cache_get(sm->pmksa, aa, sm->own_addr, pmkid, network_ctx,
5148 akmp);
5149}
5150
5151
5152void wpa_sm_pmksa_cache_remove(struct wpa_sm *sm,
5153 struct rsn_pmksa_cache_entry *entry)
5154{
5155 if (sm && sm->pmksa)
5156 pmksa_cache_remove(sm->pmksa, entry);
Hai Shalom60840252021-02-19 19:02:11 -08005157}
5158
5159
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005160void wpa_sm_drop_sa(struct wpa_sm *sm)
5161{
5162 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
Sunil Ravi77d572f2023-01-17 23:58:31 +00005163 wpa_sm_clear_ptk(sm);
Roshan Pius3a1667e2018-07-03 15:17:14 -07005164 sm->pmk_len = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005165 os_memset(sm->pmk, 0, sizeof(sm->pmk));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005166#ifdef CONFIG_IEEE80211R
5167 os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
Roshan Pius3a1667e2018-07-03 15:17:14 -07005168 sm->xxkey_len = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005169 os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07005170 sm->pmk_r0_len = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005171 os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1));
Roshan Pius3a1667e2018-07-03 15:17:14 -07005172 sm->pmk_r1_len = 0;
Hai Shalom60840252021-02-19 19:02:11 -08005173#ifdef CONFIG_PASN
5174 os_free(sm->pasn_r1kh);
5175 sm->pasn_r1kh = NULL;
5176 sm->n_pasn_r1kh = 0;
5177#endif /* CONFIG_PASN */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005178#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005179}
5180
5181
Sunil Ravi77d572f2023-01-17 23:58:31 +00005182#ifdef CONFIG_IEEE80211R
5183bool wpa_sm_has_ft_keys(struct wpa_sm *sm, const u8 *md)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005184{
Sunil Ravi77d572f2023-01-17 23:58:31 +00005185 if (!sm)
5186 return false;
5187 if (!wpa_key_mgmt_ft(sm->key_mgmt) ||
5188 os_memcmp(md, sm->key_mobility_domain,
5189 MOBILITY_DOMAIN_ID_LEN) != 0) {
5190 /* Do not allow FT protocol to be used even if we were to have
5191 * an PTK since the mobility domain has changed. */
5192 return false;
5193 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005194 return sm->ptk_set;
5195}
Sunil Ravi77d572f2023-01-17 23:58:31 +00005196#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005197
5198
Hai Shalomfdcde762020-04-02 11:19:20 -07005199int wpa_sm_has_ptk_installed(struct wpa_sm *sm)
5200{
5201 if (!sm)
5202 return 0;
Sunil8cd6f4d2022-06-28 18:40:46 +00005203 return sm->tk_set || sm->ptk.installed;
Hai Shalomfdcde762020-04-02 11:19:20 -07005204}
5205
5206
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005207void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr)
5208{
5209 os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN);
5210}
5211
5212
5213void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
5214{
Hai Shalomc1a21442022-02-04 13:43:00 -08005215 pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0, false);
5216}
5217
5218
5219void wpa_sm_external_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx)
5220{
5221 pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0, true);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005222}
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005223
Andy Kuoaba17c12022-04-14 16:05:31 +08005224#if defined(CONFIG_DRIVER_NL80211_BRCM) || defined(CONFIG_DRIVER_NL80211_SYNA)
Mir Ali677e7482020-11-12 19:49:02 +05305225void wpa_sm_install_pmk(struct wpa_sm *sm)
5226{
5227 /* In case the driver wants to handle re-assocs, pass it down the PMK. */
Sunil Ravi77d572f2023-01-17 23:58:31 +00005228 if (wpa_sm_set_key(sm, -1, wpa_cipher_to_alg(sm->pairwise_cipher), NULL, 0, 0, NULL, 0,
Mir Ali677e7482020-11-12 19:49:02 +05305229 (u8*)sm->pmk, sm->pmk_len, KEY_FLAG_PMK) < 0) {
5230 wpa_hexdump(MSG_DEBUG, "PSK: Install PMK to the driver for driver reassociations",
5231 (u8*)sm->pmk, sm->pmk_len);
5232 /* No harm if the driver doesn't support. */
5233 wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG,
5234 "WPA: Failed to set PMK to the driver");
5235 }
5236}
Mir Alieaaf04e2021-06-07 12:17:29 +05305237
5238void wpa_sm_notify_brcm_ft_reassoc(struct wpa_sm *sm, const u8 *bssid)
5239{
5240 u8 buf[256];
5241 struct wpa_supplicant *wpa_s = sm->ctx->ctx;
5242
5243 wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
5244 "WPA: BRCM FT Reassociation event - clear replay counter");
5245 os_memcpy(sm->bssid, bssid, ETH_ALEN);
5246 os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN);
5247 sm->rx_replay_counter_set = 0;
5248
5249 if (wpa_drv_driver_cmd(wpa_s, "GET_FTKEY", (char *)buf, sizeof(buf)) < 0) {
5250 wpa_msg(sm->ctx->msg_ctx, MSG_ERROR,
5251 "WPA: Failed to get FT KEY information");
5252 wpa_supplicant_deauthenticate(
5253 wpa_s, WLAN_REASON_DEAUTH_LEAVING);
5254
5255 } else {
5256 /* update kck and kek */
5257 os_memcpy(sm->ptk.kck, buf, 16);
5258 os_memcpy(sm->ptk.kek, buf + 16, 16);
5259 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
5260 "WPA: Updated KCK and KEK after FT reassoc");
5261 }
5262}
Andy Kuoaba17c12022-04-14 16:05:31 +08005263#endif /* CONFIG_DRIVER_NL80211_BRCM || CONFIG_DRIVER_NL80211_SYNA */
5264
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005265
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005266#ifdef CONFIG_WNM
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005267int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
5268{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005269 u16 keyinfo;
5270 u8 keylen; /* plaintext key len */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005271 u8 *key_rsc;
5272
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005273 if (subelem_id == WNM_SLEEP_SUBELEM_GTK) {
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005274 struct wpa_gtk_data gd;
5275
5276 os_memset(&gd, 0, sizeof(gd));
5277 keylen = wpa_cipher_key_len(sm->group_cipher);
5278 gd.key_rsc_len = wpa_cipher_rsc_len(sm->group_cipher);
5279 gd.alg = wpa_cipher_to_alg(sm->group_cipher);
5280 if (gd.alg == WPA_ALG_NONE) {
5281 wpa_printf(MSG_DEBUG, "Unsupported group cipher suite");
5282 return -1;
5283 }
5284
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005285 key_rsc = buf + 5;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005286 keyinfo = WPA_GET_LE16(buf + 2);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005287 gd.gtk_len = keylen;
5288 if (gd.gtk_len != buf[4]) {
5289 wpa_printf(MSG_DEBUG, "GTK len mismatch len %d vs %d",
5290 gd.gtk_len, buf[4]);
5291 return -1;
5292 }
5293 gd.keyidx = keyinfo & 0x03; /* B0 - B1 */
5294 gd.tx = wpa_supplicant_gtk_tx_bit_workaround(
5295 sm, !!(keyinfo & WPA_KEY_INFO_TXRX));
5296
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005297 os_memcpy(gd.gtk, buf + 13, gd.gtk_len);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005298
5299 wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
5300 gd.gtk, gd.gtk_len);
Jouni Malinen58c0e962017-10-01 12:12:24 +03005301 if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 1)) {
Hai Shalom81f62d82019-07-22 12:10:00 -07005302 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005303 wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
5304 "WNM mode");
5305 return -1;
5306 }
Hai Shalom81f62d82019-07-22 12:10:00 -07005307 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005308 } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02005309 const struct wpa_igtk_kde *igtk;
Dmitry Shmidt61593f02014-04-21 16:27:35 -07005310
Mathy Vanhoef10bfd642017-07-12 16:03:24 +02005311 igtk = (const struct wpa_igtk_kde *) (buf + 2);
Jouni Malinen58c0e962017-10-01 12:12:24 +03005312 if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0)
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005313 return -1;
Hai Shalomfdcde762020-04-02 11:19:20 -07005314 } else if (subelem_id == WNM_SLEEP_SUBELEM_BIGTK) {
5315 const struct wpa_bigtk_kde *bigtk;
5316
5317 bigtk = (const struct wpa_bigtk_kde *) (buf + 2);
5318 if (sm->beacon_prot &&
5319 wpa_supplicant_install_bigtk(sm, bigtk, 1) < 0)
5320 return -1;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07005321 } else {
5322 wpa_printf(MSG_DEBUG, "Unknown element id");
5323 return -1;
5324 }
5325
5326 return 0;
5327}
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08005328#endif /* CONFIG_WNM */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005329
5330
Dmitry Shmidtcf32e602014-01-28 10:57:39 -08005331#ifdef CONFIG_P2P
5332
5333int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf)
5334{
5335 if (sm == NULL || WPA_GET_BE32(sm->p2p_ip_addr) == 0)
5336 return -1;
5337 os_memcpy(buf, sm->p2p_ip_addr, 3 * 4);
5338 return 0;
5339}
5340
5341#endif /* CONFIG_P2P */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005342
5343
5344void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter)
5345{
5346 if (rx_replay_counter == NULL)
5347 return;
5348
5349 os_memcpy(sm->rx_replay_counter, rx_replay_counter,
5350 WPA_REPLAY_COUNTER_LEN);
5351 sm->rx_replay_counter_set = 1;
5352 wpa_printf(MSG_DEBUG, "Updated key replay counter");
5353}
5354
5355
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005356void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm,
5357 const u8 *ptk_kck, size_t ptk_kck_len,
5358 const u8 *ptk_kek, size_t ptk_kek_len)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005359{
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005360 if (ptk_kck && ptk_kck_len <= WPA_KCK_MAX_LEN) {
5361 os_memcpy(sm->ptk.kck, ptk_kck, ptk_kck_len);
5362 sm->ptk.kck_len = ptk_kck_len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005363 wpa_printf(MSG_DEBUG, "Updated PTK KCK");
5364 }
Dmitry Shmidt807291d2015-01-27 13:40:23 -08005365 if (ptk_kek && ptk_kek_len <= WPA_KEK_MAX_LEN) {
5366 os_memcpy(sm->ptk.kek, ptk_kek, ptk_kek_len);
5367 sm->ptk.kek_len = ptk_kek_len;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08005368 wpa_printf(MSG_DEBUG, "Updated PTK KEK");
5369 }
5370 sm->ptk_set = 1;
5371}
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005372
5373
5374#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005375
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005376void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf)
5377{
5378 wpabuf_free(sm->test_assoc_ie);
5379 sm->test_assoc_ie = buf;
5380}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005381
5382
Sunil Ravib0ac25f2024-07-12 01:42:03 +00005383void wpa_sm_set_test_eapol_m2_elems(struct wpa_sm *sm, struct wpabuf *buf)
5384{
5385 wpabuf_free(sm->test_eapol_m2_elems);
5386 sm->test_eapol_m2_elems = buf;
5387}
5388
5389
5390void wpa_sm_set_test_eapol_m4_elems(struct wpa_sm *sm, struct wpabuf *buf)
5391{
5392 wpabuf_free(sm->test_eapol_m4_elems);
5393 sm->test_eapol_m4_elems = buf;
5394}
5395
5396
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005397const u8 * wpa_sm_get_anonce(struct wpa_sm *sm)
5398{
5399 return sm->anonce;
5400}
5401
Dmitry Shmidt55840ad2015-12-14 12:45:46 -08005402#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005403
5404
Roshan Pius3a1667e2018-07-03 15:17:14 -07005405unsigned int wpa_sm_get_key_mgmt(struct wpa_sm *sm)
5406{
5407 return sm->key_mgmt;
5408}
5409
5410
Sunil Ravi77d572f2023-01-17 23:58:31 +00005411const u8 * wpa_sm_get_auth_addr(struct wpa_sm *sm)
5412{
5413 return sm->mlo.valid_links ? sm->mlo.ap_mld_addr : sm->bssid;
5414}
5415
5416
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005417#ifdef CONFIG_FILS
5418
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005419struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005420{
5421 struct wpabuf *buf = NULL;
5422 struct wpabuf *erp_msg;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005423 struct wpabuf *pub = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005424
5425 erp_msg = eapol_sm_build_erp_reauth_start(sm->eapol);
5426 if (!erp_msg && !sm->cur_pmksa) {
5427 wpa_printf(MSG_DEBUG,
5428 "FILS: Neither ERP EAP-Initiate/Re-auth nor PMKSA cache entry is available - skip FILS");
5429 goto fail;
5430 }
5431
5432 wpa_printf(MSG_DEBUG, "FILS: Try to use FILS (erp=%d pmksa_cache=%d)",
5433 erp_msg != NULL, sm->cur_pmksa != NULL);
5434
5435 sm->fils_completed = 0;
5436
5437 if (!sm->assoc_wpa_ie) {
5438 wpa_printf(MSG_INFO, "FILS: No own RSN IE set for FILS");
5439 goto fail;
5440 }
5441
5442 if (random_get_bytes(sm->fils_nonce, FILS_NONCE_LEN) < 0 ||
5443 random_get_bytes(sm->fils_session, FILS_SESSION_LEN) < 0)
5444 goto fail;
5445
5446 wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Nonce",
5447 sm->fils_nonce, FILS_NONCE_LEN);
5448 wpa_hexdump(MSG_DEBUG, "FILS: Generated FILS Session",
5449 sm->fils_session, FILS_SESSION_LEN);
5450
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005451#ifdef CONFIG_FILS_SK_PFS
5452 sm->fils_dh_group = dh_group;
5453 if (dh_group) {
5454 crypto_ecdh_deinit(sm->fils_ecdh);
5455 sm->fils_ecdh = crypto_ecdh_init(dh_group);
5456 if (!sm->fils_ecdh) {
5457 wpa_printf(MSG_INFO,
5458 "FILS: Could not initialize ECDH with group %d",
5459 dh_group);
5460 goto fail;
5461 }
5462 pub = crypto_ecdh_get_pubkey(sm->fils_ecdh, 1);
5463 if (!pub)
5464 goto fail;
5465 wpa_hexdump_buf(MSG_DEBUG, "FILS: Element (DH public key)",
5466 pub);
5467 sm->fils_dh_elem_len = wpabuf_len(pub);
5468 }
5469#endif /* CONFIG_FILS_SK_PFS */
5470
5471 buf = wpabuf_alloc(1000 + sm->assoc_wpa_ie_len +
5472 (pub ? wpabuf_len(pub) : 0));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005473 if (!buf)
5474 goto fail;
5475
5476 /* Fields following the Authentication algorithm number field */
5477
5478 /* Authentication Transaction seq# */
5479 wpabuf_put_le16(buf, 1);
5480
5481 /* Status Code */
5482 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
5483
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005484 /* TODO: FILS PK */
5485#ifdef CONFIG_FILS_SK_PFS
5486 if (dh_group) {
5487 /* Finite Cyclic Group */
5488 wpabuf_put_le16(buf, dh_group);
5489 /* Element */
5490 wpabuf_put_buf(buf, pub);
5491 }
5492#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005493
5494 /* RSNE */
5495 wpa_hexdump(MSG_DEBUG, "FILS: RSNE in FILS Authentication frame",
5496 sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
5497 wpabuf_put_data(buf, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
5498
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005499 if (md) {
5500 /* MDE when using FILS for FT initial association */
5501 struct rsn_mdie *mdie;
5502
5503 wpabuf_put_u8(buf, WLAN_EID_MOBILITY_DOMAIN);
5504 wpabuf_put_u8(buf, sizeof(*mdie));
5505 mdie = wpabuf_put(buf, sizeof(*mdie));
5506 os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
5507 mdie->ft_capab = 0;
5508 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005509
5510 /* FILS Nonce */
5511 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
5512 wpabuf_put_u8(buf, 1 + FILS_NONCE_LEN); /* Length */
5513 /* Element ID Extension */
5514 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_NONCE);
5515 wpabuf_put_data(buf, sm->fils_nonce, FILS_NONCE_LEN);
5516
5517 /* FILS Session */
5518 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
5519 wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */
5520 /* Element ID Extension */
5521 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
5522 wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
5523
Hai Shalomfdcde762020-04-02 11:19:20 -07005524 /* Wrapped Data */
Paul Stewart092955c2017-02-06 09:13:09 -08005525 sm->fils_erp_pmkid_set = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005526 if (erp_msg) {
5527 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
5528 wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg)); /* Length */
5529 /* Element ID Extension */
Hai Shalomfdcde762020-04-02 11:19:20 -07005530 wpabuf_put_u8(buf, WLAN_EID_EXT_WRAPPED_DATA);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005531 wpabuf_put_buf(buf, erp_msg);
Paul Stewart092955c2017-02-06 09:13:09 -08005532 /* Calculate pending PMKID here so that we do not need to
5533 * maintain a copy of the EAP-Initiate/Reauth message. */
5534 if (fils_pmkid_erp(sm->key_mgmt, wpabuf_head(erp_msg),
5535 wpabuf_len(erp_msg),
5536 sm->fils_erp_pmkid) == 0)
5537 sm->fils_erp_pmkid_set = 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005538 }
5539
5540 wpa_hexdump_buf(MSG_DEBUG, "RSN: FILS fields for Authentication frame",
5541 buf);
5542
5543fail:
5544 wpabuf_free(erp_msg);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005545 wpabuf_free(pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005546 return buf;
5547}
5548
5549
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005550int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
5551 size_t len)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005552{
5553 const u8 *pos, *end;
5554 struct ieee802_11_elems elems;
5555 struct wpa_ie_data rsn;
5556 int pmkid_match = 0;
5557 u8 ick[FILS_ICK_MAX_LEN];
5558 size_t ick_len;
5559 int res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005560 struct wpabuf *dh_ss = NULL;
5561 const u8 *g_sta = NULL;
5562 size_t g_sta_len = 0;
5563 const u8 *g_ap = NULL;
Hai Shalom60840252021-02-19 19:02:11 -08005564 size_t g_ap_len = 0, kdk_len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005565 struct wpabuf *pub = NULL;
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005566#ifdef CONFIG_IEEE80211R
5567 struct wpa_ft_ies parse;
5568
5569 os_memset(&parse, 0, sizeof(parse));
5570#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005571
5572 os_memcpy(sm->bssid, bssid, ETH_ALEN);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005573
5574 wpa_hexdump(MSG_DEBUG, "FILS: Authentication frame fields",
5575 data, len);
5576 pos = data;
5577 end = data + len;
5578
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005579 /* TODO: FILS PK */
5580#ifdef CONFIG_FILS_SK_PFS
5581 if (sm->fils_dh_group) {
5582 u16 group;
5583
5584 /* Using FILS PFS */
5585
5586 /* Finite Cyclic Group */
5587 if (end - pos < 2) {
5588 wpa_printf(MSG_DEBUG,
5589 "FILS: No room for Finite Cyclic Group");
5590 goto fail;
5591 }
5592 group = WPA_GET_LE16(pos);
5593 pos += 2;
5594 if (group != sm->fils_dh_group) {
5595 wpa_printf(MSG_DEBUG,
5596 "FILS: Unexpected change in Finite Cyclic Group: %u (expected %u)",
5597 group, sm->fils_dh_group);
5598 goto fail;
5599 }
5600
5601 /* Element */
5602 if ((size_t) (end - pos) < sm->fils_dh_elem_len) {
5603 wpa_printf(MSG_DEBUG, "FILS: No room for Element");
5604 goto fail;
5605 }
5606
5607 if (!sm->fils_ecdh) {
5608 wpa_printf(MSG_DEBUG, "FILS: No ECDH state available");
5609 goto fail;
5610 }
5611 dh_ss = crypto_ecdh_set_peerkey(sm->fils_ecdh, 1, pos,
5612 sm->fils_dh_elem_len);
5613 if (!dh_ss) {
5614 wpa_printf(MSG_DEBUG, "FILS: ECDH operation failed");
5615 goto fail;
5616 }
5617 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: DH_SS", dh_ss);
5618 g_ap = pos;
5619 g_ap_len = sm->fils_dh_elem_len;
5620 pos += sm->fils_dh_elem_len;
5621 }
5622#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005623
5624 wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
5625 if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
5626 wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005627 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005628 }
5629
5630 /* RSNE */
5631 wpa_hexdump(MSG_DEBUG, "FILS: RSN element", elems.rsn_ie,
5632 elems.rsn_ie_len);
5633 if (!elems.rsn_ie ||
5634 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
5635 &rsn) < 0) {
5636 wpa_printf(MSG_DEBUG, "FILS: No RSN element");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005637 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005638 }
5639
5640 if (!elems.fils_nonce) {
5641 wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005642 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005643 }
5644 os_memcpy(sm->fils_anonce, elems.fils_nonce, FILS_NONCE_LEN);
5645 wpa_hexdump(MSG_DEBUG, "FILS: ANonce", sm->fils_anonce, FILS_NONCE_LEN);
5646
Roshan Pius3a1667e2018-07-03 15:17:14 -07005647#ifdef CONFIG_IEEE80211R
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005648 if (wpa_key_mgmt_ft(sm->key_mgmt)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005649 if (!elems.mdie || !elems.ftie) {
5650 wpa_printf(MSG_DEBUG, "FILS+FT: No MDE or FTE");
5651 goto fail;
5652 }
5653
Roshan Pius3a1667e2018-07-03 15:17:14 -07005654 if (wpa_ft_parse_ies(pos, end - pos, &parse,
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005655 sm->key_mgmt, false) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005656 wpa_printf(MSG_DEBUG, "FILS+FT: Failed to parse IEs");
5657 goto fail;
5658 }
5659
5660 if (!parse.r0kh_id) {
5661 wpa_printf(MSG_DEBUG,
5662 "FILS+FT: No R0KH-ID subelem in FTE");
5663 goto fail;
5664 }
5665 os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len);
5666 sm->r0kh_id_len = parse.r0kh_id_len;
5667 wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: R0KH-ID",
5668 sm->r0kh_id, sm->r0kh_id_len);
5669
5670 if (!parse.r1kh_id) {
5671 wpa_printf(MSG_DEBUG,
5672 "FILS+FT: No R1KH-ID subelem in FTE");
5673 goto fail;
5674 }
5675 os_memcpy(sm->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN);
5676 wpa_hexdump(MSG_DEBUG, "FILS+FT: R1KH-ID",
5677 sm->r1kh_id, FT_R1KH_ID_LEN);
5678
5679 /* TODO: Check MDE and FTE payload */
5680
5681 wpabuf_free(sm->fils_ft_ies);
5682 sm->fils_ft_ies = wpabuf_alloc(2 + elems.mdie_len +
5683 2 + elems.ftie_len);
5684 if (!sm->fils_ft_ies)
5685 goto fail;
5686 wpabuf_put_data(sm->fils_ft_ies, elems.mdie - 2,
5687 2 + elems.mdie_len);
5688 wpabuf_put_data(sm->fils_ft_ies, elems.ftie - 2,
5689 2 + elems.ftie_len);
5690 } else {
5691 wpabuf_free(sm->fils_ft_ies);
5692 sm->fils_ft_ies = NULL;
5693 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07005694#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005695
5696 /* PMKID List */
5697 if (rsn.pmkid && rsn.num_pmkid > 0) {
5698 wpa_hexdump(MSG_DEBUG, "FILS: PMKID List",
5699 rsn.pmkid, rsn.num_pmkid * PMKID_LEN);
5700
5701 if (rsn.num_pmkid != 1) {
5702 wpa_printf(MSG_DEBUG, "FILS: Invalid PMKID selection");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005703 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005704 }
5705 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", rsn.pmkid, PMKID_LEN);
5706 if (os_memcmp(sm->cur_pmksa->pmkid, rsn.pmkid, PMKID_LEN) != 0)
5707 {
5708 wpa_printf(MSG_DEBUG, "FILS: PMKID mismatch");
5709 wpa_hexdump(MSG_DEBUG, "FILS: Expected PMKID",
5710 sm->cur_pmksa->pmkid, PMKID_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005711 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005712 }
5713 wpa_printf(MSG_DEBUG,
5714 "FILS: Matching PMKID - continue using PMKSA caching");
5715 pmkid_match = 1;
5716 }
5717 if (!pmkid_match && sm->cur_pmksa) {
5718 wpa_printf(MSG_DEBUG,
5719 "FILS: No PMKID match - cannot use cached PMKSA entry");
5720 sm->cur_pmksa = NULL;
5721 }
5722
5723 /* FILS Session */
5724 if (!elems.fils_session) {
5725 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005726 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005727 }
5728 wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
5729 FILS_SESSION_LEN);
5730 if (os_memcmp(sm->fils_session, elems.fils_session, FILS_SESSION_LEN)
5731 != 0) {
5732 wpa_printf(MSG_DEBUG, "FILS: Session mismatch");
5733 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
5734 sm->fils_session, FILS_SESSION_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005735 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005736 }
5737
Hai Shalomfdcde762020-04-02 11:19:20 -07005738 /* Wrapped Data */
5739 if (!sm->cur_pmksa && elems.wrapped_data) {
Paul Stewart092955c2017-02-06 09:13:09 -08005740 u8 rmsk[ERP_MAX_KEY_LEN];
5741 size_t rmsk_len;
5742
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005743 wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
Hai Shalomfdcde762020-04-02 11:19:20 -07005744 elems.wrapped_data,
5745 elems.wrapped_data_len);
5746 eapol_sm_process_erp_finish(sm->eapol, elems.wrapped_data,
5747 elems.wrapped_data_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005748 if (eapol_sm_failed(sm->eapol))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005749 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005750
Paul Stewart092955c2017-02-06 09:13:09 -08005751 rmsk_len = ERP_MAX_KEY_LEN;
5752 res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
5753 if (res == PMK_LEN) {
5754 rmsk_len = PMK_LEN;
5755 res = eapol_sm_get_key(sm->eapol, rmsk, rmsk_len);
5756 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005757 if (res)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005758 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005759
Paul Stewart092955c2017-02-06 09:13:09 -08005760 res = fils_rmsk_to_pmk(sm->key_mgmt, rmsk, rmsk_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005761 sm->fils_nonce, sm->fils_anonce,
5762 dh_ss ? wpabuf_head(dh_ss) : NULL,
5763 dh_ss ? wpabuf_len(dh_ss) : 0,
Paul Stewart092955c2017-02-06 09:13:09 -08005764 sm->pmk, &sm->pmk_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07005765 forced_memzero(rmsk, sizeof(rmsk));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005766
5767 /* Don't use DHss in PTK derivation if PMKSA caching is not
5768 * used. */
5769 wpabuf_clear_free(dh_ss);
5770 dh_ss = NULL;
5771
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08005772 if (res)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005773 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08005774
5775 if (!sm->fils_erp_pmkid_set) {
5776 wpa_printf(MSG_DEBUG, "FILS: PMKID not available");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005777 goto fail;
Paul Stewart092955c2017-02-06 09:13:09 -08005778 }
5779 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", sm->fils_erp_pmkid,
5780 PMKID_LEN);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005781 wpa_printf(MSG_DEBUG, "FILS: ERP processing succeeded - add PMKSA cache entry for the result");
Paul Stewart092955c2017-02-06 09:13:09 -08005782 sm->cur_pmksa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len,
5783 sm->fils_erp_pmkid, NULL, 0,
5784 sm->bssid, sm->own_addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005785 sm->network_ctx, sm->key_mgmt,
5786 NULL);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005787 }
5788
5789 if (!sm->cur_pmksa) {
5790 wpa_printf(MSG_DEBUG,
5791 "FILS: No remaining options to continue FILS authentication");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005792 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005793 }
5794
Hai Shalom60840252021-02-19 19:02:11 -08005795 if (sm->force_kdk_derivation ||
Hai Shalomc1a21442022-02-04 13:43:00 -08005796 (sm->secure_ltf &&
5797 ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF)))
Hai Shalom60840252021-02-19 19:02:11 -08005798 kdk_len = WPA_KDK_MAX_LEN;
5799 else
5800 kdk_len = 0;
5801
Sunil Ravi77d572f2023-01-17 23:58:31 +00005802 if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr,
5803 wpa_sm_get_auth_addr(sm),
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005804 sm->fils_nonce, sm->fils_anonce,
5805 dh_ss ? wpabuf_head(dh_ss) : NULL,
5806 dh_ss ? wpabuf_len(dh_ss) : 0,
5807 &sm->ptk, ick, &ick_len,
5808 sm->key_mgmt, sm->pairwise_cipher,
Hai Shalom60840252021-02-19 19:02:11 -08005809 sm->fils_ft, &sm->fils_ft_len,
5810 kdk_len) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005811 wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005812 goto fail;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005813 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005814
Sunil Ravi89eba102022-09-13 21:04:37 -07005815#ifdef CONFIG_PASN
5816 if (sm->secure_ltf &&
5817 ieee802_11_rsnx_capab(sm->ap_rsnxe, WLAN_RSNX_CAPAB_SECURE_LTF) &&
5818 wpa_ltf_keyseed(&sm->ptk, sm->key_mgmt, sm->pairwise_cipher)) {
5819 wpa_printf(MSG_DEBUG, "FILS: Failed to derive LTF keyseed");
5820 goto fail;
5821 }
5822#endif /* CONFIG_PASN */
5823
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005824 wpabuf_clear_free(dh_ss);
5825 dh_ss = NULL;
5826
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005827 sm->ptk_set = 1;
5828 sm->tptk_set = 0;
5829 os_memset(&sm->tptk, 0, sizeof(sm->tptk));
5830
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005831#ifdef CONFIG_FILS_SK_PFS
5832 if (sm->fils_dh_group) {
5833 if (!sm->fils_ecdh) {
5834 wpa_printf(MSG_INFO, "FILS: ECDH not initialized");
5835 goto fail;
5836 }
5837 pub = crypto_ecdh_get_pubkey(sm->fils_ecdh, 1);
5838 if (!pub)
5839 goto fail;
5840 wpa_hexdump_buf(MSG_DEBUG, "FILS: gSTA", pub);
5841 g_sta = wpabuf_head(pub);
5842 g_sta_len = wpabuf_len(pub);
5843 if (!g_ap) {
5844 wpa_printf(MSG_INFO, "FILS: gAP not available");
5845 goto fail;
5846 }
5847 wpa_hexdump(MSG_DEBUG, "FILS: gAP", g_ap, g_ap_len);
5848 }
5849#endif /* CONFIG_FILS_SK_PFS */
5850
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005851 res = fils_key_auth_sk(ick, ick_len, sm->fils_nonce,
5852 sm->fils_anonce, sm->own_addr, sm->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005853 g_sta, g_sta_len, g_ap, g_ap_len,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005854 sm->key_mgmt, sm->fils_key_auth_sta,
5855 sm->fils_key_auth_ap,
5856 &sm->fils_key_auth_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005857 wpabuf_free(pub);
Hai Shalom81f62d82019-07-22 12:10:00 -07005858 forced_memzero(ick, sizeof(ick));
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005859#ifdef CONFIG_IEEE80211R
5860 wpa_ft_parse_ies_free(&parse);
5861#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005862 return res;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005863fail:
5864 wpabuf_free(pub);
5865 wpabuf_clear_free(dh_ss);
Sunil Ravi2a14cf12023-11-21 00:54:38 +00005866#ifdef CONFIG_IEEE80211R
5867 wpa_ft_parse_ies_free(&parse);
5868#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005869 return -1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005870}
5871
5872
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005873#ifdef CONFIG_IEEE80211R
5874static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf)
5875{
5876 struct rsn_ie_hdr *rsnie;
5877 u16 capab;
5878 u8 *pos;
Roshan Pius3a1667e2018-07-03 15:17:14 -07005879 int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005880
5881 /* RSNIE[PMKR0Name/PMKR1Name] */
5882 rsnie = wpabuf_put(buf, sizeof(*rsnie));
5883 rsnie->elem_id = WLAN_EID_RSN;
5884 WPA_PUT_LE16(rsnie->version, RSN_VERSION);
5885
5886 /* Group Suite Selector */
5887 if (!wpa_cipher_valid_group(sm->group_cipher)) {
5888 wpa_printf(MSG_WARNING, "FT: Invalid group cipher (%d)",
5889 sm->group_cipher);
5890 return -1;
5891 }
5892 pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
5893 RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
5894 sm->group_cipher));
5895
5896 /* Pairwise Suite Count */
5897 wpabuf_put_le16(buf, 1);
5898
5899 /* Pairwise Suite List */
5900 if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) {
5901 wpa_printf(MSG_WARNING, "FT: Invalid pairwise cipher (%d)",
5902 sm->pairwise_cipher);
5903 return -1;
5904 }
5905 pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
5906 RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
5907 sm->pairwise_cipher));
5908
5909 /* Authenticated Key Management Suite Count */
5910 wpabuf_put_le16(buf, 1);
5911
5912 /* Authenticated Key Management Suite List */
5913 pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
5914 if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256)
5915 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256);
5916 else if (sm->key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384)
5917 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384);
5918 else {
5919 wpa_printf(MSG_WARNING,
5920 "FILS+FT: Invalid key management type (%d)",
5921 sm->key_mgmt);
5922 return -1;
5923 }
5924
5925 /* RSN Capabilities */
5926 capab = 0;
Hai Shalomc3565922019-10-28 11:58:20 -07005927 if (sm->mfp)
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005928 capab |= WPA_CAPABILITY_MFPC;
Hai Shalomc3565922019-10-28 11:58:20 -07005929 if (sm->mfp == 2)
5930 capab |= WPA_CAPABILITY_MFPR;
Hai Shalom74f70d42019-02-11 14:42:39 -08005931 if (sm->ocv)
5932 capab |= WPA_CAPABILITY_OCVC;
Hai Shalomfdcde762020-04-02 11:19:20 -07005933 if (sm->ext_key_id)
5934 capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005935 wpabuf_put_le16(buf, capab);
5936
5937 /* PMKID Count */
5938 wpabuf_put_le16(buf, 1);
5939
5940 /* PMKID List [PMKR1Name] */
5941 wpa_hexdump_key(MSG_DEBUG, "FILS+FT: XXKey (FILS-FT)",
5942 sm->fils_ft, sm->fils_ft_len);
5943 wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: SSID", sm->ssid, sm->ssid_len);
5944 wpa_hexdump(MSG_DEBUG, "FILS+FT: MDID",
5945 sm->mobility_domain, MOBILITY_DOMAIN_ID_LEN);
5946 wpa_hexdump_ascii(MSG_DEBUG, "FILS+FT: R0KH-ID",
5947 sm->r0kh_id, sm->r0kh_id_len);
5948 if (wpa_derive_pmk_r0(sm->fils_ft, sm->fils_ft_len, sm->ssid,
5949 sm->ssid_len, sm->mobility_domain,
5950 sm->r0kh_id, sm->r0kh_id_len, sm->own_addr,
Sunil Ravi77d572f2023-01-17 23:58:31 +00005951 sm->pmk_r0, sm->pmk_r0_name, sm->key_mgmt) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005952 wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMK-R0");
5953 return -1;
5954 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00005955 if (wpa_key_mgmt_sae_ext_key(sm->key_mgmt))
5956 sm->pmk_r0_len = sm->fils_ft_len;
5957 else
5958 sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005959 wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR,
5960 MAC2STR(sm->r1kh_id));
5961 pos = wpabuf_put(buf, WPA_PMK_NAME_LEN);
5962 if (wpa_derive_pmk_r1_name(sm->pmk_r0_name, sm->r1kh_id, sm->own_addr,
Sunil Ravi77d572f2023-01-17 23:58:31 +00005963 sm->pmk_r1_name, sm->fils_ft_len) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005964 wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMKR1Name");
5965 return -1;
5966 }
Hai Shalom021b0b52019-04-10 11:17:58 -07005967 os_memcpy(pos, sm->pmk_r1_name, WPA_PMK_NAME_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005968
Sunil Ravi77d572f2023-01-17 23:58:31 +00005969 os_memcpy(sm->key_mobility_domain, sm->mobility_domain,
5970 MOBILITY_DOMAIN_ID_LEN);
5971
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005972 if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
5973 /* Management Group Cipher Suite */
5974 pos = wpabuf_put(buf, RSN_SELECTOR_LEN);
5975 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
5976 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005977
5978 rsnie->len = ((u8 *) wpabuf_put(buf, 0) - (u8 *) rsnie) - 2;
5979 return 0;
5980}
5981#endif /* CONFIG_IEEE80211R */
5982
5983
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005984struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
5985 size_t *kek_len, const u8 **snonce,
Paul Stewart092955c2017-02-06 09:13:09 -08005986 const u8 **anonce,
5987 const struct wpabuf **hlp,
5988 unsigned int num_hlp)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005989{
5990 struct wpabuf *buf;
Paul Stewart092955c2017-02-06 09:13:09 -08005991 size_t len;
5992 unsigned int i;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005993
Paul Stewart092955c2017-02-06 09:13:09 -08005994 len = 1000;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005995#ifdef CONFIG_IEEE80211R
5996 if (sm->fils_ft_ies)
5997 len += wpabuf_len(sm->fils_ft_ies);
5998 if (wpa_key_mgmt_ft(sm->key_mgmt))
5999 len += 256;
6000#endif /* CONFIG_IEEE80211R */
Paul Stewart092955c2017-02-06 09:13:09 -08006001 for (i = 0; hlp && i < num_hlp; i++)
6002 len += 10 + wpabuf_len(hlp[i]);
6003 buf = wpabuf_alloc(len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006004 if (!buf)
6005 return NULL;
6006
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006007#ifdef CONFIG_IEEE80211R
6008 if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->fils_ft_ies) {
6009 /* MDE and FTE when using FILS+FT */
6010 wpabuf_put_buf(buf, sm->fils_ft_ies);
6011 /* RSNE with PMKR1Name in PMKID field */
6012 if (fils_ft_build_assoc_req_rsne(sm, buf) < 0) {
6013 wpabuf_free(buf);
6014 return NULL;
6015 }
6016 }
6017#endif /* CONFIG_IEEE80211R */
6018
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006019 /* FILS Session */
6020 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
6021 wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */
6022 /* Element ID Extension */
6023 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
6024 wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
6025
6026 /* Everything after FILS Session element gets encrypted in the driver
6027 * with KEK. The buffer returned from here is the plaintext version. */
6028
6029 /* TODO: FILS Public Key */
6030
6031 /* FILS Key Confirm */
6032 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
6033 wpabuf_put_u8(buf, 1 + sm->fils_key_auth_len); /* Length */
6034 /* Element ID Extension */
6035 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM);
6036 wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len);
6037
Paul Stewart092955c2017-02-06 09:13:09 -08006038 /* FILS HLP Container */
6039 for (i = 0; hlp && i < num_hlp; i++) {
6040 const u8 *pos = wpabuf_head(hlp[i]);
6041 size_t left = wpabuf_len(hlp[i]);
6042
6043 wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
6044 if (left <= 254)
6045 len = 1 + left;
6046 else
6047 len = 255;
6048 wpabuf_put_u8(buf, len); /* Length */
6049 /* Element ID Extension */
6050 wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_HLP_CONTAINER);
6051 /* Destination MAC Address, Source MAC Address, HLP Packet.
6052 * HLP Packet is in MSDU format (i.e., included the LLC/SNAP
6053 * header when LPD is used). */
6054 wpabuf_put_data(buf, pos, len - 1);
6055 pos += len - 1;
6056 left -= len - 1;
6057 while (left) {
6058 wpabuf_put_u8(buf, WLAN_EID_FRAGMENT);
6059 len = left > 255 ? 255 : left;
6060 wpabuf_put_u8(buf, len);
6061 wpabuf_put_data(buf, pos, len);
6062 pos += len;
6063 left -= len;
6064 }
6065 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006066
6067 /* TODO: FILS IP Address Assignment */
6068
Hai Shalom74f70d42019-02-11 14:42:39 -08006069#ifdef CONFIG_OCV
6070 if (wpa_sm_ocv_enabled(sm)) {
6071 struct wpa_channel_info ci;
6072 u8 *pos;
6073
6074 if (wpa_sm_channel_info(sm, &ci) != 0) {
6075 wpa_printf(MSG_WARNING,
6076 "FILS: Failed to get channel info for OCI element");
6077 wpabuf_free(buf);
6078 return NULL;
6079 }
Hai Shalom899fcc72020-10-19 14:38:18 -07006080#ifdef CONFIG_TESTING_OPTIONS
6081 if (sm->oci_freq_override_fils_assoc) {
6082 wpa_printf(MSG_INFO,
6083 "TEST: Override OCI KDE frequency %d -> %d MHz",
6084 ci.frequency,
6085 sm->oci_freq_override_fils_assoc);
6086 ci.frequency = sm->oci_freq_override_fils_assoc;
6087 }
6088#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalom74f70d42019-02-11 14:42:39 -08006089
6090 pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN);
6091 if (ocv_insert_extended_oci(&ci, pos) < 0) {
6092 wpabuf_free(buf);
6093 return NULL;
6094 }
6095 }
6096#endif /* CONFIG_OCV */
6097
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006098 wpa_hexdump_buf(MSG_DEBUG, "FILS: Association Request plaintext", buf);
6099
6100 *kek = sm->ptk.kek;
6101 *kek_len = sm->ptk.kek_len;
6102 wpa_hexdump_key(MSG_DEBUG, "FILS: KEK for AEAD", *kek, *kek_len);
6103 *snonce = sm->fils_nonce;
6104 wpa_hexdump(MSG_DEBUG, "FILS: SNonce for AEAD AAD",
6105 *snonce, FILS_NONCE_LEN);
6106 *anonce = sm->fils_anonce;
6107 wpa_hexdump(MSG_DEBUG, "FILS: ANonce for AEAD AAD",
6108 *anonce, FILS_NONCE_LEN);
6109
6110 return buf;
6111}
6112
6113
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006114static void fils_process_hlp_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
6115{
6116 const u8 *pos, *end;
6117
6118 wpa_hexdump(MSG_MSGDUMP, "FILS: HLP response", resp, len);
6119 if (len < 2 * ETH_ALEN)
6120 return;
6121 pos = resp + 2 * ETH_ALEN;
6122 end = resp + len;
6123 if (end - pos >= 6 &&
6124 os_memcmp(pos, "\xaa\xaa\x03\x00\x00\x00", 6) == 0)
6125 pos += 6; /* Remove SNAP/LLC header */
6126 wpa_sm_fils_hlp_rx(sm, resp, resp + ETH_ALEN, pos, end - pos);
6127}
6128
6129
6130static void fils_process_hlp_container(struct wpa_sm *sm, const u8 *pos,
6131 size_t len)
6132{
6133 const u8 *end = pos + len;
6134 u8 *tmp, *tmp_pos;
6135
6136 /* Check if there are any FILS HLP Container elements */
6137 while (end - pos >= 2) {
6138 if (2 + pos[1] > end - pos)
6139 return;
6140 if (pos[0] == WLAN_EID_EXTENSION &&
6141 pos[1] >= 1 + 2 * ETH_ALEN &&
6142 pos[2] == WLAN_EID_EXT_FILS_HLP_CONTAINER)
6143 break;
6144 pos += 2 + pos[1];
6145 }
6146 if (end - pos < 2)
6147 return; /* No FILS HLP Container elements */
6148
6149 tmp = os_malloc(end - pos);
6150 if (!tmp)
6151 return;
6152
6153 while (end - pos >= 2) {
6154 if (2 + pos[1] > end - pos ||
6155 pos[0] != WLAN_EID_EXTENSION ||
6156 pos[1] < 1 + 2 * ETH_ALEN ||
6157 pos[2] != WLAN_EID_EXT_FILS_HLP_CONTAINER)
6158 break;
6159 tmp_pos = tmp;
6160 os_memcpy(tmp_pos, pos + 3, pos[1] - 1);
6161 tmp_pos += pos[1] - 1;
6162 pos += 2 + pos[1];
6163
6164 /* Add possible fragments */
6165 while (end - pos >= 2 && pos[0] == WLAN_EID_FRAGMENT &&
6166 2 + pos[1] <= end - pos) {
6167 os_memcpy(tmp_pos, pos + 2, pos[1]);
6168 tmp_pos += pos[1];
6169 pos += 2 + pos[1];
6170 }
6171
6172 fils_process_hlp_resp(sm, tmp, tmp_pos - tmp);
6173 }
6174
6175 os_free(tmp);
6176}
6177
6178
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006179int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
6180{
6181 const struct ieee80211_mgmt *mgmt;
6182 const u8 *end, *ie_start;
6183 struct ieee802_11_elems elems;
6184 int keylen, rsclen;
6185 enum wpa_alg alg;
6186 struct wpa_gtk_data gd;
6187 int maxkeylen;
6188 struct wpa_eapol_ie_parse kde;
6189
6190 if (!sm || !sm->ptk_set) {
6191 wpa_printf(MSG_DEBUG, "FILS: No KEK available");
6192 return -1;
6193 }
6194
6195 if (!wpa_key_mgmt_fils(sm->key_mgmt)) {
6196 wpa_printf(MSG_DEBUG, "FILS: Not a FILS AKM");
6197 return -1;
6198 }
6199
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006200 if (sm->fils_completed) {
6201 wpa_printf(MSG_DEBUG,
6202 "FILS: Association has already been completed for this FILS authentication - ignore unexpected retransmission");
6203 return -1;
6204 }
6205
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006206 wpa_hexdump(MSG_DEBUG, "FILS: (Re)Association Response frame",
6207 resp, len);
6208
6209 mgmt = (const struct ieee80211_mgmt *) resp;
6210 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_resp))
6211 return -1;
6212
6213 end = resp + len;
6214 /* Same offset for Association Response and Reassociation Response */
6215 ie_start = mgmt->u.assoc_resp.variable;
6216
6217 if (ieee802_11_parse_elems(ie_start, end - ie_start, &elems, 1) ==
6218 ParseFailed) {
6219 wpa_printf(MSG_DEBUG,
6220 "FILS: Failed to parse decrypted elements");
6221 goto fail;
6222 }
6223
6224 if (!elems.fils_session) {
6225 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
6226 return -1;
6227 }
6228 if (os_memcmp(elems.fils_session, sm->fils_session,
6229 FILS_SESSION_LEN) != 0) {
6230 wpa_printf(MSG_DEBUG, "FILS: FILS Session mismatch");
6231 wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session",
6232 elems.fils_session, FILS_SESSION_LEN);
6233 wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session",
6234 sm->fils_session, FILS_SESSION_LEN);
6235 }
6236
Hai Shalom81f62d82019-07-22 12:10:00 -07006237 if (!elems.rsn_ie) {
6238 wpa_printf(MSG_DEBUG,
6239 "FILS: No RSNE in (Re)Association Response");
6240 /* As an interop workaround, allow this for now since IEEE Std
6241 * 802.11ai-2016 did not include all the needed changes to make
6242 * a FILS AP include RSNE in the frame. This workaround might
6243 * eventually be removed and replaced with rejection (goto fail)
6244 * to follow a strict interpretation of the standard. */
6245 } else if (wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt),
6246 sm->ap_rsn_ie, sm->ap_rsn_ie_len,
6247 elems.rsn_ie - 2, elems.rsn_ie_len + 2)) {
6248 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
6249 "FILS: RSNE mismatch between Beacon/Probe Response and (Re)Association Response");
6250 wpa_hexdump(MSG_DEBUG, "FILS: RSNE in Beacon/Probe Response",
6251 sm->ap_rsn_ie, sm->ap_rsn_ie_len);
6252 wpa_hexdump(MSG_DEBUG, "FILS: RSNE in (Re)Association Response",
6253 elems.rsn_ie, elems.rsn_ie_len);
6254 goto fail;
6255 }
6256
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006257 /* TODO: FILS Public Key */
6258
6259 if (!elems.fils_key_confirm) {
6260 wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element");
6261 goto fail;
6262 }
6263 if (elems.fils_key_confirm_len != sm->fils_key_auth_len) {
6264 wpa_printf(MSG_DEBUG,
6265 "FILS: Unexpected Key-Auth length %d (expected %d)",
6266 elems.fils_key_confirm_len,
6267 (int) sm->fils_key_auth_len);
6268 goto fail;
6269 }
6270 if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_ap,
6271 sm->fils_key_auth_len) != 0) {
6272 wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch");
6273 wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth",
6274 elems.fils_key_confirm,
6275 elems.fils_key_confirm_len);
6276 wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth",
6277 sm->fils_key_auth_ap, sm->fils_key_auth_len);
6278 goto fail;
6279 }
6280
Hai Shalom74f70d42019-02-11 14:42:39 -08006281#ifdef CONFIG_OCV
6282 if (wpa_sm_ocv_enabled(sm)) {
6283 struct wpa_channel_info ci;
6284
6285 if (wpa_sm_channel_info(sm, &ci) != 0) {
6286 wpa_printf(MSG_WARNING,
6287 "Failed to get channel info to validate received OCI in FILS (Re)Association Response frame");
6288 goto fail;
6289 }
6290
6291 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
6292 channel_width_to_int(ci.chanwidth),
Hai Shalom899fcc72020-10-19 14:38:18 -07006293 ci.seg1_idx) != OCI_SUCCESS) {
6294 wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE
6295 "addr=" MACSTR " frame=fils-assoc error=%s",
6296 MAC2STR(sm->bssid), ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08006297 goto fail;
6298 }
6299 }
6300#endif /* CONFIG_OCV */
6301
Hai Shalom021b0b52019-04-10 11:17:58 -07006302#ifdef CONFIG_IEEE80211R
6303 if (wpa_key_mgmt_ft(sm->key_mgmt) && sm->fils_ft_ies) {
6304 struct wpa_ie_data rsn;
6305
6306 /* Check that PMKR1Name derived by the AP matches */
6307 if (!elems.rsn_ie ||
6308 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
6309 &rsn) < 0 ||
6310 !rsn.pmkid || rsn.num_pmkid != 1 ||
6311 os_memcmp(rsn.pmkid, sm->pmk_r1_name,
6312 WPA_PMK_NAME_LEN) != 0) {
6313 wpa_printf(MSG_DEBUG,
6314 "FILS+FT: No RSNE[PMKR1Name] match in AssocResp");
6315 goto fail;
6316 }
6317 }
6318#endif /* CONFIG_IEEE80211R */
6319
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006320 /* Key Delivery */
6321 if (!elems.key_delivery) {
6322 wpa_printf(MSG_DEBUG, "FILS: No Key Delivery element");
6323 goto fail;
6324 }
6325
6326 /* Parse GTK and set the key to the driver */
6327 os_memset(&gd, 0, sizeof(gd));
6328 if (wpa_supplicant_parse_ies(elems.key_delivery + WPA_KEY_RSC_LEN,
6329 elems.key_delivery_len - WPA_KEY_RSC_LEN,
6330 &kde) < 0) {
6331 wpa_printf(MSG_DEBUG, "FILS: Failed to parse KDEs");
6332 goto fail;
6333 }
6334 if (!kde.gtk) {
6335 wpa_printf(MSG_DEBUG, "FILS: No GTK KDE");
6336 goto fail;
6337 }
6338 maxkeylen = gd.gtk_len = kde.gtk_len - 2;
6339 if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
6340 gd.gtk_len, maxkeylen,
6341 &gd.key_rsc_len, &gd.alg))
6342 goto fail;
6343
6344 wpa_hexdump_key(MSG_DEBUG, "FILS: Received GTK", kde.gtk, kde.gtk_len);
6345 gd.keyidx = kde.gtk[0] & 0x3;
6346 gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm,
6347 !!(kde.gtk[0] & BIT(2)));
6348 if (kde.gtk_len - 2 > sizeof(gd.gtk)) {
6349 wpa_printf(MSG_DEBUG, "FILS: Too long GTK in GTK KDE (len=%lu)",
6350 (unsigned long) kde.gtk_len - 2);
6351 goto fail;
6352 }
6353 os_memcpy(gd.gtk, kde.gtk + 2, kde.gtk_len - 2);
6354
6355 wpa_printf(MSG_DEBUG, "FILS: Set GTK to driver");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006356 if (wpa_supplicant_install_gtk(sm, &gd, elems.key_delivery, 0) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006357 wpa_printf(MSG_DEBUG, "FILS: Failed to set GTK");
6358 goto fail;
6359 }
6360
6361 if (ieee80211w_set_keys(sm, &kde) < 0) {
6362 wpa_printf(MSG_DEBUG, "FILS: Failed to set IGTK");
6363 goto fail;
6364 }
6365
6366 alg = wpa_cipher_to_alg(sm->pairwise_cipher);
6367 keylen = wpa_cipher_key_len(sm->pairwise_cipher);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006368 if (keylen <= 0 || (unsigned int) keylen != sm->ptk.tk_len) {
6369 wpa_printf(MSG_DEBUG, "FILS: TK length mismatch: %u != %lu",
6370 keylen, (long unsigned int) sm->ptk.tk_len);
6371 goto fail;
6372 }
Hai Shalomfdcde762020-04-02 11:19:20 -07006373
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006374 rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher);
6375 wpa_hexdump_key(MSG_DEBUG, "FILS: Set TK to driver",
6376 sm->ptk.tk, keylen);
Sunil Ravi77d572f2023-01-17 23:58:31 +00006377 if (wpa_sm_set_key(sm, -1, alg, wpa_sm_get_auth_addr(sm), 0, 1,
6378 null_rsc, rsclen,
Hai Shalomfdcde762020-04-02 11:19:20 -07006379 sm->ptk.tk, keylen, KEY_FLAG_PAIRWISE_RX_TX) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006380 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
Sunil Ravi77d572f2023-01-17 23:58:31 +00006381 "FILS: Failed to set PTK to the driver (alg=%d keylen=%d auth_addr="
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006382 MACSTR ")",
Sunil Ravi77d572f2023-01-17 23:58:31 +00006383 alg, keylen, MAC2STR(wpa_sm_get_auth_addr(sm)));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006384 goto fail;
6385 }
6386
Hai Shalom60840252021-02-19 19:02:11 -08006387 wpa_sm_store_ptk(sm, sm->bssid, sm->pairwise_cipher,
6388 sm->dot11RSNAConfigPMKLifetime, &sm->ptk);
6389
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006390 /* TODO: TK could be cleared after auth frame exchange now that driver
6391 * takes care of association frame encryption/decryption. */
6392 /* TK is not needed anymore in supplicant */
6393 os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006394 sm->ptk.tk_len = 0;
Mathy Vanhoefc66556c2017-09-29 04:22:51 +02006395 sm->ptk.installed = 1;
Sunil8cd6f4d2022-06-28 18:40:46 +00006396 sm->tk_set = true;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006397
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08006398 /* FILS HLP Container */
6399 fils_process_hlp_container(sm, ie_start, end - ie_start);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006400
6401 /* TODO: FILS IP Address Assignment */
6402
6403 wpa_printf(MSG_DEBUG, "FILS: Auth+Assoc completed successfully");
6404 sm->fils_completed = 1;
Hai Shalom81f62d82019-07-22 12:10:00 -07006405 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006406
Hai Shalomfdcde762020-04-02 11:19:20 -07006407 if (kde.transition_disable)
6408 wpa_sm_transition_disable(sm, kde.transition_disable[0]);
6409
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006410 return 0;
6411fail:
Hai Shalom81f62d82019-07-22 12:10:00 -07006412 forced_memzero(&gd, sizeof(gd));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006413 return -1;
6414}
6415
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006416
6417void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set)
6418{
6419 if (sm)
6420 sm->fils_completed = !!set;
6421}
6422
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08006423#endif /* CONFIG_FILS */
6424
6425
6426int wpa_fils_is_completed(struct wpa_sm *sm)
6427{
6428#ifdef CONFIG_FILS
6429 return sm && sm->fils_completed;
6430#else /* CONFIG_FILS */
6431 return 0;
6432#endif /* CONFIG_FILS */
6433}
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006434
6435
6436#ifdef CONFIG_OWE
6437
6438struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm, u16 group)
6439{
6440 struct wpabuf *ie = NULL, *pub = NULL;
6441 size_t prime_len;
6442
6443 if (group == 19)
6444 prime_len = 32;
6445 else if (group == 20)
6446 prime_len = 48;
6447 else if (group == 21)
6448 prime_len = 66;
6449 else
6450 return NULL;
6451
6452 crypto_ecdh_deinit(sm->owe_ecdh);
6453 sm->owe_ecdh = crypto_ecdh_init(group);
6454 if (!sm->owe_ecdh)
6455 goto fail;
6456 sm->owe_group = group;
6457 pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
6458 pub = wpabuf_zeropad(pub, prime_len);
6459 if (!pub)
6460 goto fail;
6461
6462 ie = wpabuf_alloc(5 + wpabuf_len(pub));
6463 if (!ie)
6464 goto fail;
6465 wpabuf_put_u8(ie, WLAN_EID_EXTENSION);
6466 wpabuf_put_u8(ie, 1 + 2 + wpabuf_len(pub));
6467 wpabuf_put_u8(ie, WLAN_EID_EXT_OWE_DH_PARAM);
6468 wpabuf_put_le16(ie, group);
6469 wpabuf_put_buf(ie, pub);
6470 wpabuf_free(pub);
6471 wpa_hexdump_buf(MSG_DEBUG, "OWE: Diffie-Hellman Parameter element",
6472 ie);
6473
6474 return ie;
6475fail:
6476 wpabuf_free(pub);
6477 crypto_ecdh_deinit(sm->owe_ecdh);
6478 sm->owe_ecdh = NULL;
6479 return NULL;
6480}
6481
6482
6483int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid,
6484 const u8 *resp_ies, size_t resp_ies_len)
6485{
6486 struct ieee802_11_elems elems;
6487 u16 group;
6488 struct wpabuf *secret, *pub, *hkey;
6489 int res;
6490 u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN];
6491 const char *info = "OWE Key Generation";
6492 const u8 *addr[2];
6493 size_t len[2];
6494 size_t hash_len, prime_len;
6495 struct wpa_ie_data data;
6496
6497 if (!resp_ies ||
6498 ieee802_11_parse_elems(resp_ies, resp_ies_len, &elems, 1) ==
6499 ParseFailed) {
6500 wpa_printf(MSG_INFO,
6501 "OWE: Could not parse Association Response frame elements");
6502 return -1;
6503 }
6504
6505 if (sm->cur_pmksa && elems.rsn_ie &&
6506 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, 2 + elems.rsn_ie_len,
6507 &data) == 0 &&
6508 data.num_pmkid == 1 && data.pmkid &&
6509 os_memcmp(sm->cur_pmksa->pmkid, data.pmkid, PMKID_LEN) == 0) {
6510 wpa_printf(MSG_DEBUG, "OWE: Use PMKSA caching");
6511 wpa_sm_set_pmk_from_pmksa(sm);
6512 return 0;
6513 }
6514
6515 if (!elems.owe_dh) {
6516 wpa_printf(MSG_INFO,
6517 "OWE: No Diffie-Hellman Parameter element found in Association Response frame");
6518 return -1;
6519 }
6520
6521 group = WPA_GET_LE16(elems.owe_dh);
6522 if (group != sm->owe_group) {
6523 wpa_printf(MSG_INFO,
6524 "OWE: Unexpected Diffie-Hellman group in response: %u",
6525 group);
6526 return -1;
6527 }
6528
6529 if (!sm->owe_ecdh) {
6530 wpa_printf(MSG_INFO, "OWE: No ECDH state available");
6531 return -1;
6532 }
6533
6534 if (group == 19)
6535 prime_len = 32;
6536 else if (group == 20)
6537 prime_len = 48;
6538 else if (group == 21)
6539 prime_len = 66;
6540 else
6541 return -1;
6542
6543 secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0,
6544 elems.owe_dh + 2,
6545 elems.owe_dh_len - 2);
6546 secret = wpabuf_zeropad(secret, prime_len);
6547 if (!secret) {
6548 wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
6549 return -1;
6550 }
6551 wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret);
6552
6553 /* prk = HKDF-extract(C | A | group, z) */
6554
6555 pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
6556 if (!pub) {
6557 wpabuf_clear_free(secret);
6558 return -1;
6559 }
6560
6561 /* PMKID = Truncate-128(Hash(C | A)) */
6562 addr[0] = wpabuf_head(pub);
6563 len[0] = wpabuf_len(pub);
6564 addr[1] = elems.owe_dh + 2;
6565 len[1] = elems.owe_dh_len - 2;
6566 if (group == 19) {
6567 res = sha256_vector(2, addr, len, pmkid);
6568 hash_len = SHA256_MAC_LEN;
6569 } else if (group == 20) {
6570 res = sha384_vector(2, addr, len, pmkid);
6571 hash_len = SHA384_MAC_LEN;
6572 } else if (group == 21) {
6573 res = sha512_vector(2, addr, len, pmkid);
6574 hash_len = SHA512_MAC_LEN;
6575 } else {
6576 res = -1;
6577 hash_len = 0;
6578 }
6579 pub = wpabuf_zeropad(pub, prime_len);
6580 if (res < 0 || !pub) {
6581 wpabuf_free(pub);
6582 wpabuf_clear_free(secret);
6583 return -1;
6584 }
6585
6586 hkey = wpabuf_alloc(wpabuf_len(pub) + elems.owe_dh_len - 2 + 2);
6587 if (!hkey) {
6588 wpabuf_free(pub);
6589 wpabuf_clear_free(secret);
6590 return -1;
6591 }
6592
6593 wpabuf_put_buf(hkey, pub); /* C */
6594 wpabuf_free(pub);
6595 wpabuf_put_data(hkey, elems.owe_dh + 2, elems.owe_dh_len - 2); /* A */
6596 wpabuf_put_le16(hkey, sm->owe_group); /* group */
6597 if (group == 19)
6598 res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
6599 wpabuf_head(secret), wpabuf_len(secret), prk);
6600 else if (group == 20)
6601 res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey),
6602 wpabuf_head(secret), wpabuf_len(secret), prk);
6603 else if (group == 21)
6604 res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey),
6605 wpabuf_head(secret), wpabuf_len(secret), prk);
6606 wpabuf_clear_free(hkey);
6607 wpabuf_clear_free(secret);
6608 if (res < 0)
6609 return -1;
6610
6611 wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
6612
6613 /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
6614
6615 if (group == 19)
6616 res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info,
6617 os_strlen(info), sm->pmk, hash_len);
6618 else if (group == 20)
6619 res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info,
6620 os_strlen(info), sm->pmk, hash_len);
6621 else if (group == 21)
6622 res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
6623 os_strlen(info), sm->pmk, hash_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07006624 forced_memzero(prk, SHA512_MAC_LEN);
Roshan Pius3a1667e2018-07-03 15:17:14 -07006625 if (res < 0) {
6626 sm->pmk_len = 0;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006627 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07006628 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07006629 sm->pmk_len = hash_len;
6630
6631 wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len);
6632 wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
6633 pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, pmkid, NULL, 0,
6634 bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt,
6635 NULL);
6636
6637 return 0;
6638}
6639
6640#endif /* CONFIG_OWE */
6641
6642
6643void wpa_sm_set_fils_cache_id(struct wpa_sm *sm, const u8 *fils_cache_id)
6644{
6645#ifdef CONFIG_FILS
6646 if (sm && fils_cache_id) {
6647 sm->fils_cache_id_set = 1;
6648 os_memcpy(sm->fils_cache_id, fils_cache_id, FILS_CACHE_ID_LEN);
6649 }
6650#endif /* CONFIG_FILS */
6651}
Hai Shalom021b0b52019-04-10 11:17:58 -07006652
6653
6654#ifdef CONFIG_DPP2
6655void wpa_sm_set_dpp_z(struct wpa_sm *sm, const struct wpabuf *z)
6656{
6657 if (sm) {
6658 wpabuf_clear_free(sm->dpp_z);
6659 sm->dpp_z = z ? wpabuf_dup(z) : NULL;
6660 }
6661}
6662#endif /* CONFIG_DPP2 */
Hai Shalom60840252021-02-19 19:02:11 -08006663
6664
6665#ifdef CONFIG_PASN
Sunil Ravi89eba102022-09-13 21:04:37 -07006666
Sunil Ravi89eba102022-09-13 21:04:37 -07006667void wpa_pasn_sm_set_caps(struct wpa_sm *sm, unsigned int flags2)
6668{
6669 if (flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_STA)
6670 sm->secure_ltf = 1;
6671 if (flags2 & WPA_DRIVER_FLAGS2_SEC_RTT_STA)
6672 sm->secure_rtt = 1;
6673 if (flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_STA)
6674 sm->prot_range_neg = 1;
6675}
6676
Hai Shalom60840252021-02-19 19:02:11 -08006677#endif /* CONFIG_PASN */
Hai Shalomc1a21442022-02-04 13:43:00 -08006678
6679
6680void wpa_sm_pmksa_cache_reconfig(struct wpa_sm *sm)
6681{
6682 if (sm)
6683 pmksa_cache_reconfig(sm->pmksa);
6684}
Sunil Ravi77d572f2023-01-17 23:58:31 +00006685
6686
6687struct rsn_pmksa_cache * wpa_sm_get_pmksa_cache(struct wpa_sm *sm)
6688{
6689 return sm ? sm->pmksa : NULL;
6690}
6691
6692
6693void wpa_sm_set_cur_pmksa(struct wpa_sm *sm,
6694 struct rsn_pmksa_cache_entry *entry)
6695{
6696 if (sm)
6697 sm->cur_pmksa = entry;
6698}
Sunil Ravi2a14cf12023-11-21 00:54:38 +00006699
6700
6701void wpa_sm_set_driver_bss_selection(struct wpa_sm *sm,
6702 bool driver_bss_selection)
6703{
6704 if (sm)
6705 sm->driver_bss_selection = driver_bss_selection;
6706}