blob: df2c68fe0229f9e0b8b5fc18f57a1a27a9d3ffad [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * wpa_supplicant - SME
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003 * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "utils/eloop.h"
Sunil Ravi77d572f2023-01-17 23:58:31 +000013#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#include "common/ieee802_11_defs.h"
15#include "common/ieee802_11_common.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080016#include "common/ocv.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070017#include "eapol_supp/eapol_supp_sm.h"
18#include "common/wpa_common.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080019#include "common/sae.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070020#include "common/dpp.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "rsn_supp/wpa.h"
22#include "rsn_supp/pmksa_cache.h"
23#include "config.h"
24#include "wpa_supplicant_i.h"
25#include "driver_i.h"
26#include "wpas_glue.h"
27#include "wps_supplicant.h"
28#include "p2p_supplicant.h"
29#include "notify.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "bss.h"
31#include "scan.h"
32#include "sme.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070033#include "hs20_supplicant.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034
35#define SME_AUTH_TIMEOUT 5
36#define SME_ASSOC_TIMEOUT 5
37
38static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
39static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt04949592012-07-19 12:16:46 -070040static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042
43
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080044#ifdef CONFIG_SAE
45
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080046static int index_within_array(const int *array, int idx)
47{
48 int i;
49 for (i = 0; i < idx; i++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -080050 if (array[i] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080051 return 0;
52 }
53 return 1;
54}
55
56
Sunil Ravi77d572f2023-01-17 23:58:31 +000057static int sme_set_sae_group(struct wpa_supplicant *wpa_s, bool external)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080058{
59 int *groups = wpa_s->conf->sae_groups;
Hai Shalom021b0b52019-04-10 11:17:58 -070060 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080061
Dmitry Shmidtcce06662013-11-04 18:44:24 -080062 if (!groups || groups[0] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080063 groups = default_groups;
64
65 /* Configuration may have changed, so validate current index */
66 if (!index_within_array(groups, wpa_s->sme.sae_group_index))
67 return -1;
68
69 for (;;) {
70 int group = groups[wpa_s->sme.sae_group_index];
Dmitry Shmidt41712582015-06-29 11:02:15 -070071 if (group <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080072 break;
73 if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
74 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
75 wpa_s->sme.sae.group);
Sunil Ravi77d572f2023-01-17 23:58:31 +000076 wpa_s->sme.sae.akmp = external ?
77 wpa_s->sme.ext_auth_key_mgmt : wpa_s->key_mgmt;
Hai Shalom74f70d42019-02-11 14:42:39 -080078 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080079 }
80 wpa_s->sme.sae_group_index++;
81 }
82
83 return -1;
84}
85
86
87static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
88 struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +000089 const u8 *bssid,
90 const u8 *mld_addr,
91 int external,
Hai Shalom899fcc72020-10-19 14:38:18 -070092 int reuse, int *ret_use_pt,
93 bool *ret_use_pk)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080094{
95 struct wpabuf *buf;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080096 size_t len;
Sunil Ravi77d572f2023-01-17 23:58:31 +000097 char *password = NULL;
Hai Shalomc3565922019-10-28 11:58:20 -070098 struct wpa_bss *bss;
99 int use_pt = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700100 bool use_pk = false;
101 u8 rsnxe_capa = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000102 int key_mgmt = external ? wpa_s->sme.ext_auth_key_mgmt :
103 wpa_s->key_mgmt;
104 const u8 *addr = mld_addr ? mld_addr : bssid;
Hai Shalomc3565922019-10-28 11:58:20 -0700105
106 if (ret_use_pt)
107 *ret_use_pt = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700108 if (ret_use_pk)
109 *ret_use_pk = false;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800110
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700111#ifdef CONFIG_TESTING_OPTIONS
112 if (wpa_s->sae_commit_override) {
113 wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
114 buf = wpabuf_alloc(4 + wpabuf_len(wpa_s->sae_commit_override));
115 if (!buf)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000116 goto fail;
Hai Shalom021b0b52019-04-10 11:17:58 -0700117 if (!external) {
118 wpabuf_put_le16(buf, 1); /* Transaction seq# */
119 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
120 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700121 wpabuf_put_buf(buf, wpa_s->sae_commit_override);
122 return buf;
123 }
124#endif /* CONFIG_TESTING_OPTIONS */
125
Sunil Ravi77d572f2023-01-17 23:58:31 +0000126 if (ssid->sae_password) {
127 password = os_strdup(ssid->sae_password);
128 if (!password) {
129 wpa_dbg(wpa_s, MSG_INFO,
130 "SAE: Failed to allocate password");
131 goto fail;
132 }
133 }
134 if (!password && ssid->passphrase) {
135 password = os_strdup(ssid->passphrase);
136 if (!password) {
137 wpa_dbg(wpa_s, MSG_INFO,
138 "SAE: Failed to allocate password");
139 goto fail;
140 }
141 }
142 if (!password && ssid->ext_psk) {
143 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
144 ssid->ext_psk);
145
146 if (!pw) {
147 wpa_msg(wpa_s, MSG_INFO,
148 "SAE: No password found from external storage");
149 goto fail;
150 }
151
152 password = os_malloc(wpabuf_len(pw) + 1);
153 if (!password) {
154 wpa_dbg(wpa_s, MSG_INFO,
155 "SAE: Failed to allocate password");
156 goto fail;
157 }
158 os_memcpy(password, wpabuf_head(pw), wpabuf_len(pw));
159 password[wpabuf_len(pw)] = '\0';
160 ext_password_free(pw);
161 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700162 if (!password) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800163 wpa_printf(MSG_DEBUG, "SAE: No password available");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000164 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800165 }
166
Hai Shalom021b0b52019-04-10 11:17:58 -0700167 if (reuse && wpa_s->sme.sae.tmp &&
Sunil Ravi77d572f2023-01-17 23:58:31 +0000168 os_memcmp(addr, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700169 wpa_printf(MSG_DEBUG,
170 "SAE: Reuse previously generated PWE on a retry with the same AP");
Hai Shalom899fcc72020-10-19 14:38:18 -0700171 use_pt = wpa_s->sme.sae.h2e;
172 use_pk = wpa_s->sme.sae.pk;
Hai Shalom021b0b52019-04-10 11:17:58 -0700173 goto reuse_data;
174 }
Sunil Ravi77d572f2023-01-17 23:58:31 +0000175 if (sme_set_sae_group(wpa_s, external) < 0) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800176 wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000177 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800178 }
179
Hai Shalom899fcc72020-10-19 14:38:18 -0700180 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800181 if (!bss) {
182 wpa_printf(MSG_DEBUG,
183 "SAE: BSS not available, update scan result to get BSS");
184 wpa_supplicant_update_scan_results(wpa_s);
185 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
186 }
Hai Shalom899fcc72020-10-19 14:38:18 -0700187 if (bss) {
188 const u8 *rsnxe;
189
190 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
191 if (rsnxe && rsnxe[1] >= 1)
192 rsnxe_capa = rsnxe[2];
193 }
194
Sunil Ravi77d572f2023-01-17 23:58:31 +0000195 if (ssid->sae_password_id &&
196 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Hai Shalomfdcde762020-04-02 11:19:20 -0700197 use_pt = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000198 if (wpa_key_mgmt_sae_ext_key(key_mgmt) &&
199 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -0700200 use_pt = 1;
Sunil Ravi036cec52023-03-29 11:35:17 -0700201 if (bss && is_6ghz_freq(bss->freq) &&
202 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
203 use_pt = 1;
Hai Shalom899fcc72020-10-19 14:38:18 -0700204#ifdef CONFIG_SAE_PK
205 if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
206 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
207 ((ssid->sae_password &&
208 sae_pk_valid_password(ssid->sae_password)) ||
209 (!ssid->sae_password && ssid->passphrase &&
210 sae_pk_valid_password(ssid->passphrase)))) {
211 use_pt = 1;
212 use_pk = true;
213 }
214
215 if (ssid->sae_pk == SAE_PK_MODE_ONLY && !use_pk) {
216 wpa_printf(MSG_DEBUG,
217 "SAE: Cannot use PK with the selected AP");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000218 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -0700219 }
220#endif /* CONFIG_SAE_PK */
Hai Shalomfdcde762020-04-02 11:19:20 -0700221
Sunil Ravi77d572f2023-01-17 23:58:31 +0000222 if (use_pt || wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
223 wpa_s->conf->sae_pwe == SAE_PWE_BOTH) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700224 use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
Hai Shalomc3565922019-10-28 11:58:20 -0700225
Sunil Ravi77d572f2023-01-17 23:58:31 +0000226 if ((wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
227 ssid->sae_password_id ||
228 wpa_key_mgmt_sae_ext_key(key_mgmt)) &&
229 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
Hai Shalomfdcde762020-04-02 11:19:20 -0700230 !use_pt) {
Hai Shalomc3565922019-10-28 11:58:20 -0700231 wpa_printf(MSG_DEBUG,
232 "SAE: Cannot use H2E with the selected AP");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000233 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -0700234 }
235 }
236
Sunil Ravi036cec52023-03-29 11:35:17 -0700237 if (use_pt && !ssid->pt)
238 wpa_s_setup_sae_pt(wpa_s->conf, ssid, true);
Hai Shalomc3565922019-10-28 11:58:20 -0700239 if (use_pt &&
240 sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000241 wpa_s->own_addr, addr,
Hai Shalom899fcc72020-10-19 14:38:18 -0700242 wpa_s->sme.sae_rejected_groups, NULL) < 0)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000243 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -0700244 if (!use_pt &&
245 sae_prepare_commit(wpa_s->own_addr, bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700246 (u8 *) password, os_strlen(password),
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800247 &wpa_s->sme.sae) < 0) {
248 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000249 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800250 }
Hai Shalom899fcc72020-10-19 14:38:18 -0700251 if (wpa_s->sme.sae.tmp) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000252 os_memcpy(wpa_s->sme.sae.tmp->bssid, addr, ETH_ALEN);
Hai Shalom899fcc72020-10-19 14:38:18 -0700253 if (use_pt && use_pk)
254 wpa_s->sme.sae.pk = 1;
255#ifdef CONFIG_SAE_PK
256 os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr,
257 ETH_ALEN);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000258 os_memcpy(wpa_s->sme.sae.tmp->peer_addr, addr, ETH_ALEN);
Hai Shalom899fcc72020-10-19 14:38:18 -0700259 sae_pk_set_password(&wpa_s->sme.sae, password);
260#endif /* CONFIG_SAE_PK */
261 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800262
Hai Shalom021b0b52019-04-10 11:17:58 -0700263reuse_data:
Hai Shalomfdcde762020-04-02 11:19:20 -0700264 len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700265 if (ssid->sae_password_id)
266 len += 4 + os_strlen(ssid->sae_password_id);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800267 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800268 if (buf == NULL)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000269 goto fail;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700270 if (!external) {
271 wpabuf_put_le16(buf, 1); /* Transaction seq# */
Hai Shalom899fcc72020-10-19 14:38:18 -0700272 if (use_pk)
273 wpabuf_put_le16(buf, WLAN_STATUS_SAE_PK);
274 else if (use_pt)
275 wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
276 else
277 wpabuf_put_le16(buf,WLAN_STATUS_SUCCESS);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700278 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700279 if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
280 ssid->sae_password_id) < 0) {
281 wpabuf_free(buf);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000282 goto fail;
Hai Shalomfdcde762020-04-02 11:19:20 -0700283 }
Hai Shalomc3565922019-10-28 11:58:20 -0700284 if (ret_use_pt)
285 *ret_use_pt = use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -0700286 if (ret_use_pk)
287 *ret_use_pk = use_pk;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800288
Sunil Ravi77d572f2023-01-17 23:58:31 +0000289 str_clear_free(password);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800290 return buf;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000291
292fail:
293 str_clear_free(password);
294 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800295}
296
297
Roshan Pius3a1667e2018-07-03 15:17:14 -0700298static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s,
299 int external)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800300{
301 struct wpabuf *buf;
302
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800303 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800304 if (buf == NULL)
305 return NULL;
306
Roshan Pius3a1667e2018-07-03 15:17:14 -0700307 if (!external) {
308 wpabuf_put_le16(buf, 2); /* Transaction seq# */
309 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
310 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800311 sae_write_confirm(&wpa_s->sme.sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800312
313 return buf;
314}
315
316#endif /* CONFIG_SAE */
317
318
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800319/**
320 * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt
321 * @wpa_s: Pointer to wpa_supplicant data
322 * @bss: Pointer to the bss which is the target of authentication attempt
323 */
324static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
325 struct wpa_bss *bss)
326{
327 const u8 rrm_ie_len = 5;
328 u8 *pos;
329 const u8 *rrm_ie;
330
331 wpa_s->rrm.rrm_used = 0;
332
333 wpa_printf(MSG_DEBUG,
334 "RRM: Determining whether RRM can be used - device support: 0x%x",
335 wpa_s->drv_rrm_flags);
336
337 rrm_ie = wpa_bss_get_ie(bss, WLAN_EID_RRM_ENABLED_CAPABILITIES);
338 if (!rrm_ie || !(bss->caps & IEEE80211_CAP_RRM)) {
339 wpa_printf(MSG_DEBUG, "RRM: No RRM in network");
340 return;
341 }
342
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700343 if (!((wpa_s->drv_rrm_flags &
344 WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
345 (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
346 !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800347 wpa_printf(MSG_DEBUG,
348 "RRM: Insufficient RRM support in driver - do not use RRM");
349 return;
350 }
351
352 if (sizeof(wpa_s->sme.assoc_req_ie) <
353 wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) {
354 wpa_printf(MSG_INFO,
355 "RRM: Unable to use RRM, no room for RRM IE");
356 return;
357 }
358
359 wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to Association Request");
360 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
361 os_memset(pos, 0, 2 + rrm_ie_len);
362 *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
363 *pos++ = rrm_ie_len;
364
Hai Shalom60840252021-02-19 19:02:11 -0800365 /* Set supported capabilities flags */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800366 if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
367 *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
368
Dmitry Shmidt29333592017-01-09 12:27:11 -0800369 *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
370 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
371 WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
372
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700373 if (wpa_s->lci)
374 pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
375
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800376 wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
377 wpa_s->rrm.rrm_used = 1;
378}
379
380
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000381static void wpas_process_tbtt_info(struct wpa_supplicant *wpa_s, const u8 *data)
382{
383 struct wpa_bss *neigh_bss;
384 const u8 *bssid;
385 u8 bss_params;
386 u8 link_id;
387
388 /* TBTT Information field
389 * Neighbor AP TBTT Offset[1]
390 * BSSID[6]
391 * Short SSID[4]
392 * BSS parameters[1]
393 * 20 MHz PSD[1]
394 * MLD Parameters[3]
395 * B0..B7: AP MLD ID
396 * B7..B11: Link ID
397 * B12..B19: BSS Parameters Change Count
398 * B20: All Updates Included
399 * B21: Disabled Link Indication */
400
401 bssid = data + 1;
402 bss_params = data[1 + ETH_ALEN + 4];
403
404 data += 13; /* MLD Parameters */
405 link_id = *(data + 1) & 0xF;
406
407 wpa_dbg(wpa_s, MSG_DEBUG,
408 "MLD: mld ID=%u, link ID=%u, bssid=" MACSTR ", bss_params=0x%x",
409 *data, link_id, MAC2STR(bssid), bss_params);
410
411 if (*data) {
412 wpa_printf(MSG_DEBUG, "MLD: Reported link not part of MLD");
413 return;
414 }
415
416 neigh_bss = wpa_bss_get_bssid(wpa_s, bssid);
417 if (!neigh_bss) {
418 wpa_printf(MSG_DEBUG, "MLD: Neighbor not found in scan");
419 return;
420 }
421
422 if (!((bss_params & RNR_BSS_PARAM_SAME_SSID) &&
423 (bss_params & RNR_BSS_PARAM_CO_LOCATED)) &&
424 !wpa_scan_res_match(wpa_s, 0, neigh_bss, wpa_s->current_ssid,
425 1, 0)) {
426 wpa_printf(MSG_DEBUG,
427 "MLD: Neighbor doesn't match current SSID - skip link");
428 return;
429 }
430
431 wpa_s->valid_links |= BIT(link_id);
432 os_memcpy(wpa_s->links[link_id].bssid, bssid, ETH_ALEN);
433 wpa_s->links[link_id].freq = neigh_bss->freq;
434}
435
436
437static void wpas_process_rnr(struct wpa_supplicant *wpa_s, const u8 *pos,
438 size_t rnr_ie_len)
439{
440 while (rnr_ie_len > sizeof(struct ieee80211_neighbor_ap_info)) {
441 const struct ieee80211_neighbor_ap_info *ap_info =
442 (const struct ieee80211_neighbor_ap_info *) pos;
443 /* The first TBTT Information field */
444 const u8 *data = ap_info->data;
445 u8 tbtt_count;
446 size_t len;
447 int tbtt_i;
448
449 if (rnr_ie_len < sizeof(struct ieee80211_neighbor_ap_info))
450 break;
451
452 tbtt_count = (ap_info->tbtt_info_hdr >> 4) + 1;
453 len = sizeof(struct ieee80211_neighbor_ap_info) +
454 ap_info->tbtt_info_len * tbtt_count;
455
456 wpa_printf(MSG_DEBUG, "MLD: op_class=%u, channel=%u",
457 ap_info->op_class, ap_info->channel);
458
459 if (len > rnr_ie_len)
460 break;
461
462 if (ap_info->tbtt_info_len < 16) {
463 rnr_ie_len -= len;
464 pos += len;
465 continue;
466 }
467
468 for (tbtt_i = 0; tbtt_i < tbtt_count; tbtt_i++) {
469 wpas_process_tbtt_info(wpa_s, data);
470 data += ap_info->tbtt_info_len;
471 }
472
473 rnr_ie_len -= len;
474 pos += len;
475 }
476}
477
478
Sunil Ravi640215c2023-06-28 23:08:09 +0000479static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
480 struct wpa_ssid *ssid)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000481{
482 struct wpabuf *mlbuf;
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000483 const u8 *rnr_ie, *rsn_ie;
Sunil Ravi640215c2023-06-28 23:08:09 +0000484 struct wpa_ie_data ie;
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000485 u8 ml_ie_len;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000486 const struct ieee80211_eht_ml *eht_ml;
487 const struct eht_ml_basic_common_info *ml_basic_common_info;
488 u8 i;
489 const u16 control =
490 host_to_le16(MULTI_LINK_CONTROL_TYPE_BASIC |
491 BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
492 BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
493 BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA);
494 bool ret = false;
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000495 int rnr_idx;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000496
497 if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO))
498 return false;
499
500 mlbuf = wpa_bss_defrag_mle(bss, MULTI_LINK_CONTROL_TYPE_BASIC);
501 if (!mlbuf) {
502 wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No ML element");
503 return false;
504 }
505
Sunil Ravi640215c2023-06-28 23:08:09 +0000506 rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
507 if (!rsn_ie || wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
508 wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
509 goto out;
510 }
511
512 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
513 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
514 wpa_dbg(wpa_s, MSG_DEBUG,
515 "MLD: No management frame protection");
516 goto out;
517 }
518
519 ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
520 WPA_KEY_MGMT_PSK_SHA256);
521 if (!(ie.key_mgmt & ssid->key_mgmt)) {
522 wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
523 goto out;
524 }
525
Sunil Ravi77d572f2023-01-17 23:58:31 +0000526 ml_ie_len = wpabuf_len(mlbuf);
527
528 /* control + common info len + MLD address + MLD link information */
529 if (ml_ie_len < 2 + 1 + ETH_ALEN + 1)
530 goto out;
531
532 eht_ml = wpabuf_head(mlbuf);
533 if ((eht_ml->ml_control & control) != control) {
534 wpa_printf(MSG_DEBUG, "MLD: Unexpected ML element control=0x%x",
535 eht_ml->ml_control);
536 goto out;
537 }
538
539 ml_basic_common_info =
540 (const struct eht_ml_basic_common_info *) eht_ml->variable;
541
542 /* common info length should be valid (self, mld_addr, link_id) */
543 if (ml_basic_common_info->len < 1 + ETH_ALEN + 1)
544 goto out;
545
546 /* get the MLD address and MLD link ID */
547 os_memcpy(wpa_s->ap_mld_addr, ml_basic_common_info->mld_addr,
548 ETH_ALEN);
549 wpa_s->mlo_assoc_link_id = ml_basic_common_info->variable[0] &
550 EHT_ML_LINK_ID_MSK;
551
552 os_memcpy(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid, bss->bssid,
553 ETH_ALEN);
554 wpa_s->links[wpa_s->mlo_assoc_link_id].freq = bss->freq;
555
556 wpa_printf(MSG_DEBUG, "MLD: address=" MACSTR ", link ID=%u",
557 MAC2STR(wpa_s->ap_mld_addr), wpa_s->mlo_assoc_link_id);
558
559 wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
560
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000561 ret = true;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000562
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000563 /* Process all Reduced Neighbor Report elements */
564 for (rnr_idx = 1; ; rnr_idx++) {
565 rnr_ie = wpa_bss_get_ie_nth(bss,
566 WLAN_EID_REDUCED_NEIGHBOR_REPORT,
567 rnr_idx);
568 if (!rnr_ie) {
569 if (rnr_idx == 0) {
570 wpa_dbg(wpa_s, MSG_DEBUG,
571 "MLD: No RNR element");
572 goto out;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000573 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000574 break;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000575 }
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000576 wpas_process_rnr(wpa_s, rnr_ie + 2, rnr_ie[1]);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000577 }
578
579 wpa_printf(MSG_DEBUG, "MLD: valid_links=0x%x", wpa_s->valid_links);
580
581 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
582 if (!(wpa_s->valid_links & BIT(i)))
583 continue;
584
585 wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
586 i, MAC2STR(wpa_s->links[i].bssid));
587 }
588
Sunil Ravi77d572f2023-01-17 23:58:31 +0000589out:
590 wpabuf_free(mlbuf);
591 return ret;
592}
593
594
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000595static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s,
596 struct wpa_bss *bss)
597{
598 u16 removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, bss);
599
600 wpa_s->valid_links &= ~removed_links;
601}
602
603
Sunil Ravi77d572f2023-01-17 23:58:31 +0000604static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
605 union wpa_event_data *data,
606 int ie_offset)
607{
608 struct ieee802_11_elems elems;
609 const u8 *mld_addr;
Sunil Ravi640215c2023-06-28 23:08:09 +0000610 u16 status_code = data->auth.status_code;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000611
612 if (!wpa_s->valid_links)
613 return;
614
615 if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
616 data->auth.ies_len - ie_offset,
Sunil Ravi640215c2023-06-28 23:08:09 +0000617 &elems, 0) == ParseFailed) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000618 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
619 goto out;
620 }
621
622 if (!elems.basic_mle || !elems.basic_mle_len) {
623 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
Sunil Ravi640215c2023-06-28 23:08:09 +0000624 if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
625 status_code == WLAN_STATUS_SUCCESS ||
626 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
627 status_code == WLAN_STATUS_SAE_PK)
628 goto out;
629 /* Accept missing Multi-Link element in failed authentication
630 * cases. */
631 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000632 }
633
634 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
635 if (!mld_addr)
636 goto out;
637
638 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
639
640 if (os_memcmp(wpa_s->ap_mld_addr, mld_addr, ETH_ALEN) != 0) {
641 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
642 MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
643 goto out;
644 }
645
646 return;
647out:
648 wpa_printf(MSG_DEBUG, "MLD: Authentication - clearing MLD state");
649 wpas_reset_mlo_info(wpa_s);
650}
651
652
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800653static void sme_send_authentication(struct wpa_supplicant *wpa_s,
654 struct wpa_bss *bss, struct wpa_ssid *ssid,
655 int start)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700656{
657 struct wpa_driver_auth_params params;
658 struct wpa_ssid *old_ssid;
659#ifdef CONFIG_IEEE80211R
660 const u8 *ie;
661#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700662#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700663 const u8 *md = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700664#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Hai Shalomfdcde762020-04-02 11:19:20 -0700665 int bssid_changed;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800666 struct wpabuf *resp = NULL;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700667 u8 ext_capab[18];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800668 int ext_capab_len;
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800669 int skip_auth;
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800670 u8 *wpa_ie;
671 size_t wpa_ie_len;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700672#ifdef CONFIG_MBO
673 const u8 *mbo_ie;
674#endif /* CONFIG_MBO */
Hai Shalomfdcde762020-04-02 11:19:20 -0700675 int omit_rsnxe = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700676
677 if (bss == NULL) {
678 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
679 "the network");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800680 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700681 return;
682 }
683
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800684 skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
685 wpa_s->reassoc_same_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700686 wpa_s->current_bss = bss;
687
688 os_memset(&params, 0, sizeof(params));
689 wpa_s->reassociate = 0;
690
691 params.freq = bss->freq;
692 params.bssid = bss->bssid;
693 params.ssid = bss->ssid;
694 params.ssid_len = bss->ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800695 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700696
Sunil Ravi640215c2023-06-28 23:08:09 +0000697 if (wpas_ml_element(wpa_s, bss, ssid)) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000698 wpa_printf(MSG_DEBUG, "MLD: In authentication");
699 params.mld = true;
700 params.mld_link_id = wpa_s->mlo_assoc_link_id;
701 params.ap_mld_addr = wpa_s->ap_mld_addr;
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000702 wpas_ml_handle_removed_links(wpa_s, bss);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000703 }
704
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705 if (wpa_s->sme.ssid_len != params.ssid_len ||
706 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
707 wpa_s->sme.prev_bssid_set = 0;
708
709 wpa_s->sme.freq = params.freq;
710 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
711 wpa_s->sme.ssid_len = params.ssid_len;
712
713 params.auth_alg = WPA_AUTH_ALG_OPEN;
714#ifdef IEEE8021X_EAPOL
715 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
716 if (ssid->leap) {
717 if (ssid->non_leap == 0)
718 params.auth_alg = WPA_AUTH_ALG_LEAP;
719 else
720 params.auth_alg |= WPA_AUTH_ALG_LEAP;
721 }
722 }
723#endif /* IEEE8021X_EAPOL */
724 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
725 params.auth_alg);
726 if (ssid->auth_alg) {
727 params.auth_alg = ssid->auth_alg;
728 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
729 "0x%x", params.auth_alg);
730 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800731#ifdef CONFIG_SAE
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800732 wpa_s->sme.sae_pmksa_caching = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800733 if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
734 const u8 *rsn;
735 struct wpa_ie_data ied;
736
737 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800738 if (!rsn) {
739 wpa_dbg(wpa_s, MSG_DEBUG,
740 "SAE enabled, but target BSS does not advertise RSN");
Hai Shalom021b0b52019-04-10 11:17:58 -0700741#ifdef CONFIG_DPP
742 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
743 (ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
744 (ied.key_mgmt & WPA_KEY_MGMT_DPP)) {
745 wpa_dbg(wpa_s, MSG_DEBUG, "Prefer DPP over SAE when both are enabled");
746#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800747 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
748 wpa_key_mgmt_sae(ied.key_mgmt)) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000749 if (wpas_is_sae_avoided(wpa_s, ssid, &ied)) {
750 wpa_dbg(wpa_s, MSG_DEBUG,
751 "SAE enabled, but disallowing SAE auth_alg without PMF");
752 } else {
753 wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
754 params.auth_alg = WPA_AUTH_ALG_SAE;
755 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800756 } else {
757 wpa_dbg(wpa_s, MSG_DEBUG,
758 "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800759 }
760 }
761#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700762
Hai Shalomfdcde762020-04-02 11:19:20 -0700763#ifdef CONFIG_WEP
764 {
765 int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700766
Hai Shalomfdcde762020-04-02 11:19:20 -0700767 for (i = 0; i < NUM_WEP_KEYS; i++) {
768 if (ssid->wep_key_len[i])
769 params.wep_key[i] = ssid->wep_key[i];
770 params.wep_key_len[i] = ssid->wep_key_len[i];
771 }
772 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
773 }
774#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700775
776 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
777 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800778 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700779 int try_opportunistic;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700780 const u8 *cache_id = NULL;
781
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800782 try_opportunistic = (ssid->proactive_key_caching < 0 ?
783 wpa_s->conf->okc :
784 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700785 (ssid->proto & WPA_PROTO_RSN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700786#ifdef CONFIG_FILS
787 if (wpa_key_mgmt_fils(ssid->key_mgmt))
788 cache_id = wpa_bss_get_fils_cache_id(bss);
789#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000790 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
791 params.mld ? params.ap_mld_addr :
792 bss->bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700793 wpa_s->current_ssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700794 try_opportunistic, cache_id,
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000795 0, false) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800796 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700797 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
798 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
799 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000800 &wpa_s->sme.assoc_req_ie_len,
801 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700802 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
803 "key management and encryption suites");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800804 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700805 return;
806 }
Hai Shalom74f70d42019-02-11 14:42:39 -0800807#ifdef CONFIG_HS20
808 } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
809 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
810 /* No PMKSA caching, but otherwise similar to RSN/WPA */
811 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
812 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
813 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000814 &wpa_s->sme.assoc_req_ie_len,
815 false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800816 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
817 "key management and encryption suites");
818 wpas_connect_work_done(wpa_s);
819 return;
820 }
821#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700822 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
823 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
824 /*
825 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
826 * use non-WPA since the scan results did not indicate that the
827 * AP is using WPA or WPA2.
828 */
829 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
830 wpa_s->sme.assoc_req_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800831 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700832 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
833 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
834 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000835 &wpa_s->sme.assoc_req_ie_len,
836 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700837 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
838 "key management and encryption suites (no "
839 "scan results)");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800840 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700841 return;
842 }
843#ifdef CONFIG_WPS
844 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
845 struct wpabuf *wps_ie;
846 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
847 if (wps_ie && wpabuf_len(wps_ie) <=
848 sizeof(wpa_s->sme.assoc_req_ie)) {
849 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
850 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
851 wpa_s->sme.assoc_req_ie_len);
852 } else
853 wpa_s->sme.assoc_req_ie_len = 0;
854 wpabuf_free(wps_ie);
855 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
856#endif /* CONFIG_WPS */
857 } else {
858 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
859 wpa_s->sme.assoc_req_ie_len = 0;
860 }
861
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800862 /* In case the WPA vendor IE is used, it should be placed after all the
863 * non-vendor IEs, as the lower layer expects the IEs to be ordered as
864 * defined in the standard. Store the WPA IE so it can later be
865 * inserted at the correct location.
866 */
867 wpa_ie = NULL;
868 wpa_ie_len = 0;
869 if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
870 wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
871 wpa_s->sme.assoc_req_ie_len);
872 if (wpa_ie) {
873 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
874
875 wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
876 wpa_s->sme.assoc_req_ie_len = 0;
877 } else {
878 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
879 wpas_connect_work_done(wpa_s);
880 return;
881 }
882 }
883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884#ifdef CONFIG_IEEE80211R
885 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
886 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
887 md = ie + 2;
888 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
Hai Shalom021b0b52019-04-10 11:17:58 -0700889 if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
890 !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
891 md = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700892 if (md) {
893 /* Prepare for the next transition */
894 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
895 }
896
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700897 if (md) {
898 wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
899 md[0], md[1]);
900
Hai Shalomfdcde762020-04-02 11:19:20 -0700901 omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700902 if (wpa_s->sme.assoc_req_ie_len + 5 <
903 sizeof(wpa_s->sme.assoc_req_ie)) {
904 struct rsn_mdie *mdie;
905 u8 *pos = wpa_s->sme.assoc_req_ie +
906 wpa_s->sme.assoc_req_ie_len;
907 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
908 *pos++ = sizeof(*mdie);
909 mdie = (struct rsn_mdie *) pos;
910 os_memcpy(mdie->mobility_domain, md,
911 MOBILITY_DOMAIN_ID_LEN);
912 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
913 wpa_s->sme.assoc_req_ie_len += 5;
914 }
915
Hai Shalom74f70d42019-02-11 14:42:39 -0800916 if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700917 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
Sunil Ravi77d572f2023-01-17 23:58:31 +0000918 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700919 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
920 "over-the-air");
921 params.auth_alg = WPA_AUTH_ALG_FT;
922 params.ie = wpa_s->sme.ft_ies;
923 params.ie_len = wpa_s->sme.ft_ies_len;
924 }
925 }
926#endif /* CONFIG_IEEE80211R */
927
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800928 wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800929 if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700930 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
931 struct wpa_ie_data _ie;
932 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
933 _ie.capabilities &
934 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
935 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
936 "MFP: require MFP");
937 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
938 }
939 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700940
941#ifdef CONFIG_P2P
942 if (wpa_s->global->p2p) {
943 u8 *pos;
944 size_t len;
945 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700946 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
947 len = sizeof(wpa_s->sme.assoc_req_ie) -
948 wpa_s->sme.assoc_req_ie_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800949 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
950 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700951 if (res >= 0)
952 wpa_s->sme.assoc_req_ie_len += res;
953 }
954#endif /* CONFIG_P2P */
955
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800956#ifdef CONFIG_FST
957 if (wpa_s->fst_ies) {
958 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
959
960 if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <=
961 sizeof(wpa_s->sme.assoc_req_ie)) {
962 os_memcpy(wpa_s->sme.assoc_req_ie +
963 wpa_s->sme.assoc_req_ie_len,
964 wpabuf_head(wpa_s->fst_ies),
965 fst_ies_len);
966 wpa_s->sme.assoc_req_ie_len += fst_ies_len;
967 }
968 }
969#endif /* CONFIG_FST */
970
971 sme_auth_handle_rrm(wpa_s, bss);
972
Dmitry Shmidt29333592017-01-09 12:27:11 -0800973 wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
Hai Shalomfdcde762020-04-02 11:19:20 -0700974 wpa_s, ssid, bss,
Dmitry Shmidt29333592017-01-09 12:27:11 -0800975 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
976 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800977
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700978 if (params.p2p)
979 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
980 else
981 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
982
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800983 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000984 sizeof(ext_capab), bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800985 if (ext_capab_len > 0) {
986 u8 *pos = wpa_s->sme.assoc_req_ie;
987 if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
988 pos += 2 + pos[1];
989 os_memmove(pos + ext_capab_len, pos,
990 wpa_s->sme.assoc_req_ie_len -
991 (pos - wpa_s->sme.assoc_req_ie));
992 wpa_s->sme.assoc_req_ie_len += ext_capab_len;
993 os_memcpy(pos, ext_capab, ext_capab_len);
994 }
995
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800996#ifdef CONFIG_TESTING_OPTIONS
997 if (wpa_s->rsnxe_override_assoc &&
998 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
999 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
1000 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
1001 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1002 wpabuf_head(wpa_s->rsnxe_override_assoc),
1003 wpabuf_len(wpa_s->rsnxe_override_assoc));
1004 wpa_s->sme.assoc_req_ie_len +=
1005 wpabuf_len(wpa_s->rsnxe_override_assoc);
1006 } else
1007#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -07001008 if (wpa_s->rsnxe_len > 0 &&
1009 wpa_s->rsnxe_len <=
Hai Shalomfdcde762020-04-02 11:19:20 -07001010 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len &&
1011 !omit_rsnxe) {
Hai Shalomc3565922019-10-28 11:58:20 -07001012 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1013 wpa_s->rsnxe, wpa_s->rsnxe_len);
1014 wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
1015 }
1016
Dmitry Shmidt04949592012-07-19 12:16:46 -07001017#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -08001018 if (is_hs20_network(wpa_s, ssid, bss)
1019#ifndef ANDROID /* Android does not use the native HS 2.0 config */
1020 && is_hs20_config(wpa_s)
1021#endif /* ANDROID */
1022 ) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07001023 struct wpabuf *hs20;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001024
Roshan Pius3a1667e2018-07-03 15:17:14 -07001025 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001026 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001027 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001028 size_t len;
1029
Hai Shalom74f70d42019-02-11 14:42:39 -08001030 wpas_hs20_add_indication(hs20, pps_mo_id,
1031 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001032 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -07001033 len = sizeof(wpa_s->sme.assoc_req_ie) -
1034 wpa_s->sme.assoc_req_ie_len;
1035 if (wpabuf_len(hs20) <= len) {
1036 os_memcpy(wpa_s->sme.assoc_req_ie +
1037 wpa_s->sme.assoc_req_ie_len,
1038 wpabuf_head(hs20), wpabuf_len(hs20));
1039 wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
1040 }
Dmitry Shmidt04949592012-07-19 12:16:46 -07001041 wpabuf_free(hs20);
1042 }
1043 }
1044#endif /* CONFIG_HS20 */
1045
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001046 if (wpa_ie) {
1047 size_t len;
1048
1049 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
1050
1051 len = sizeof(wpa_s->sme.assoc_req_ie) -
1052 wpa_s->sme.assoc_req_ie_len;
1053
1054 if (len > wpa_ie_len) {
1055 os_memcpy(wpa_s->sme.assoc_req_ie +
1056 wpa_s->sme.assoc_req_ie_len,
1057 wpa_ie, wpa_ie_len);
1058 wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
1059 } else {
1060 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
1061 }
1062
1063 os_free(wpa_ie);
1064 }
1065
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001066 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
1067 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
1068 size_t len;
1069
1070 len = sizeof(wpa_s->sme.assoc_req_ie) -
1071 wpa_s->sme.assoc_req_ie_len;
1072 if (wpabuf_len(buf) <= len) {
1073 os_memcpy(wpa_s->sme.assoc_req_ie +
1074 wpa_s->sme.assoc_req_ie_len,
1075 wpabuf_head(buf), wpabuf_len(buf));
1076 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
1077 }
1078 }
1079
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001080#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07001081 mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001082 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001083 int len;
1084
1085 len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
1086 wpa_s->sme.assoc_req_ie_len,
1087 sizeof(wpa_s->sme.assoc_req_ie) -
Hai Shalomce48b4a2018-09-05 11:41:35 -07001088 wpa_s->sme.assoc_req_ie_len,
1089 !!mbo_attr_from_mbo_ie(mbo_ie,
1090 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001091 if (len >= 0)
1092 wpa_s->sme.assoc_req_ie_len += len;
1093 }
1094#endif /* CONFIG_MBO */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001095
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001096#ifdef CONFIG_SAE
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001097 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001098 pmksa_cache_set_current(wpa_s->wpa, NULL,
1099 params.mld ? params.ap_mld_addr :
1100 bss->bssid,
1101 ssid, 0,
Hai Shalom021b0b52019-04-10 11:17:58 -07001102 NULL,
Sunil Ravi89eba102022-09-13 21:04:37 -07001103 wpa_key_mgmt_sae(wpa_s->key_mgmt) ?
1104 wpa_s->key_mgmt :
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001105 (int) WPA_KEY_MGMT_SAE, false) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001106 wpa_dbg(wpa_s, MSG_DEBUG,
1107 "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001108 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001109 params.auth_alg = WPA_AUTH_ALG_OPEN;
1110 wpa_s->sme.sae_pmksa_caching = 1;
1111 }
1112
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001113 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001114 if (start)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001115 resp = sme_auth_build_sae_commit(wpa_s, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001116 bss->bssid,
1117 params.mld ?
1118 params.ap_mld_addr :
1119 NULL, 0,
Hai Shalom899fcc72020-10-19 14:38:18 -07001120 start == 2, NULL,
1121 NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001122 else
Roshan Pius3a1667e2018-07-03 15:17:14 -07001123 resp = sme_auth_build_sae_confirm(wpa_s, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001124 if (resp == NULL) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001125 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001126 return;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001127 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001128 params.auth_data = wpabuf_head(resp);
1129 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001130 wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001131 }
1132#endif /* CONFIG_SAE */
1133
Hai Shalomfdcde762020-04-02 11:19:20 -07001134 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1135 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1136 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1137 if (bssid_changed)
1138 wpas_notify_bssid_changed(wpa_s);
1139
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001140 old_ssid = wpa_s->current_ssid;
1141 wpa_s->current_ssid = ssid;
1142 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1143 wpa_supplicant_initiate_eapol(wpa_s);
1144
1145#ifdef CONFIG_FILS
1146 /* TODO: FILS operations can in some cases be done between different
1147 * network_ctx (i.e., same credentials can be used with multiple
1148 * networks). */
1149 if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
1150 wpa_key_mgmt_fils(ssid->key_mgmt)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001151 const u8 *indic;
1152 u16 fils_info;
Hai Shalomce48b4a2018-09-05 11:41:35 -07001153 const u8 *realm, *username, *rrk;
1154 size_t realm_len, username_len, rrk_len;
1155 u16 next_seq_num;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001156
1157 /*
1158 * Check FILS Indication element (FILS Information field) bits
1159 * indicating supported authentication algorithms against local
1160 * configuration (ssid->fils_dh_group). Try to use FILS
1161 * authentication only if the AP supports the combination in the
1162 * network profile. */
1163 indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
1164 if (!indic || indic[1] < 2) {
1165 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1166 " does not include FILS Indication element - cannot use FILS authentication with it",
1167 MAC2STR(bss->bssid));
1168 goto no_fils;
1169 }
1170
1171 fils_info = WPA_GET_LE16(indic + 2);
1172 if (ssid->fils_dh_group == 0 && !(fils_info & BIT(9))) {
1173 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1174 " does not support FILS SK without PFS - cannot use FILS authentication with it",
1175 MAC2STR(bss->bssid));
1176 goto no_fils;
1177 }
1178 if (ssid->fils_dh_group != 0 && !(fils_info & BIT(10))) {
1179 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1180 " does not support FILS SK with PFS - cannot use FILS authentication with it",
1181 MAC2STR(bss->bssid));
1182 goto no_fils;
1183 }
1184
Hai Shalomce48b4a2018-09-05 11:41:35 -07001185 if (wpa_s->last_con_fail_realm &&
1186 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
1187 &username, &username_len,
1188 &realm, &realm_len, &next_seq_num,
1189 &rrk, &rrk_len) == 0 &&
1190 realm && realm_len == wpa_s->last_con_fail_realm_len &&
1191 os_memcmp(realm, wpa_s->last_con_fail_realm,
1192 realm_len) == 0) {
1193 wpa_printf(MSG_DEBUG,
1194 "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
1195 goto no_fils;
1196 }
1197
Sunil Ravi77d572f2023-01-17 23:58:31 +00001198 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
1199 params.mld ? params.ap_mld_addr :
1200 bss->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001201 ssid, 0,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001202 wpa_bss_get_fils_cache_id(bss),
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001203 0, false) == 0)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001204 wpa_printf(MSG_DEBUG,
1205 "SME: Try to use FILS with PMKSA caching");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001206 resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001207 if (resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001208 int auth_alg;
1209
1210 if (ssid->fils_dh_group)
1211 wpa_printf(MSG_DEBUG,
1212 "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
1213 ssid->fils_dh_group);
1214 else
1215 wpa_printf(MSG_DEBUG,
1216 "SME: Try to use FILS SK authentication without PFS");
1217 auth_alg = ssid->fils_dh_group ?
1218 WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
1219 params.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001220 params.auth_data = wpabuf_head(resp);
1221 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001222 wpa_s->sme.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001223 }
1224 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001225no_fils:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001226#endif /* CONFIG_FILS */
1227
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001228 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001229 wpa_supplicant_cancel_scan(wpa_s);
1230
1231 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
1232 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
1233 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
1234
Hai Shalome21d4e82020-04-29 16:34:06 -07001235 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001236 wpa_clear_keys(wpa_s, bss->bssid);
1237 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001238 if (old_ssid != wpa_s->current_ssid)
1239 wpas_notify_network_changed(wpa_s);
1240
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001241#ifdef CONFIG_HS20
1242 hs20_configure_frame_filters(wpa_s);
1243#endif /* CONFIG_HS20 */
1244
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001245#ifdef CONFIG_P2P
1246 /*
1247 * If multi-channel concurrency is not supported, check for any
1248 * frequency conflict. In case of any frequency conflict, remove the
1249 * least prioritized connection.
1250 */
1251 if (wpa_s->num_multichan_concurrent < 2) {
1252 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001253 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001254 if (num > 0 && freq > 0 && freq != params.freq) {
1255 wpa_printf(MSG_DEBUG,
1256 "Conflicting frequency found (%d != %d)",
1257 freq, params.freq);
1258 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1259 params.freq,
1260 ssid) < 0) {
1261 wpas_connection_failed(wpa_s, bss->bssid);
1262 wpa_supplicant_mark_disassoc(wpa_s);
1263 wpabuf_free(resp);
1264 wpas_connect_work_done(wpa_s);
1265 return;
1266 }
1267 }
1268 }
1269#endif /* CONFIG_P2P */
1270
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001271 if (skip_auth) {
1272 wpa_msg(wpa_s, MSG_DEBUG,
1273 "SME: Skip authentication step on reassoc-to-same-BSS");
1274 wpabuf_free(resp);
1275 sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN);
1276 return;
1277 }
1278
1279
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001280 wpa_s->sme.auth_alg = params.auth_alg;
1281 if (wpa_drv_authenticate(wpa_s, &params) < 0) {
1282 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
1283 "driver failed");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001284 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001285 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001286 wpabuf_free(resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001287 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001288 return;
1289 }
1290
1291 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
1292 NULL);
1293
1294 /*
1295 * Association will be started based on the authentication event from
1296 * the driver.
1297 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001298
1299 wpabuf_free(resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300}
1301
1302
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001303static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
1304{
1305 struct wpa_connect_work *cwork = work->ctx;
1306 struct wpa_supplicant *wpa_s = work->wpa_s;
1307
Hai Shaloma20dcd72022-02-04 13:43:00 -08001308 wpa_s->roam_in_progress = false;
1309#ifdef CONFIG_WNM
1310 wpa_s->bss_trans_mgmt_in_progress = false;
1311#endif /* CONFIG_WNM */
1312
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001313 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001314 if (work->started)
1315 wpa_s->connect_work = NULL;
1316
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001317 wpas_connect_work_free(cwork);
1318 return;
1319 }
1320
1321 wpa_s->connect_work = work;
1322
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001323 if (cwork->bss_removed ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001324 !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
1325 wpas_network_disabled(wpa_s, cwork->ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001326 wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
1327 wpas_connect_work_done(wpa_s);
1328 return;
1329 }
1330
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001331 /* Starting new connection, so clear the possibly used WPA IE from the
1332 * previous association. */
1333 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07001334 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
1335 wpa_s->rsnxe_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001336
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001337 sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001338 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001339}
1340
1341
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001342void sme_authenticate(struct wpa_supplicant *wpa_s,
1343 struct wpa_bss *bss, struct wpa_ssid *ssid)
1344{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001345 struct wpa_connect_work *cwork;
1346
1347 if (bss == NULL || ssid == NULL)
1348 return;
1349 if (wpa_s->connect_work) {
1350 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
1351 return;
1352 }
1353
Hai Shaloma20dcd72022-02-04 13:43:00 -08001354 if (wpa_s->roam_in_progress) {
1355 wpa_dbg(wpa_s, MSG_DEBUG,
1356 "SME: Reject sme_authenticate() in favor of explicit roam request");
1357 return;
1358 }
1359#ifdef CONFIG_WNM
1360 if (wpa_s->bss_trans_mgmt_in_progress) {
1361 wpa_dbg(wpa_s, MSG_DEBUG,
1362 "SME: Reject sme_authenticate() in favor of BSS transition management request");
1363 return;
1364 }
1365#endif /* CONFIG_WNM */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001366 if (radio_work_pending(wpa_s, "sme-connect")) {
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001367 /*
1368 * The previous sme-connect work might no longer be valid due to
1369 * the fact that the BSS list was updated. In addition, it makes
1370 * sense to adhere to the 'newer' decision.
1371 */
1372 wpa_dbg(wpa_s, MSG_DEBUG,
1373 "SME: Remove previous pending sme-connect");
1374 radio_remove_works(wpa_s, "sme-connect", 0);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001375 }
1376
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001377 wpas_abort_ongoing_scan(wpa_s);
1378
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001379 cwork = os_zalloc(sizeof(*cwork));
1380 if (cwork == NULL)
1381 return;
1382 cwork->bss = bss;
1383 cwork->ssid = ssid;
1384 cwork->sme = 1;
1385
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001386#ifdef CONFIG_SAE
1387 wpa_s->sme.sae.state = SAE_NOTHING;
1388 wpa_s->sme.sae.send_confirm = 0;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001389 wpa_s->sme.sae_group_index = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001390#endif /* CONFIG_SAE */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001391
1392 if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
1393 sme_auth_start_cb, cwork) < 0)
1394 wpas_connect_work_free(cwork);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001395}
1396
1397
1398#ifdef CONFIG_SAE
1399
Sunil Ravi036cec52023-03-29 11:35:17 -07001400#define WPA_AUTH_FRAME_ML_IE_LEN (6 + ETH_ALEN)
1401
1402static void wpa_auth_ml_ie(struct wpabuf *buf, const u8 *mld_addr)
1403{
1404
1405 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1406 wpabuf_put_u8(buf, 4 + ETH_ALEN);
1407 wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK);
1408
1409 /* Basic Multi-Link element Control field */
1410 wpabuf_put_u8(buf, 0x0);
1411 wpabuf_put_u8(buf, 0x0);
1412
1413 /* Common Info */
1414 wpabuf_put_u8(buf, 0x7); /* length = Length field + MLD MAC address */
1415 wpabuf_put_data(buf, mld_addr, ETH_ALEN);
1416}
1417
1418
Roshan Pius3a1667e2018-07-03 15:17:14 -07001419static int sme_external_auth_build_buf(struct wpabuf *buf,
1420 struct wpabuf *params,
1421 const u8 *sa, const u8 *da,
Hai Shalomc3565922019-10-28 11:58:20 -07001422 u16 auth_transaction, u16 seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001423 u16 status_code, const u8 *mld_addr)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001424{
1425 struct ieee80211_mgmt *resp;
1426
1427 resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
1428 u.auth.variable));
1429
1430 resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
1431 (WLAN_FC_STYPE_AUTH << 4));
1432 os_memcpy(resp->da, da, ETH_ALEN);
1433 os_memcpy(resp->sa, sa, ETH_ALEN);
1434 os_memcpy(resp->bssid, da, ETH_ALEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08001435 resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
1436 resp->seq_ctrl = host_to_le16(seq_num << 4);
1437 resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
Hai Shalomc3565922019-10-28 11:58:20 -07001438 resp->u.auth.status_code = host_to_le16(status_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001439 if (params)
1440 wpabuf_put_buf(buf, params);
1441
Sunil Ravi036cec52023-03-29 11:35:17 -07001442 if (mld_addr)
1443 wpa_auth_ml_ie(buf, mld_addr);
1444
Roshan Pius3a1667e2018-07-03 15:17:14 -07001445 return 0;
1446}
1447
1448
Hai Shalom81f62d82019-07-22 12:10:00 -07001449static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
1450 const u8 *bssid,
1451 struct wpa_ssid *ssid)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001452{
1453 struct wpabuf *resp, *buf;
Hai Shalomc3565922019-10-28 11:58:20 -07001454 int use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -07001455 bool use_pk;
1456 u16 status;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001457
Sunil Ravi036cec52023-03-29 11:35:17 -07001458 resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid,
1459 wpa_s->sme.ext_ml_auth ?
1460 wpa_s->sme.ext_auth_ap_mld_addr : NULL,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001461 1, 0, &use_pt, &use_pk);
Hai Shalom81f62d82019-07-22 12:10:00 -07001462 if (!resp) {
1463 wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
1464 return -1;
1465 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001466
1467 wpa_s->sme.sae.state = SAE_COMMITTED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001468 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp) +
1469 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1470 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001471 if (!buf) {
1472 wpabuf_free(resp);
Hai Shalom81f62d82019-07-22 12:10:00 -07001473 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001474 }
1475
1476 wpa_s->sme.seq_num++;
Hai Shalom899fcc72020-10-19 14:38:18 -07001477 if (use_pk)
1478 status = WLAN_STATUS_SAE_PK;
1479 else if (use_pt)
1480 status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
1481 else
1482 status = WLAN_STATUS_SUCCESS;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001483 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Sunil Ravi036cec52023-03-29 11:35:17 -07001484 wpa_s->sme.ext_ml_auth ?
1485 wpa_s->sme.ext_auth_ap_mld_addr : bssid, 1,
1486 wpa_s->sme.seq_num, status,
1487 wpa_s->sme.ext_ml_auth ?
1488 wpa_s->own_addr : NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07001489 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001490 wpabuf_free(resp);
1491 wpabuf_free(buf);
Hai Shalom81f62d82019-07-22 12:10:00 -07001492
1493 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001494}
1495
1496
1497static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
1498 u16 status)
1499{
1500 struct external_auth params;
1501
Sunil Ravi89eba102022-09-13 21:04:37 -07001502 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001503 os_memset(&params, 0, sizeof(params));
1504 params.status = status;
Hai Shalom66904732019-05-29 11:54:04 -07001505 params.ssid = wpa_s->sme.ext_auth_ssid;
1506 params.ssid_len = wpa_s->sme.ext_auth_ssid_len;
1507 params.bssid = wpa_s->sme.ext_auth_bssid;
Hai Shalomc3565922019-10-28 11:58:20 -07001508 if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
1509 params.pmkid = wpa_s->sme.sae.pmkid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001510 wpa_drv_send_external_auth_status(wpa_s, &params);
1511}
1512
1513
Hai Shalom81f62d82019-07-22 12:10:00 -07001514static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
1515 union wpa_event_data *data)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001516{
1517 struct wpa_ssid *ssid;
1518 size_t ssid_str_len = data->external_auth.ssid_len;
Hai Shalom5f92bc92019-04-18 11:54:11 -07001519 const u8 *ssid_str = data->external_auth.ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001520
Sunil Ravi89eba102022-09-13 21:04:37 -07001521 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001522 /* Get the SSID conf from the ssid string obtained */
1523 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1524 if (!wpas_network_disabled(wpa_s, ssid) &&
1525 ssid_str_len == ssid->ssid_len &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001526 os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001527 wpa_key_mgmt_sae(ssid->key_mgmt)) {
1528 /* Make sure PT is derived */
Sunil Ravi036cec52023-03-29 11:35:17 -07001529 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Sunil Ravi89eba102022-09-13 21:04:37 -07001530 wpa_s->sme.ext_auth_wpa_ssid = ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001531 break;
Sunil Ravi89eba102022-09-13 21:04:37 -07001532 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001533 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001534 if (!ssid ||
1535 sme_external_auth_send_sae_commit(wpa_s, data->external_auth.bssid,
1536 ssid) < 0)
1537 return -1;
1538
1539 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001540}
1541
1542
1543static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
1544 const u8 *da)
1545{
1546 struct wpabuf *resp, *buf;
1547
1548 resp = sme_auth_build_sae_confirm(wpa_s, 1);
1549 if (!resp) {
1550 wpa_printf(MSG_DEBUG, "SAE: Confirm message buf alloc failure");
1551 return;
1552 }
1553
1554 wpa_s->sme.sae.state = SAE_CONFIRMED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001555 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp) +
1556 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1557 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001558 if (!buf) {
1559 wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure");
1560 wpabuf_free(resp);
1561 return;
1562 }
1563 wpa_s->sme.seq_num++;
1564 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Hai Shalomc3565922019-10-28 11:58:20 -07001565 da, 2, wpa_s->sme.seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001566 WLAN_STATUS_SUCCESS,
1567 wpa_s->sme.ext_ml_auth ?
1568 wpa_s->own_addr : NULL);
1569
Hai Shalomfdcde762020-04-02 11:19:20 -07001570 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001571 wpabuf_free(resp);
1572 wpabuf_free(buf);
1573}
1574
1575
Sunil Ravi77d572f2023-01-17 23:58:31 +00001576static bool is_sae_key_mgmt_suite(struct wpa_supplicant *wpa_s, u32 suite)
1577{
1578 /* suite is supposed to be the selector value in host byte order with
1579 * the OUI in three most significant octets. However, the initial
1580 * implementation swapped that byte order and did not work with drivers
1581 * that followed the expected byte order. Keep a workaround here to
1582 * match that initial implementation so that already deployed use cases
1583 * remain functional. */
1584 if (RSN_SELECTOR_GET(&suite) == RSN_AUTH_KEY_MGMT_SAE) {
1585 /* Old drivers which follow initial implementation send SAE AKM
1586 * for both SAE and FT-SAE connections. In that case, determine
1587 * the actual AKM from wpa_s->key_mgmt. */
1588 wpa_s->sme.ext_auth_key_mgmt = wpa_s->key_mgmt;
1589 return true;
1590 }
1591
1592 if (suite == RSN_AUTH_KEY_MGMT_SAE)
1593 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE;
1594 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE)
1595 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE;
1596 else if (suite == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
1597 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1598 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
1599 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1600 else
1601 return false;
1602
1603 return true;
1604}
1605
1606
Roshan Pius3a1667e2018-07-03 15:17:14 -07001607void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
1608 union wpa_event_data *data)
1609{
Sunil Ravi77d572f2023-01-17 23:58:31 +00001610 if (!is_sae_key_mgmt_suite(wpa_s, data->external_auth.key_mgmt_suite))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001611 return;
1612
1613 if (data->external_auth.action == EXT_AUTH_START) {
Hai Shalom66904732019-05-29 11:54:04 -07001614 if (!data->external_auth.bssid || !data->external_auth.ssid)
1615 return;
1616 os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid,
1617 ETH_ALEN);
1618 os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid,
1619 data->external_auth.ssid_len);
1620 wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len;
Sunil Ravi036cec52023-03-29 11:35:17 -07001621 if (data->external_auth.mld_addr) {
1622 wpa_s->sme.ext_ml_auth = true;
1623 os_memcpy(wpa_s->sme.ext_auth_ap_mld_addr,
1624 data->external_auth.mld_addr, ETH_ALEN);
1625 } else {
1626 wpa_s->sme.ext_ml_auth = false;
1627 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001628 wpa_s->sme.seq_num = 0;
1629 wpa_s->sme.sae.state = SAE_NOTHING;
1630 wpa_s->sme.sae.send_confirm = 0;
1631 wpa_s->sme.sae_group_index = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001632 if (sme_handle_external_auth_start(wpa_s, data) < 0)
1633 sme_send_external_auth_status(wpa_s,
1634 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001635 } else if (data->external_auth.action == EXT_AUTH_ABORT) {
1636 /* Report failure to driver for the wrong trigger */
1637 sme_send_external_auth_status(wpa_s,
1638 WLAN_STATUS_UNSPECIFIED_FAILURE);
1639 }
1640}
1641
1642
Hai Shalomc3565922019-10-28 11:58:20 -07001643static int sme_sae_is_group_enabled(struct wpa_supplicant *wpa_s, int group)
1644{
1645 int *groups = wpa_s->conf->sae_groups;
1646 int default_groups[] = { 19, 20, 21, 0 };
1647 int i;
1648
1649 if (!groups)
1650 groups = default_groups;
1651
1652 for (i = 0; groups[i] > 0; i++) {
1653 if (groups[i] == group)
1654 return 1;
1655 }
1656
1657 return 0;
1658}
1659
1660
1661static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
1662 const struct wpabuf *groups)
1663{
1664 size_t i, count;
1665 const u8 *pos;
1666
1667 if (!groups)
1668 return 0;
1669
1670 pos = wpabuf_head(groups);
1671 count = wpabuf_len(groups) / 2;
1672 for (i = 0; i < count; i++) {
1673 int enabled;
1674 u16 group;
1675
1676 group = WPA_GET_LE16(pos);
1677 pos += 2;
1678 enabled = sme_sae_is_group_enabled(wpa_s, group);
1679 wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
1680 group, enabled ? "enabled" : "disabled");
1681 if (enabled)
1682 return 1;
1683 }
1684
1685 return 0;
1686}
1687
1688
Sunil Ravi036cec52023-03-29 11:35:17 -07001689static int sme_external_ml_auth(struct wpa_supplicant *wpa_s,
Sunil Ravi640215c2023-06-28 23:08:09 +00001690 const u8 *data, size_t len, int ie_offset,
1691 u16 status_code)
Sunil Ravi036cec52023-03-29 11:35:17 -07001692{
1693 struct ieee802_11_elems elems;
1694 const u8 *mld_addr;
1695
1696 if (ieee802_11_parse_elems(data + ie_offset, len - ie_offset,
Sunil Ravi640215c2023-06-28 23:08:09 +00001697 &elems, 0) == ParseFailed) {
Sunil Ravi036cec52023-03-29 11:35:17 -07001698 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
1699 return -1;
1700 }
1701
1702 if (!elems.basic_mle || !elems.basic_mle_len) {
1703 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
Sunil Ravi640215c2023-06-28 23:08:09 +00001704 if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
1705 status_code == WLAN_STATUS_SUCCESS ||
1706 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
1707 status_code == WLAN_STATUS_SAE_PK)
1708 return -1;
1709 /* Accept missing Multi-Link element in failed authentication
1710 * cases. */
1711 return 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07001712 }
1713
1714 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
1715 if (!mld_addr) {
1716 wpa_printf(MSG_DEBUG, "MLD: No MLD address in ML element");
1717 return -1;
1718 }
1719
1720 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
1721
1722 if (os_memcmp(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr, ETH_ALEN) !=
1723 0) {
1724 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
Sunil Ravi640215c2023-06-28 23:08:09 +00001725 MACSTR ")",
1726 MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr));
Sunil Ravi036cec52023-03-29 11:35:17 -07001727 return -1;
1728 }
1729
1730 return 0;
1731}
1732
1733
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001734static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001735 u16 status_code, const u8 *data, size_t len,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001736 int external, const u8 *sa, int *ie_offset)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001737{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001738 int *groups;
1739
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001740 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
1741 "status code %u", auth_transaction, status_code);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001742
1743 if (auth_transaction == 1 &&
1744 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1745 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001746 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1747 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001748 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001749 u16 group;
Hai Shalomfdcde762020-04-02 11:19:20 -07001750 const u8 *token_pos;
1751 size_t token_len;
1752 int h2e = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001753
1754 groups = wpa_s->conf->sae_groups;
1755 if (!groups || groups[0] <= 0)
1756 groups = default_groups;
1757
Hai Shalomfdcde762020-04-02 11:19:20 -07001758 wpa_hexdump(MSG_DEBUG, "SME: SAE anti-clogging token request",
1759 data, len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001760 if (len < sizeof(le16)) {
1761 wpa_dbg(wpa_s, MSG_DEBUG,
1762 "SME: Too short SAE anti-clogging token request");
1763 return -1;
1764 }
1765 group = WPA_GET_LE16(data);
1766 wpa_dbg(wpa_s, MSG_DEBUG,
1767 "SME: SAE anti-clogging token requested (group %u)",
1768 group);
1769 if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
1770 WLAN_STATUS_SUCCESS) {
1771 wpa_dbg(wpa_s, MSG_ERROR,
1772 "SME: SAE group %u of anti-clogging request is invalid",
1773 group);
1774 return -1;
1775 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001776 wpabuf_free(wpa_s->sme.sae_token);
Hai Shalomfdcde762020-04-02 11:19:20 -07001777 token_pos = data + sizeof(le16);
1778 token_len = len - sizeof(le16);
Hai Shalom899fcc72020-10-19 14:38:18 -07001779 h2e = wpa_s->sme.sae.h2e;
Hai Shalomfdcde762020-04-02 11:19:20 -07001780 if (h2e) {
Sunil8cd6f4d2022-06-28 18:40:46 +00001781 u8 id, elen, extid;
1782
Hai Shalomfdcde762020-04-02 11:19:20 -07001783 if (token_len < 3) {
1784 wpa_dbg(wpa_s, MSG_DEBUG,
1785 "SME: Too short SAE anti-clogging token container");
1786 return -1;
1787 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001788 id = *token_pos++;
1789 elen = *token_pos++;
1790 extid = *token_pos++;
1791 if (id != WLAN_EID_EXTENSION ||
1792 elen == 0 || elen > token_len - 2 ||
1793 extid != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001794 wpa_dbg(wpa_s, MSG_DEBUG,
1795 "SME: Invalid SAE anti-clogging token container header");
1796 return -1;
1797 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001798 token_len = elen - 1;
Hai Shalomfdcde762020-04-02 11:19:20 -07001799 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00001800
Sunil Ravi036cec52023-03-29 11:35:17 -07001801 *ie_offset = token_pos + token_len - data;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001802
Hai Shalomfdcde762020-04-02 11:19:20 -07001803 wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001804 if (!wpa_s->sme.sae_token) {
1805 wpa_dbg(wpa_s, MSG_ERROR,
1806 "SME: Failed to allocate SAE token");
1807 return -1;
1808 }
1809
Hai Shalomfdcde762020-04-02 11:19:20 -07001810 wpa_hexdump_buf(MSG_DEBUG, "SME: Requested anti-clogging token",
1811 wpa_s->sme.sae_token);
Sunil Ravi036cec52023-03-29 11:35:17 -07001812 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001813 sme_send_authentication(wpa_s, wpa_s->current_bss,
Hai Shalom021b0b52019-04-10 11:17:58 -07001814 wpa_s->current_ssid, 2);
Sunil Ravi036cec52023-03-29 11:35:17 -07001815 } else {
1816 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001817 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1818 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001819 return -1;
1820
Roshan Pius3a1667e2018-07-03 15:17:14 -07001821 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001822 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001823 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001824 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001825 return 0;
1826 }
1827
1828 if (auth_transaction == 1 &&
1829 status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1830 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001831 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1832 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001833 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
Hai Shalomc3565922019-10-28 11:58:20 -07001834 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1835 wpa_s->sme.sae.group);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001836 wpa_s->sme.sae_group_index++;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001837 if (sme_set_sae_group(wpa_s, external) < 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001838 return -1; /* no other groups enabled */
1839 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
Sunil Ravi036cec52023-03-29 11:35:17 -07001840 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001841 sme_send_authentication(wpa_s, wpa_s->current_bss,
1842 wpa_s->current_ssid, 1);
Sunil Ravi036cec52023-03-29 11:35:17 -07001843 } else {
1844 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001845 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1846 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001847 return -1;
1848
Roshan Pius3a1667e2018-07-03 15:17:14 -07001849 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001850 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001851 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001852 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001853 return 0;
1854 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001855
Roshan Pius3a1667e2018-07-03 15:17:14 -07001856 if (auth_transaction == 1 &&
1857 status_code == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1858 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1859
1860 wpa_msg(wpa_s, MSG_INFO,
1861 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR,
1862 MAC2STR(bssid));
1863 return -1;
1864 }
1865
Hai Shalomc3565922019-10-28 11:58:20 -07001866 if (status_code != WLAN_STATUS_SUCCESS &&
Hai Shalom899fcc72020-10-19 14:38:18 -07001867 status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08001868 status_code != WLAN_STATUS_SAE_PK) {
1869 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1870
1871 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
1872 " auth_type=%u auth_transaction=%u status_code=%u",
1873 MAC2STR(bssid), WLAN_AUTH_SAE,
1874 auth_transaction, status_code);
Sunil Ravia04bd252022-05-02 22:54:18 -07001875 return -2;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001876 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001877
1878 if (auth_transaction == 1) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07001879 u16 res;
1880
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001881 groups = wpa_s->conf->sae_groups;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001882
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001883 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
Sunil Ravi89eba102022-09-13 21:04:37 -07001884 if ((external && !wpa_s->sme.ext_auth_wpa_ssid) ||
1885 (!external &&
1886 (!wpa_s->current_bss || !wpa_s->current_ssid)))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001887 return -1;
Hai Shalomc3565922019-10-28 11:58:20 -07001888 if (wpa_s->sme.sae.state != SAE_COMMITTED) {
1889 wpa_printf(MSG_DEBUG,
1890 "SAE: Ignore commit message while waiting for confirm");
1891 return 0;
1892 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001893 if (wpa_s->sme.sae.h2e && status_code == WLAN_STATUS_SUCCESS) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001894 wpa_printf(MSG_DEBUG,
1895 "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
1896 return -1;
1897 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001898 if ((!wpa_s->sme.sae.h2e || wpa_s->sme.sae.pk) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001899 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
1900 wpa_printf(MSG_DEBUG,
1901 "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
1902 return -1;
1903 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001904 if (!wpa_s->sme.sae.pk &&
1905 status_code == WLAN_STATUS_SAE_PK) {
1906 wpa_printf(MSG_DEBUG,
1907 "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected");
1908 return -1;
1909 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001910
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001911 if (groups && groups[0] <= 0)
1912 groups = NULL;
Dmitry Shmidt41712582015-06-29 11:02:15 -07001913 res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
Hai Shalomc3565922019-10-28 11:58:20 -07001914 groups, status_code ==
Hai Shalom899fcc72020-10-19 14:38:18 -07001915 WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001916 status_code == WLAN_STATUS_SAE_PK,
1917 ie_offset);
Dmitry Shmidt41712582015-06-29 11:02:15 -07001918 if (res == SAE_SILENTLY_DISCARD) {
1919 wpa_printf(MSG_DEBUG,
1920 "SAE: Drop commit message due to reflection attack");
1921 return 0;
1922 }
1923 if (res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001924 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001925
Hai Shalomc3565922019-10-28 11:58:20 -07001926 if (wpa_s->sme.sae.tmp &&
1927 sme_check_sae_rejected_groups(
1928 wpa_s,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001929 wpa_s->sme.sae.tmp->peer_rejected_groups))
Hai Shalomc3565922019-10-28 11:58:20 -07001930 return -1;
1931
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001932 if (sae_process_commit(&wpa_s->sme.sae) < 0) {
1933 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
1934 "commit");
1935 return -1;
1936 }
1937
1938 wpabuf_free(wpa_s->sme.sae_token);
1939 wpa_s->sme.sae_token = NULL;
Sunil Ravi036cec52023-03-29 11:35:17 -07001940 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001941 sme_send_authentication(wpa_s, wpa_s->current_bss,
1942 wpa_s->current_ssid, 0);
Sunil Ravi036cec52023-03-29 11:35:17 -07001943 } else {
1944 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001945 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1946 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001947 return -1;
1948
Roshan Pius3a1667e2018-07-03 15:17:14 -07001949 sme_external_auth_send_sae_confirm(wpa_s, sa);
Sunil Ravi036cec52023-03-29 11:35:17 -07001950 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001951 return 0;
1952 } else if (auth_transaction == 2) {
Hai Shalomc3565922019-10-28 11:58:20 -07001953 if (status_code != WLAN_STATUS_SUCCESS)
1954 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001955 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001956 if (wpa_s->sme.sae.state != SAE_CONFIRMED)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001957 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001958 if (sae_check_confirm(&wpa_s->sme.sae, data, len,
1959 ie_offset) < 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001960 return -1;
Sunil Ravi036cec52023-03-29 11:35:17 -07001961 if (external && wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001962 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1963 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001964 return -1;
1965
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001966 wpa_s->sme.sae.state = SAE_ACCEPTED;
1967 sae_clear_temp_data(&wpa_s->sme.sae);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001968
1969 if (external) {
1970 /* Report success to driver */
1971 sme_send_external_auth_status(wpa_s,
1972 WLAN_STATUS_SUCCESS);
1973 }
1974
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001975 return 1;
1976 }
1977
1978 return -1;
1979}
Roshan Pius3a1667e2018-07-03 15:17:14 -07001980
1981
Hai Shalomc3565922019-10-28 11:58:20 -07001982static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
1983{
1984 wpa_printf(MSG_DEBUG,
1985 "SME: SAE completed - setting PMK for 4-way handshake");
Sunil Ravi89eba102022-09-13 21:04:37 -07001986 wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, wpa_s->sme.sae.pmk_len,
Hai Shalomc3565922019-10-28 11:58:20 -07001987 wpa_s->sme.sae.pmkid, bssid);
1988 if (wpa_s->conf->sae_pmkid_in_assoc) {
1989 /* Update the own RSNE contents now that we have set the PMK
1990 * and added a PMKSA cache entry based on the successfully
1991 * completed SAE exchange. In practice, this will add the PMKID
1992 * into RSNE. */
1993 if (wpa_s->sme.assoc_req_ie_len + 2 + PMKID_LEN >
1994 sizeof(wpa_s->sme.assoc_req_ie)) {
1995 wpa_msg(wpa_s, MSG_WARNING,
1996 "RSN: Not enough room for inserting own PMKID into RSNE");
1997 return -1;
1998 }
1999 if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
2000 &wpa_s->sme.assoc_req_ie_len,
2001 wpa_s->sme.sae.pmkid) < 0)
2002 return -1;
2003 wpa_hexdump(MSG_DEBUG,
2004 "SME: Updated Association Request IEs",
2005 wpa_s->sme.assoc_req_ie,
2006 wpa_s->sme.assoc_req_ie_len);
2007 }
2008
2009 return 0;
2010}
2011
2012
Roshan Pius3a1667e2018-07-03 15:17:14 -07002013void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
2014 const u8 *auth_frame, size_t len)
2015{
2016 const struct ieee80211_mgmt *header;
2017 size_t auth_length;
2018
2019 header = (const struct ieee80211_mgmt *) auth_frame;
2020 auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);
2021
2022 if (len < auth_length) {
2023 /* Notify failure to the driver */
2024 sme_send_external_auth_status(wpa_s,
2025 WLAN_STATUS_UNSPECIFIED_FAILURE);
2026 return;
2027 }
2028
Hai Shalom74f70d42019-02-11 14:42:39 -08002029 if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002030 int res;
Sunil Ravi036cec52023-03-29 11:35:17 -07002031 int ie_offset = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002032
Hai Shalom74f70d42019-02-11 14:42:39 -08002033 res = sme_sae_auth(
2034 wpa_s, le_to_host16(header->u.auth.auth_transaction),
2035 le_to_host16(header->u.auth.status_code),
2036 header->u.auth.variable,
Sunil Ravi036cec52023-03-29 11:35:17 -07002037 len - auth_length, 1, header->sa, &ie_offset);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002038 if (res < 0) {
2039 /* Notify failure to the driver */
2040 sme_send_external_auth_status(
Sunil Ravia04bd252022-05-02 22:54:18 -07002041 wpa_s,
2042 res == -2 ?
2043 le_to_host16(header->u.auth.status_code) :
2044 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002045 return;
2046 }
2047 if (res != 1)
2048 return;
2049
Sunil Ravi036cec52023-03-29 11:35:17 -07002050 if (sme_sae_set_pmk(wpa_s,
2051 wpa_s->sme.ext_ml_auth ?
2052 wpa_s->sme.ext_auth_ap_mld_addr :
2053 wpa_s->sme.ext_auth_bssid) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002054 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002055 }
2056}
2057
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002058#endif /* CONFIG_SAE */
2059
2060
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
2062{
2063 struct wpa_ssid *ssid = wpa_s->current_ssid;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002064 int ie_offset = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002065
2066 if (ssid == NULL) {
2067 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
2068 "when network is not selected");
2069 return;
2070 }
2071
2072 if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
2073 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
2074 "when not in authenticating state");
2075 return;
2076 }
2077
Sunil Ravi77d572f2023-01-17 23:58:31 +00002078 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0 &&
2079 !(wpa_s->valid_links &&
2080 os_memcmp(wpa_s->ap_mld_addr, data->auth.peer, ETH_ALEN) == 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002081 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
2082 "unexpected peer " MACSTR,
2083 MAC2STR(data->auth.peer));
2084 return;
2085 }
2086
2087 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002088 " auth_type=%d auth_transaction=%d status_code=%d",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002089 MAC2STR(data->auth.peer), data->auth.auth_type,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002090 data->auth.auth_transaction, data->auth.status_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002091 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
2092 data->auth.ies, data->auth.ies_len);
2093
2094 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2095
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002096#ifdef CONFIG_SAE
2097 if (data->auth.auth_type == WLAN_AUTH_SAE) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002098 const u8 *addr = wpa_s->pending_bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002099 int res;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002100
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002101 res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
2102 data->auth.status_code, data->auth.ies,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002103 data->auth.ies_len, 0, data->auth.peer,
2104 &ie_offset);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002105 if (res < 0) {
2106 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2107 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2108
2109 }
2110 if (res != 1)
2111 return;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002112
Sunil Ravi77d572f2023-01-17 23:58:31 +00002113 if (wpa_s->valid_links)
2114 addr = wpa_s->ap_mld_addr;
2115
2116 if (sme_sae_set_pmk(wpa_s, addr) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002117 return;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002118 }
2119#endif /* CONFIG_SAE */
2120
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002121 if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002122 char *ie_txt = NULL;
2123
2124 if (data->auth.ies && data->auth.ies_len) {
2125 size_t buflen = 2 * data->auth.ies_len + 1;
2126 ie_txt = os_malloc(buflen);
2127 if (ie_txt) {
2128 wpa_snprintf_hex(ie_txt, buflen, data->auth.ies,
2129 data->auth.ies_len);
2130 }
2131 }
2132 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002133 " auth_type=%u auth_transaction=%u status_code=%u%s%s",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002134 MAC2STR(data->auth.peer), data->auth.auth_type,
2135 data->auth.auth_transaction, data->auth.status_code,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002136 ie_txt ? " ie=" : "",
2137 ie_txt ? ie_txt : "");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002138 os_free(ie_txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002139
Hai Shalomce48b4a2018-09-05 11:41:35 -07002140#ifdef CONFIG_FILS
2141 if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
2142 wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS)
2143 fils_connection_failure(wpa_s);
2144#endif /* CONFIG_FILS */
2145
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002146 if (data->auth.status_code !=
2147 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
2148 wpa_s->sme.auth_alg == data->auth.auth_type ||
2149 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
2150 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002151 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152 return;
2153 }
2154
Dmitry Shmidt97672262014-02-03 13:02:54 -08002155 wpas_connect_work_done(wpa_s);
2156
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002157 switch (data->auth.auth_type) {
2158 case WLAN_AUTH_OPEN:
2159 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
2160
2161 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
2162 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2163 wpa_s->current_ssid);
2164 return;
2165
2166 case WLAN_AUTH_SHARED_KEY:
2167 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
2168
2169 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
2170 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2171 wpa_s->current_ssid);
2172 return;
2173
2174 default:
2175 return;
2176 }
2177 }
2178
2179#ifdef CONFIG_IEEE80211R
2180 if (data->auth.auth_type == WLAN_AUTH_FT) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002181 const u8 *ric_ies = NULL;
2182 size_t ric_ies_len = 0;
2183
2184 if (wpa_s->ric_ies) {
2185 ric_ies = wpabuf_head(wpa_s->ric_ies);
2186 ric_ies_len = wpabuf_len(wpa_s->ric_ies);
2187 }
Dmitry Shmidt41712582015-06-29 11:02:15 -07002188 if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
2189 data->auth.ies_len, 0,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002190 data->auth.peer,
2191 ric_ies, ric_ies_len) < 0) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07002192 wpa_dbg(wpa_s, MSG_DEBUG,
2193 "SME: FT Authentication response processing failed");
2194 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2195 MACSTR
2196 " reason=%d locally_generated=1",
2197 MAC2STR(wpa_s->pending_bssid),
2198 WLAN_REASON_DEAUTH_LEAVING);
2199 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2200 wpa_supplicant_mark_disassoc(wpa_s);
2201 return;
2202 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002203 }
2204#endif /* CONFIG_IEEE80211R */
2205
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002206#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002207 if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
2208 data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
2209 u16 expect_auth_type;
2210
2211 expect_auth_type = wpa_s->sme.auth_alg ==
2212 WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
2213 WLAN_AUTH_FILS_SK;
2214 if (data->auth.auth_type != expect_auth_type) {
2215 wpa_dbg(wpa_s, MSG_DEBUG,
2216 "SME: FILS Authentication response used different auth alg (%u; expected %u)",
2217 data->auth.auth_type, expect_auth_type);
2218 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2219 MACSTR
2220 " reason=%d locally_generated=1",
2221 MAC2STR(wpa_s->pending_bssid),
2222 WLAN_REASON_DEAUTH_LEAVING);
2223 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2224 wpa_supplicant_mark_disassoc(wpa_s);
2225 return;
2226 }
2227
2228 if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
2229 data->auth.ies, data->auth.ies_len) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002230 wpa_dbg(wpa_s, MSG_DEBUG,
2231 "SME: FILS Authentication response processing failed");
2232 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2233 MACSTR
2234 " reason=%d locally_generated=1",
2235 MAC2STR(wpa_s->pending_bssid),
2236 WLAN_REASON_DEAUTH_LEAVING);
2237 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2238 wpa_supplicant_mark_disassoc(wpa_s);
2239 return;
2240 }
2241 }
2242#endif /* CONFIG_FILS */
2243
Sunil Ravi77d572f2023-01-17 23:58:31 +00002244 /* TODO: Support additional auth_type values as well */
2245 if (data->auth.auth_type == WLAN_AUTH_OPEN ||
2246 data->auth.auth_type == WLAN_AUTH_SAE)
2247 wpas_sme_ml_auth(wpa_s, data, ie_offset);
2248
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002249 sme_associate(wpa_s, ssid->mode, data->auth.peer,
2250 data->auth.auth_type);
2251}
2252
2253
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002254#ifdef CONFIG_IEEE80211R
2255static void remove_ie(u8 *buf, size_t *len, u8 eid)
2256{
2257 u8 *pos, *next, *end;
2258
2259 pos = (u8 *) get_ie(buf, *len, eid);
2260 if (pos) {
2261 next = pos + 2 + pos[1];
2262 end = buf + *len;
2263 *len -= 2 + pos[1];
2264 os_memmove(pos, next, end - next);
2265 }
2266}
2267#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002268
2269
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002270void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
2271 const u8 *bssid, u16 auth_type)
2272{
2273 struct wpa_driver_associate_params params;
2274 struct ieee802_11_elems elems;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002275 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002276#ifdef CONFIG_FILS
2277 u8 nonces[2 * FILS_NONCE_LEN];
2278#endif /* CONFIG_FILS */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002279#ifdef CONFIG_HT_OVERRIDES
2280 struct ieee80211_ht_capabilities htcaps;
2281 struct ieee80211_ht_capabilities htcaps_mask;
2282#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002283#ifdef CONFIG_VHT_OVERRIDES
2284 struct ieee80211_vht_capabilities vhtcaps;
2285 struct ieee80211_vht_capabilities vhtcaps_mask;
2286#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002287
2288 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002289
2290#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002291 if (auth_type == WLAN_AUTH_FILS_SK ||
2292 auth_type == WLAN_AUTH_FILS_SK_PFS) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002293 struct wpabuf *buf;
2294 const u8 *snonce, *anonce;
Paul Stewart092955c2017-02-06 09:13:09 -08002295 const unsigned int max_hlp = 20;
2296 struct wpabuf *hlp[max_hlp];
2297 unsigned int i, num_hlp = 0;
2298 struct fils_hlp_req *req;
2299
2300 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2301 list) {
2302 hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
2303 wpabuf_len(req->pkt));
2304 if (!hlp[num_hlp])
2305 break;
2306 wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
2307 wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
2308 ETH_ALEN);
2309 wpabuf_put_data(hlp[num_hlp],
2310 "\xaa\xaa\x03\x00\x00\x00", 6);
2311 wpabuf_put_buf(hlp[num_hlp], req->pkt);
2312 num_hlp++;
2313 if (num_hlp >= max_hlp)
2314 break;
2315 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002316
2317 buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
2318 &params.fils_kek_len, &snonce,
Paul Stewart092955c2017-02-06 09:13:09 -08002319 &anonce,
2320 (const struct wpabuf **) hlp,
2321 num_hlp);
2322 for (i = 0; i < num_hlp; i++)
2323 wpabuf_free(hlp[i]);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002324 if (!buf)
2325 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002326 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req before FILS elements",
2327 wpa_s->sme.assoc_req_ie,
2328 wpa_s->sme.assoc_req_ie_len);
2329#ifdef CONFIG_IEEE80211R
2330 if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
2331 /* Remove RSNE and MDE to allow them to be overridden
2332 * with FILS+FT specific values from
2333 * fils_build_assoc_req(). */
2334 remove_ie(wpa_s->sme.assoc_req_ie,
2335 &wpa_s->sme.assoc_req_ie_len,
2336 WLAN_EID_RSN);
2337 wpa_hexdump(MSG_DEBUG,
2338 "FILS: assoc_req after RSNE removal",
2339 wpa_s->sme.assoc_req_ie,
2340 wpa_s->sme.assoc_req_ie_len);
2341 remove_ie(wpa_s->sme.assoc_req_ie,
2342 &wpa_s->sme.assoc_req_ie_len,
2343 WLAN_EID_MOBILITY_DOMAIN);
2344 wpa_hexdump(MSG_DEBUG,
2345 "FILS: assoc_req after MDE removal",
2346 wpa_s->sme.assoc_req_ie,
2347 wpa_s->sme.assoc_req_ie_len);
2348 }
2349#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002350 /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
2351 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
2352 sizeof(wpa_s->sme.assoc_req_ie)) {
2353 wpa_printf(MSG_ERROR,
2354 "FILS: Not enough buffer room for own AssocReq elements");
2355 wpabuf_free(buf);
2356 return;
2357 }
2358 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2359 wpabuf_head(buf), wpabuf_len(buf));
2360 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
2361 wpabuf_free(buf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002362 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req after FILS elements",
2363 wpa_s->sme.assoc_req_ie,
2364 wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002365
2366 os_memcpy(nonces, snonce, FILS_NONCE_LEN);
2367 os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
2368 params.fils_nonces = nonces;
2369 params.fils_nonces_len = sizeof(nonces);
2370 }
2371#endif /* CONFIG_FILS */
2372
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002373#ifdef CONFIG_OWE
2374#ifdef CONFIG_TESTING_OPTIONS
2375 if (get_ie_ext(wpa_s->sme.assoc_req_ie, wpa_s->sme.assoc_req_ie_len,
2376 WLAN_EID_EXT_OWE_DH_PARAM)) {
2377 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2378 } else
2379#endif /* CONFIG_TESTING_OPTIONS */
2380 if (auth_type == WLAN_AUTH_OPEN &&
2381 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2382 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002383 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002384
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002385 if (ssid && ssid->owe_group) {
2386 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08002387 } else if (wpa_s->assoc_status_code ==
2388 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002389 if (wpa_s->last_owe_group == 19)
2390 group = 20;
2391 else if (wpa_s->last_owe_group == 20)
2392 group = 21;
2393 else
2394 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002395 } else {
2396 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002397 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002398
Roshan Pius3a1667e2018-07-03 15:17:14 -07002399 wpa_s->last_owe_group = group;
2400 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002401 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2402 if (!owe_ie) {
2403 wpa_printf(MSG_ERROR,
2404 "OWE: Failed to build IE for Association Request frame");
2405 return;
2406 }
2407 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(owe_ie) >
2408 sizeof(wpa_s->sme.assoc_req_ie)) {
2409 wpa_printf(MSG_ERROR,
2410 "OWE: Not enough buffer room for own Association Request frame elements");
2411 wpabuf_free(owe_ie);
2412 return;
2413 }
2414 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2415 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2416 wpa_s->sme.assoc_req_ie_len += wpabuf_len(owe_ie);
2417 wpabuf_free(owe_ie);
2418 }
2419#endif /* CONFIG_OWE */
2420
Hai Shalom021b0b52019-04-10 11:17:58 -07002421#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002422 if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid &&
2423 ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 &&
2424 !ssid->dpp_pfs_fallback) {
2425 struct rsn_pmksa_cache_entry *pmksa;
2426
2427 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2428 if (!pmksa || !pmksa->dpp_pfs)
2429 goto pfs_fail;
Hai Shalom021b0b52019-04-10 11:17:58 -07002430
2431 dpp_pfs_free(wpa_s->dpp_pfs);
2432 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
2433 ssid->dpp_netaccesskey_len);
2434 if (!wpa_s->dpp_pfs) {
2435 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
2436 /* Try to continue without PFS */
2437 goto pfs_fail;
2438 }
2439 if (wpa_s->sme.assoc_req_ie_len +
2440 wpabuf_len(wpa_s->dpp_pfs->ie) >
2441 sizeof(wpa_s->sme.assoc_req_ie)) {
2442 wpa_printf(MSG_ERROR,
2443 "DPP: Not enough buffer room for own Association Request frame elements");
2444 dpp_pfs_free(wpa_s->dpp_pfs);
2445 wpa_s->dpp_pfs = NULL;
2446 goto pfs_fail;
2447 }
2448 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2449 wpabuf_head(wpa_s->dpp_pfs->ie),
2450 wpabuf_len(wpa_s->dpp_pfs->ie));
2451 wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
2452 }
2453pfs_fail:
2454#endif /* CONFIG_DPP2 */
2455
Hai Shalom899fcc72020-10-19 14:38:18 -07002456 wpa_s->mscs_setup_done = false;
Hai Shalom60840252021-02-19 19:02:11 -08002457 if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
2458 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002459 struct wpabuf *mscs_ie;
2460 size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len;
2461
Hai Shalom899fcc72020-10-19 14:38:18 -07002462 buf_len = 3 + /* MSCS descriptor IE header */
2463 1 + /* Request type */
2464 2 + /* User priority control */
2465 4 + /* Stream timeout */
2466 3 + /* TCLAS Mask IE header */
2467 wpa_s->robust_av.frame_classifier_len;
2468 mscs_ie = wpabuf_alloc(buf_len);
2469 if (!mscs_ie) {
2470 wpa_printf(MSG_INFO,
2471 "MSCS: Failed to allocate MSCS IE");
2472 goto mscs_fail;
2473 }
2474
2475 wpa_ie_len = &wpa_s->sme.assoc_req_ie_len;
2476 max_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
2477 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
2478 if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) {
2479 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
2480 mscs_ie_len = wpabuf_len(mscs_ie);
2481 os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len,
2482 wpabuf_head(mscs_ie), mscs_ie_len);
2483 *wpa_ie_len += mscs_ie_len;
2484 }
2485
2486 wpabuf_free(mscs_ie);
2487 }
2488mscs_fail:
2489
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002490 if (ssid && ssid->multi_ap_backhaul_sta) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002491 size_t multi_ap_ie_len;
2492
2493 multi_ap_ie_len = add_multi_ap_ie(
2494 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2495 sizeof(wpa_s->sme.assoc_req_ie) -
2496 wpa_s->sme.assoc_req_ie_len,
2497 MULTI_AP_BACKHAUL_STA);
2498 if (multi_ap_ie_len == 0) {
2499 wpa_printf(MSG_ERROR,
2500 "Multi-AP: Failed to build Multi-AP IE");
2501 return;
2502 }
2503 wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
2504 }
2505
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002506 params.bssid = bssid;
2507 params.ssid = wpa_s->sme.ssid;
2508 params.ssid_len = wpa_s->sme.ssid_len;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002509 params.freq.freq = wpa_s->sme.freq;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002510 params.bg_scan_period = ssid ? ssid->bg_scan_period : -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
2512 wpa_s->sme.assoc_req_ie : NULL;
2513 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08002514 wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
2515 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002516 params.pairwise_suite = wpa_s->pairwise_cipher;
2517 params.group_suite = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002518 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
Dmitry Shmidt15907092014-03-25 10:42:57 -07002519 params.key_mgmt_suite = wpa_s->key_mgmt;
2520 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002521#ifdef CONFIG_HT_OVERRIDES
2522 os_memset(&htcaps, 0, sizeof(htcaps));
2523 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2524 params.htcaps = (u8 *) &htcaps;
2525 params.htcaps_mask = (u8 *) &htcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002526 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002527#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002528#ifdef CONFIG_VHT_OVERRIDES
2529 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2530 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2531 params.vhtcaps = &vhtcaps;
2532 params.vhtcaps_mask = &vhtcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002533 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002534#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07002535#ifdef CONFIG_HE_OVERRIDES
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002536 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
Hai Shalomfdcde762020-04-02 11:19:20 -07002537#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00002538 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539#ifdef CONFIG_IEEE80211R
Hai Shalom74f70d42019-02-11 14:42:39 -08002540 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
2541 get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
2542 WLAN_EID_RIC_DATA)) {
2543 /* There seems to be a pretty inconvenient bug in the Linux
2544 * kernel IE splitting functionality when RIC is used. For now,
2545 * skip correct behavior in IE construction here (i.e., drop the
2546 * additional non-FT-specific IEs) to avoid kernel issues. This
2547 * is fine since RIC is used only for testing purposes in the
2548 * current implementation. */
2549 wpa_printf(MSG_INFO,
2550 "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 params.wpa_ie = wpa_s->sme.ft_ies;
2552 params.wpa_ie_len = wpa_s->sme.ft_ies_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08002553 } else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
2554 const u8 *rm_en, *pos, *end;
2555 size_t rm_en_len = 0;
2556 u8 *rm_en_dup = NULL, *wpos;
2557
2558 /* Remove RSNE, MDE, FTE to allow them to be overridden with
2559 * FT specific values */
2560 remove_ie(wpa_s->sme.assoc_req_ie,
2561 &wpa_s->sme.assoc_req_ie_len,
2562 WLAN_EID_RSN);
2563 remove_ie(wpa_s->sme.assoc_req_ie,
2564 &wpa_s->sme.assoc_req_ie_len,
2565 WLAN_EID_MOBILITY_DOMAIN);
2566 remove_ie(wpa_s->sme.assoc_req_ie,
2567 &wpa_s->sme.assoc_req_ie_len,
2568 WLAN_EID_FAST_BSS_TRANSITION);
2569 rm_en = get_ie(wpa_s->sme.assoc_req_ie,
2570 wpa_s->sme.assoc_req_ie_len,
2571 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2572 if (rm_en) {
2573 /* Need to remove RM Enabled Capabilities element as
2574 * well temporarily, so that it can be placed between
2575 * RSNE and MDE. */
2576 rm_en_len = 2 + rm_en[1];
2577 rm_en_dup = os_memdup(rm_en, rm_en_len);
2578 remove_ie(wpa_s->sme.assoc_req_ie,
2579 &wpa_s->sme.assoc_req_ie_len,
2580 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2581 }
2582 wpa_hexdump(MSG_DEBUG,
2583 "SME: Association Request IEs after FT IE removal",
2584 wpa_s->sme.assoc_req_ie,
2585 wpa_s->sme.assoc_req_ie_len);
2586 if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
2587 rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
2588 wpa_printf(MSG_ERROR,
2589 "SME: Not enough buffer room for FT IEs in Association Request frame");
2590 os_free(rm_en_dup);
2591 return;
2592 }
2593
2594 os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
2595 rm_en_len,
2596 wpa_s->sme.assoc_req_ie,
2597 wpa_s->sme.assoc_req_ie_len);
2598 pos = wpa_s->sme.ft_ies;
2599 end = pos + wpa_s->sme.ft_ies_len;
2600 wpos = wpa_s->sme.assoc_req_ie;
2601 if (*pos == WLAN_EID_RSN) {
2602 os_memcpy(wpos, pos, 2 + pos[1]);
2603 wpos += 2 + pos[1];
2604 pos += 2 + pos[1];
2605 }
2606 if (rm_en_dup) {
2607 os_memcpy(wpos, rm_en_dup, rm_en_len);
2608 wpos += rm_en_len;
2609 os_free(rm_en_dup);
2610 }
2611 os_memcpy(wpos, pos, end - pos);
2612 wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
2613 rm_en_len;
2614 params.wpa_ie = wpa_s->sme.assoc_req_ie;
2615 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
2616 wpa_hexdump(MSG_DEBUG,
2617 "SME: Association Request IEs after FT override",
2618 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002619 }
2620#endif /* CONFIG_IEEE80211R */
2621 params.mode = mode;
2622 params.mgmt_frame_protection = wpa_s->sme.mfp;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002623 params.rrm_used = wpa_s->rrm.rrm_used;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 if (wpa_s->sme.prev_bssid_set)
2625 params.prev_bssid = wpa_s->sme.prev_bssid;
2626
2627 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2628 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
2629 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002630 params.freq.freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631
2632 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2633
2634 if (params.wpa_ie == NULL ||
2635 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
2636 < 0) {
2637 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
2638 os_memset(&elems, 0, sizeof(elems));
2639 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002640 if (elems.rsn_ie) {
2641 params.wpa_proto = WPA_PROTO_RSN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002642 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
2643 elems.rsn_ie_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002644 } else if (elems.wpa_ie) {
2645 params.wpa_proto = WPA_PROTO_WPA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
2647 elems.wpa_ie_len + 2);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002648 } else if (elems.osen) {
2649 params.wpa_proto = WPA_PROTO_OSEN;
2650 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
2651 elems.osen_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002652 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002653 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07002654 if (elems.rsnxe)
2655 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, elems.rsnxe - 2,
2656 elems.rsnxe_len + 2);
2657 else
2658 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002659 if (ssid && ssid->p2p_group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002660 params.p2p = 1;
2661
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002662 if (wpa_s->p2pdev->set_sta_uapsd)
2663 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664 else
2665 params.uapsd = -1;
2666
Sunil Ravi77d572f2023-01-17 23:58:31 +00002667 if (wpa_s->valid_links) {
2668 unsigned int i;
2669
2670 wpa_printf(MSG_DEBUG,
2671 "MLD: In association. assoc_link_id=%u, valid_links=0x%x",
2672 wpa_s->mlo_assoc_link_id, wpa_s->valid_links);
2673
2674 params.mld_params.mld_addr = wpa_s->ap_mld_addr;
2675 params.mld_params.valid_links = wpa_s->valid_links;
2676 params.mld_params.assoc_link_id = wpa_s->mlo_assoc_link_id;
2677 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
2678 if (!(wpa_s->valid_links & BIT(i)))
2679 continue;
2680
2681 params.mld_params.mld_links[i].bssid =
2682 wpa_s->links[i].bssid;
2683 params.mld_params.mld_links[i].freq =
2684 wpa_s->links[i].freq;
2685
2686 wpa_printf(MSG_DEBUG, "MLD: id=%u, freq=%d, " MACSTR,
2687 i, wpa_s->links[i].freq,
2688 MAC2STR(wpa_s->links[i].bssid));
2689 }
2690 }
2691
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002692 if (wpa_drv_associate(wpa_s, &params) < 0) {
2693 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
2694 "driver failed");
2695 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002696 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002697 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2698 return;
2699 }
2700
2701 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
2702 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002703
2704#ifdef CONFIG_TESTING_OPTIONS
2705 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
2706 wpa_s->last_assoc_req_wpa_ie = NULL;
2707 if (params.wpa_ie)
2708 wpa_s->last_assoc_req_wpa_ie =
2709 wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len);
2710#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711}
2712
2713
2714int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
2715 const u8 *ies, size_t ies_len)
2716{
2717 if (md == NULL || ies == NULL) {
2718 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
2719 os_free(wpa_s->sme.ft_ies);
2720 wpa_s->sme.ft_ies = NULL;
2721 wpa_s->sme.ft_ies_len = 0;
2722 wpa_s->sme.ft_used = 0;
2723 return 0;
2724 }
2725
2726 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
2727 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
2728 os_free(wpa_s->sme.ft_ies);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002729 wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002730 if (wpa_s->sme.ft_ies == NULL)
2731 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002732 wpa_s->sme.ft_ies_len = ies_len;
2733 return 0;
2734}
2735
2736
2737static void sme_deauth(struct wpa_supplicant *wpa_s)
2738{
2739 int bssid_changed;
2740
2741 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2742
2743 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
2744 WLAN_REASON_DEAUTH_LEAVING) < 0) {
2745 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
2746 "failed");
2747 }
2748 wpa_s->sme.prev_bssid_set = 0;
2749
2750 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2751 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2752 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2753 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2754 if (bssid_changed)
2755 wpas_notify_bssid_changed(wpa_s);
2756}
2757
2758
2759void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
2760 union wpa_event_data *data)
2761{
2762 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
2763 "status code %d", MAC2STR(wpa_s->pending_bssid),
2764 data->assoc_reject.status_code);
2765
2766 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2767
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002768#ifdef CONFIG_SAE
2769 if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
2770 wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
2771 wpa_dbg(wpa_s, MSG_DEBUG,
2772 "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
2773 wpa_sm_aborted_cached(wpa_s->wpa);
2774 wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
2775 if (wpa_s->current_bss) {
2776 struct wpa_bss *bss = wpa_s->current_bss;
2777 struct wpa_ssid *ssid = wpa_s->current_ssid;
2778
2779 wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
2780 WLAN_REASON_DEAUTH_LEAVING);
2781 wpas_connect_work_done(wpa_s);
2782 wpa_supplicant_mark_disassoc(wpa_s);
2783 wpa_supplicant_connect(wpa_s, bss, ssid);
2784 return;
2785 }
2786 }
2787#endif /* CONFIG_SAE */
2788
Sunil Ravi77d572f2023-01-17 23:58:31 +00002789#ifdef CONFIG_DPP
2790 if (wpa_s->current_ssid &&
2791 wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
2792 !data->assoc_reject.timed_out &&
2793 data->assoc_reject.status_code == WLAN_STATUS_INVALID_PMKID) {
2794 struct rsn_pmksa_cache_entry *pmksa;
2795
2796 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2797 if (pmksa) {
2798 wpa_dbg(wpa_s, MSG_DEBUG,
2799 "DPP: Drop PMKSA cache entry for the BSS due to invalid PMKID report");
2800 wpa_sm_pmksa_cache_remove(wpa_s->wpa, pmksa);
2801 }
2802 wpa_sm_aborted_cached(wpa_s->wpa);
2803 if (wpa_s->current_bss) {
2804 struct wpa_bss *bss = wpa_s->current_bss;
2805 struct wpa_ssid *ssid = wpa_s->current_ssid;
2806
2807 wpa_dbg(wpa_s, MSG_DEBUG,
2808 "DPP: Try network introduction again");
2809 wpas_connect_work_done(wpa_s);
2810 wpa_supplicant_mark_disassoc(wpa_s);
2811 wpa_supplicant_connect(wpa_s, bss, ssid);
2812 return;
2813 }
2814 }
2815#endif /* CONFIG_DPP */
2816
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002817 /*
2818 * For now, unconditionally terminate the previous authentication. In
2819 * theory, this should not be needed, but mac80211 gets quite confused
2820 * if the authentication is left pending.. Some roaming cases might
2821 * benefit from using the previous authentication, so this could be
2822 * optimized in the future.
2823 */
2824 sme_deauth(wpa_s);
2825}
2826
2827
2828void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
2829 union wpa_event_data *data)
2830{
2831 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
2832 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002833 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002834}
2835
2836
2837void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
2838 union wpa_event_data *data)
2839{
2840 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
2841 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2842 wpa_supplicant_mark_disassoc(wpa_s);
2843}
2844
2845
2846void sme_event_disassoc(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002847 struct disassoc_info *info)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002848{
2849 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002850 if (wpa_s->sme.prev_bssid_set) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002851 /*
2852 * cfg80211/mac80211 can get into somewhat confused state if
2853 * the AP only disassociates us and leaves us in authenticated
2854 * state. For now, force the state to be cleared to avoid
2855 * confusing errors if we try to associate with the AP again.
2856 */
2857 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
2858 "driver state");
2859 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
2860 WLAN_REASON_DEAUTH_LEAVING);
2861 }
2862}
2863
2864
2865static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
2866{
2867 struct wpa_supplicant *wpa_s = eloop_ctx;
2868 if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
2869 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
2870 sme_deauth(wpa_s);
2871 }
2872}
2873
2874
2875static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
2876{
2877 struct wpa_supplicant *wpa_s = eloop_ctx;
2878 if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2879 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
2880 sme_deauth(wpa_s);
2881 }
2882}
2883
2884
2885void sme_state_changed(struct wpa_supplicant *wpa_s)
2886{
2887 /* Make sure timers are cleaned up appropriately. */
2888 if (wpa_s->wpa_state != WPA_ASSOCIATING)
2889 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2890 if (wpa_s->wpa_state != WPA_AUTHENTICATING)
2891 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2892}
2893
2894
2895void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
2896 const u8 *prev_pending_bssid)
2897{
2898 /*
2899 * mac80211-workaround to force deauth on failed auth cmd,
2900 * requires us to remain in authenticating state to allow the
2901 * second authentication attempt to be continued properly.
2902 */
2903 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
2904 "to proceed after disconnection event");
2905 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
2906 os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
2907
2908 /*
2909 * Re-arm authentication timer in case auth fails for whatever reason.
2910 */
2911 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2912 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
2913 NULL);
2914}
2915
2916
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002917void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
2918{
2919 wpa_s->sme.prev_bssid_set = 0;
2920#ifdef CONFIG_SAE
2921 wpabuf_free(wpa_s->sme.sae_token);
2922 wpa_s->sme.sae_token = NULL;
2923 sae_clear_data(&wpa_s->sme.sae);
2924#endif /* CONFIG_SAE */
2925#ifdef CONFIG_IEEE80211R
Roshan Pius3a1667e2018-07-03 15:17:14 -07002926 if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002927 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
2928#endif /* CONFIG_IEEE80211R */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002929 sme_stop_sa_query(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002930}
2931
2932
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002933void sme_deinit(struct wpa_supplicant *wpa_s)
2934{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002935 sme_clear_on_disassoc(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002936#ifdef CONFIG_SAE
2937 os_free(wpa_s->sme.sae_rejected_groups);
2938 wpa_s->sme.sae_rejected_groups = NULL;
2939#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002940
2941 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2942 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002943 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
2944}
2945
2946
2947static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
2948 const u8 *chan_list, u8 num_channels,
2949 u8 num_intol)
2950{
2951 struct ieee80211_2040_bss_coex_ie *bc_ie;
2952 struct ieee80211_2040_intol_chan_report *ic_report;
2953 struct wpabuf *buf;
2954
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002955 wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
2956 " (num_channels=%u num_intol=%u)",
2957 MAC2STR(wpa_s->bssid), num_channels, num_intol);
2958 wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
2959 chan_list, num_channels);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002960
2961 buf = wpabuf_alloc(2 + /* action.category + action_code */
2962 sizeof(struct ieee80211_2040_bss_coex_ie) +
2963 sizeof(struct ieee80211_2040_intol_chan_report) +
2964 num_channels);
2965 if (buf == NULL)
2966 return;
2967
2968 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
2969 wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
2970
2971 bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
2972 bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
2973 bc_ie->length = 1;
2974 if (num_intol)
2975 bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
2976
2977 if (num_channels > 0) {
2978 ic_report = wpabuf_put(buf, sizeof(*ic_report));
2979 ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
2980 ic_report->length = num_channels + 1;
2981 ic_report->op_class = 0;
2982 os_memcpy(wpabuf_put(buf, num_channels), chan_list,
2983 num_channels);
2984 }
2985
2986 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
2987 wpa_s->own_addr, wpa_s->bssid,
2988 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
2989 wpa_msg(wpa_s, MSG_INFO,
2990 "SME: Failed to send 20/40 BSS Coexistence frame");
2991 }
2992
2993 wpabuf_free(buf);
2994}
2995
2996
Hai Shaloma20dcd72022-02-04 13:43:00 -08002997int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002998{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002999 struct wpa_bss *bss;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003000 const u8 *ie;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003001 u16 ht_cap;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003002 u8 chan_list[P2P_MAX_CHANNELS], channel;
3003 u8 num_channels = 0, num_intol = 0, i;
3004
3005 if (!wpa_s->sme.sched_obss_scan)
3006 return 0;
3007
3008 wpa_s->sme.sched_obss_scan = 0;
3009 if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
3010 return 1;
3011
3012 /*
3013 * Check whether AP uses regulatory triplet or channel triplet in
3014 * country info. Right now the operating class of the BSS channel
3015 * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
3016 * based on the assumption that operating class triplet is not used in
3017 * beacon frame. If the First Channel Number/Operating Extension
3018 * Identifier octet has a positive integer value of 201 or greater,
3019 * then its operating class triplet.
3020 *
3021 * TODO: If Supported Operating Classes element is present in beacon
3022 * frame, have to lookup operating class in Annex E and fill them in
3023 * 2040 coex frame.
3024 */
3025 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
3026 if (ie && (ie[1] >= 6) && (ie[5] >= 201))
3027 return 1;
3028
3029 os_memset(chan_list, 0, sizeof(chan_list));
3030
Hai Shaloma20dcd72022-02-04 13:43:00 -08003031 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003032 /* Skip other band bss */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003033 enum hostapd_hw_mode mode;
Dmitry Shmidt4b060592013-04-29 16:42:49 -07003034 mode = ieee80211_freq_to_chan(bss->freq, &channel);
3035 if (mode != HOSTAPD_MODE_IEEE80211G &&
3036 mode != HOSTAPD_MODE_IEEE80211B)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003037 continue;
3038
Hai Shaloma20dcd72022-02-04 13:43:00 -08003039 ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
3040 ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
3041 wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
3042 " freq=%u chan=%u ht_cap=0x%x",
3043 MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
3044
3045 if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
3046 if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003047 num_intol++;
3048
Dmitry Shmidt04949592012-07-19 12:16:46 -07003049 /* Check whether the channel is already considered */
3050 for (i = 0; i < num_channels; i++) {
3051 if (channel == chan_list[i])
3052 break;
3053 }
3054 if (i != num_channels)
3055 continue;
3056
Dmitry Shmidt04949592012-07-19 12:16:46 -07003057 chan_list[num_channels++] = channel;
3058 }
3059 }
3060
3061 sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
3062 return 1;
3063}
3064
3065
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003066static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
3067 struct wpa_driver_scan_params *params)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003068{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003069 /* Include only affected channels */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003070 struct hostapd_hw_modes *mode;
3071 int count, i;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003072 int start, end;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003073
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003074 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08003075 HOSTAPD_MODE_IEEE80211G, false);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003076 if (mode == NULL) {
3077 /* No channels supported in this band - use empty list */
3078 params->freqs = os_zalloc(sizeof(int));
3079 return;
3080 }
3081
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003082 if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
3083 wpa_s->current_bss) {
3084 const u8 *ie;
3085
3086 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
3087 if (ie && ie[1] >= 2) {
3088 u8 o;
3089
3090 o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
3091 if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
3092 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
3093 else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
3094 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
3095 }
3096 }
3097
3098 start = wpa_s->assoc_freq - 10;
3099 end = wpa_s->assoc_freq + 10;
3100 switch (wpa_s->sme.ht_sec_chan) {
3101 case HT_SEC_CHAN_UNKNOWN:
3102 /* HT40+ possible on channels 1..9 */
3103 if (wpa_s->assoc_freq <= 2452)
3104 start -= 20;
3105 /* HT40- possible on channels 5-13 */
3106 if (wpa_s->assoc_freq >= 2432)
3107 end += 20;
3108 break;
3109 case HT_SEC_CHAN_ABOVE:
3110 end += 20;
3111 break;
3112 case HT_SEC_CHAN_BELOW:
3113 start -= 20;
3114 break;
3115 }
3116 wpa_printf(MSG_DEBUG,
3117 "OBSS: assoc_freq %d possible affected range %d-%d",
3118 wpa_s->assoc_freq, start, end);
3119
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003120 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
Dmitry Shmidt04949592012-07-19 12:16:46 -07003121 if (params->freqs == NULL)
3122 return;
3123 for (count = 0, i = 0; i < mode->num_channels; i++) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003124 int freq;
3125
Dmitry Shmidt04949592012-07-19 12:16:46 -07003126 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
3127 continue;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003128 freq = mode->channels[i].freq;
3129 if (freq - 10 >= end || freq + 10 <= start)
3130 continue; /* not affected */
3131 params->freqs[count++] = freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003132 }
3133}
3134
3135
3136static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
3137{
3138 struct wpa_supplicant *wpa_s = eloop_ctx;
3139 struct wpa_driver_scan_params params;
3140
3141 if (!wpa_s->current_bss) {
3142 wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
3143 return;
3144 }
3145
3146 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003147 wpa_obss_scan_freqs_list(wpa_s, &params);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003148 params.low_priority = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003149 wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
3150
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003151 if (wpa_supplicant_trigger_scan(wpa_s, &params, true, false))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003152 wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
3153 else
3154 wpa_s->sme.sched_obss_scan = 1;
3155 os_free(params.freqs);
3156
3157 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3158 sme_obss_scan_timeout, wpa_s, NULL);
3159}
3160
3161
3162void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
3163{
3164 const u8 *ie;
3165 struct wpa_bss *bss = wpa_s->current_bss;
3166 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003167 struct hostapd_hw_modes *hw_mode = NULL;
3168 int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003169
3170 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
3171 wpa_s->sme.sched_obss_scan = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003172 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003173 if (!enable)
3174 return;
3175
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003176 /*
3177 * Schedule OBSS scan if driver is using station SME in wpa_supplicant
3178 * or it expects OBSS scan to be performed by wpa_supplicant.
3179 */
3180 if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
3181 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
Hai Shalom81f62d82019-07-22 12:10:00 -07003182 ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003183 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003184
Hai Shaloma20dcd72022-02-04 13:43:00 -08003185#ifdef CONFIG_HT_OVERRIDES
3186 /* No need for OBSS scan if HT40 is explicitly disabled */
3187 if (ssid->disable_ht40)
3188 return;
3189#endif /* CONFIG_HT_OVERRIDES */
3190
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003191 if (!wpa_s->hw.modes)
3192 return;
3193
3194 /* only HT caps in 11g mode are relevant */
3195 for (i = 0; i < wpa_s->hw.num_modes; i++) {
3196 hw_mode = &wpa_s->hw.modes[i];
3197 if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
3198 break;
3199 }
3200
3201 /* Driver does not support HT40 for 11g or doesn't have 11g. */
3202 if (i == wpa_s->hw.num_modes || !hw_mode ||
3203 !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3204 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003205
3206 if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
3207 return; /* Not associated on 2.4 GHz band */
3208
3209 /* Check whether AP supports HT40 */
3210 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
3211 if (!ie || ie[1] < 2 ||
3212 !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3213 return; /* AP does not support HT40 */
3214
3215 ie = wpa_bss_get_ie(wpa_s->current_bss,
3216 WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
3217 if (!ie || ie[1] < 14)
3218 return; /* AP does not request OBSS scans */
3219
3220 wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
3221 if (wpa_s->sme.obss_scan_int < 10) {
3222 wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
3223 "replaced with the minimum 10 sec",
3224 wpa_s->sme.obss_scan_int);
3225 wpa_s->sme.obss_scan_int = 10;
3226 }
3227 wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
3228 wpa_s->sme.obss_scan_int);
3229 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3230 sme_obss_scan_timeout, wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003231}
3232
3233
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003234static const unsigned int sa_query_max_timeout = 1000;
3235static const unsigned int sa_query_retry_timeout = 201;
Hai Shalom74f70d42019-02-11 14:42:39 -08003236static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003237
3238static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
3239{
3240 u32 tu;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003241 struct os_reltime now, passed;
3242 os_get_reltime(&now);
3243 os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003244 tu = (passed.sec * 1000000 + passed.usec) / 1024;
3245 if (sa_query_max_timeout < tu) {
3246 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
3247 sme_stop_sa_query(wpa_s);
3248 wpa_supplicant_deauthenticate(
3249 wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
3250 return 1;
3251 }
3252
3253 return 0;
3254}
3255
3256
3257static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
3258 const u8 *trans_id)
3259{
Hai Shalom74f70d42019-02-11 14:42:39 -08003260 u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3261 u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3262
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003263 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
3264 MACSTR, MAC2STR(wpa_s->bssid));
3265 wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
3266 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
3267 req[0] = WLAN_ACTION_SA_QUERY;
3268 req[1] = WLAN_SA_QUERY_REQUEST;
3269 os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08003270
3271#ifdef CONFIG_OCV
3272 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3273 struct wpa_channel_info ci;
3274
3275 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3276 wpa_printf(MSG_WARNING,
3277 "Failed to get channel info for OCI element in SA Query Request frame");
3278 return;
3279 }
3280
Hai Shalom899fcc72020-10-19 14:38:18 -07003281#ifdef CONFIG_TESTING_OPTIONS
3282 if (wpa_s->oci_freq_override_saquery_req) {
3283 wpa_printf(MSG_INFO,
3284 "TEST: Override SA Query Request OCI frequency %d -> %d MHz",
3285 ci.frequency,
3286 wpa_s->oci_freq_override_saquery_req);
3287 ci.frequency = wpa_s->oci_freq_override_saquery_req;
3288 }
3289#endif /* CONFIG_TESTING_OPTIONS */
3290
Hai Shalom74f70d42019-02-11 14:42:39 -08003291 if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
3292 return;
3293
3294 req_len += OCV_OCI_EXTENDED_LEN;
3295 }
3296#endif /* CONFIG_OCV */
3297
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003298 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3299 wpa_s->own_addr, wpa_s->bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08003300 req, req_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003301 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
3302 "Request");
3303}
3304
3305
3306static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
3307{
3308 struct wpa_supplicant *wpa_s = eloop_ctx;
3309 unsigned int timeout, sec, usec;
3310 u8 *trans_id, *nbuf;
3311
3312 if (wpa_s->sme.sa_query_count > 0 &&
3313 sme_check_sa_query_timeout(wpa_s))
3314 return;
3315
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003316 nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
3317 wpa_s->sme.sa_query_count + 1,
3318 WLAN_SA_QUERY_TR_ID_LEN);
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003319 if (nbuf == NULL) {
3320 sme_stop_sa_query(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003321 return;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003322 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003323 if (wpa_s->sme.sa_query_count == 0) {
3324 /* Starting a new SA Query procedure */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003325 os_get_reltime(&wpa_s->sme.sa_query_start);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003326 }
3327 trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
3328 wpa_s->sme.sa_query_trans_id = nbuf;
3329 wpa_s->sme.sa_query_count++;
3330
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003331 if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
3332 wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003333 sme_stop_sa_query(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003334 return;
3335 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003336
3337 timeout = sa_query_retry_timeout;
3338 sec = ((timeout / 1000) * 1024) / 1000;
3339 usec = (timeout % 1000) * 1024;
3340 eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
3341
3342 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
3343 wpa_s->sme.sa_query_count);
3344
3345 sme_send_sa_query_req(wpa_s, trans_id);
3346}
3347
3348
3349static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
3350{
3351 sme_sa_query_timer(wpa_s, NULL);
3352}
3353
3354
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003355static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003356{
Hai Shalom5f92bc92019-04-18 11:54:11 -07003357 if (wpa_s->sme.sa_query_trans_id)
3358 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003359 eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
3360 os_free(wpa_s->sme.sa_query_trans_id);
3361 wpa_s->sme.sa_query_trans_id = NULL;
3362 wpa_s->sme.sa_query_count = 0;
3363}
3364
3365
3366void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
3367 const u8 *da, u16 reason_code)
3368{
3369 struct wpa_ssid *ssid;
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003370 struct os_reltime now;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003371
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003372 if (wpa_s->wpa_state != WPA_COMPLETED)
3373 return;
3374 ssid = wpa_s->current_ssid;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003375 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003376 return;
3377 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
3378 return;
3379 if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
3380 reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
3381 return;
3382 if (wpa_s->sme.sa_query_count > 0)
3383 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07003384#ifdef CONFIG_TESTING_OPTIONS
3385 if (wpa_s->disable_sa_query)
3386 return;
3387#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003388
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003389 os_get_reltime(&now);
3390 if (wpa_s->sme.last_unprot_disconnect.sec &&
3391 !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
3392 return; /* limit SA Query procedure frequency */
3393 wpa_s->sme.last_unprot_disconnect = now;
3394
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003395 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
3396 "possible AP/STA state mismatch - trigger SA Query");
3397 sme_start_sa_query(wpa_s);
3398}
3399
3400
Hai Shalom74f70d42019-02-11 14:42:39 -08003401void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
3402{
3403 unsigned int usec;
3404 u32 _rand;
3405
3406 if (wpa_s->wpa_state != WPA_COMPLETED ||
3407 !wpa_sm_ocv_enabled(wpa_s->wpa))
3408 return;
3409
3410 wpa_dbg(wpa_s, MSG_DEBUG,
3411 "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
3412 sme_stop_sa_query(wpa_s);
3413
3414 if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
3415 _rand = os_random();
3416 usec = _rand % (sa_query_ch_switch_max_delay + 1);
3417 eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
3418}
3419
3420
3421static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
3422 const u8 *sa, const u8 *data,
3423 size_t len)
3424{
3425 u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3426 u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3427
3428 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
3429 MACSTR, MAC2STR(wpa_s->bssid));
3430
3431 resp[0] = WLAN_ACTION_SA_QUERY;
3432 resp[1] = WLAN_SA_QUERY_RESPONSE;
3433 os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
3434
3435#ifdef CONFIG_OCV
3436 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3437 struct wpa_channel_info ci;
3438
3439 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3440 wpa_printf(MSG_WARNING,
3441 "Failed to get channel info for OCI element in SA Query Response frame");
3442 return;
3443 }
3444
Hai Shalom899fcc72020-10-19 14:38:18 -07003445#ifdef CONFIG_TESTING_OPTIONS
3446 if (wpa_s->oci_freq_override_saquery_resp) {
3447 wpa_printf(MSG_INFO,
3448 "TEST: Override SA Query Response OCI frequency %d -> %d MHz",
3449 ci.frequency,
3450 wpa_s->oci_freq_override_saquery_resp);
3451 ci.frequency = wpa_s->oci_freq_override_saquery_resp;
3452 }
3453#endif /* CONFIG_TESTING_OPTIONS */
3454
Hai Shalom74f70d42019-02-11 14:42:39 -08003455 if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
3456 return;
3457
3458 resp_len += OCV_OCI_EXTENDED_LEN;
3459 }
3460#endif /* CONFIG_OCV */
3461
3462 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3463 wpa_s->own_addr, wpa_s->bssid,
3464 resp, resp_len, 0) < 0)
3465 wpa_msg(wpa_s, MSG_INFO,
3466 "SME: Failed to send SA Query Response");
3467}
3468
3469
3470static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
3471 const u8 *sa, const u8 *data,
3472 size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003473{
3474 int i;
3475
Hai Shalom74f70d42019-02-11 14:42:39 -08003476 if (!wpa_s->sme.sa_query_trans_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 return;
Hai Shalom74f70d42019-02-11 14:42:39 -08003478
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003479 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
3480 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3481
3482 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
3483 return;
3484
3485 for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
3486 if (os_memcmp(wpa_s->sme.sa_query_trans_id +
3487 i * WLAN_SA_QUERY_TR_ID_LEN,
3488 data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
3489 break;
3490 }
3491
3492 if (i >= wpa_s->sme.sa_query_count) {
3493 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
3494 "transaction identifier found");
3495 return;
3496 }
3497
3498 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
3499 "from " MACSTR, MAC2STR(sa));
3500 sme_stop_sa_query(wpa_s);
3501}
3502
Hai Shalom74f70d42019-02-11 14:42:39 -08003503
Hai Shaloma20dcd72022-02-04 13:43:00 -08003504void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
Hai Shalom74f70d42019-02-11 14:42:39 -08003505 const u8 *data, size_t len)
3506{
3507 if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
3508 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003509 if (is_multicast_ether_addr(da)) {
3510 wpa_printf(MSG_DEBUG,
3511 "IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
3512 MAC2STR(da), MAC2STR(sa));
3513 return;
3514 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003515
3516 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
3517 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3518
3519#ifdef CONFIG_OCV
3520 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3521 struct ieee802_11_elems elems;
3522 struct wpa_channel_info ci;
3523
3524 if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
3525 len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
3526 &elems, 1) == ParseFailed) {
3527 wpa_printf(MSG_DEBUG,
3528 "SA Query: Failed to parse elements");
3529 return;
3530 }
3531
3532 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3533 wpa_printf(MSG_WARNING,
3534 "Failed to get channel info to validate received OCI in SA Query Action frame");
3535 return;
3536 }
3537
3538 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
3539 channel_width_to_int(ci.chanwidth),
Hai Shalom899fcc72020-10-19 14:38:18 -07003540 ci.seg1_idx) != OCI_SUCCESS) {
3541 wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR
3542 " frame=saquery%s error=%s",
3543 MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ?
3544 "req" : "resp", ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003545 return;
3546 }
3547 }
3548#endif /* CONFIG_OCV */
3549
3550 if (data[0] == WLAN_SA_QUERY_REQUEST)
3551 sme_process_sa_query_request(wpa_s, sa, data, len);
3552 else if (data[0] == WLAN_SA_QUERY_RESPONSE)
3553 sme_process_sa_query_response(wpa_s, sa, data, len);
3554}