blob: b8f7c65efa974614b196e516846757e0c26c81ba [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * wpa_supplicant - SME
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003 * Copyright (c) 2009-2024, 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"
Sunil Ravib0ac25f2024-07-12 01:42:03 +000031#include "bssid_ignore.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032#include "scan.h"
33#include "sme.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070034#include "hs20_supplicant.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070035
36#define SME_AUTH_TIMEOUT 5
37#define SME_ASSOC_TIMEOUT 5
38
39static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
40static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt04949592012-07-19 12:16:46 -070041static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043
44
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080045#ifdef CONFIG_SAE
46
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080047static int index_within_array(const int *array, int idx)
48{
49 int i;
50 for (i = 0; i < idx; i++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -080051 if (array[i] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080052 return 0;
53 }
54 return 1;
55}
56
57
Sunil Ravi77d572f2023-01-17 23:58:31 +000058static int sme_set_sae_group(struct wpa_supplicant *wpa_s, bool external)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080059{
60 int *groups = wpa_s->conf->sae_groups;
Hai Shalom021b0b52019-04-10 11:17:58 -070061 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080062
Dmitry Shmidtcce06662013-11-04 18:44:24 -080063 if (!groups || groups[0] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080064 groups = default_groups;
65
66 /* Configuration may have changed, so validate current index */
67 if (!index_within_array(groups, wpa_s->sme.sae_group_index))
68 return -1;
69
70 for (;;) {
71 int group = groups[wpa_s->sme.sae_group_index];
Dmitry Shmidt41712582015-06-29 11:02:15 -070072 if (group <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080073 break;
74 if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
75 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
76 wpa_s->sme.sae.group);
Sunil Ravi77d572f2023-01-17 23:58:31 +000077 wpa_s->sme.sae.akmp = external ?
78 wpa_s->sme.ext_auth_key_mgmt : wpa_s->key_mgmt;
Hai Shalom74f70d42019-02-11 14:42:39 -080079 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080080 }
81 wpa_s->sme.sae_group_index++;
82 }
83
84 return -1;
85}
86
87
88static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
89 struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +000090 const u8 *bssid,
91 const u8 *mld_addr,
92 int external,
Hai Shalom899fcc72020-10-19 14:38:18 -070093 int reuse, int *ret_use_pt,
94 bool *ret_use_pk)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080095{
96 struct wpabuf *buf;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080097 size_t len;
Sunil Ravi77d572f2023-01-17 23:58:31 +000098 char *password = NULL;
Hai Shalomc3565922019-10-28 11:58:20 -070099 struct wpa_bss *bss;
100 int use_pt = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700101 bool use_pk = false;
102 u8 rsnxe_capa = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000103 int key_mgmt = external ? wpa_s->sme.ext_auth_key_mgmt :
104 wpa_s->key_mgmt;
105 const u8 *addr = mld_addr ? mld_addr : bssid;
Hai Shalomc3565922019-10-28 11:58:20 -0700106
107 if (ret_use_pt)
108 *ret_use_pt = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700109 if (ret_use_pk)
110 *ret_use_pk = false;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800111
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700112#ifdef CONFIG_TESTING_OPTIONS
113 if (wpa_s->sae_commit_override) {
114 wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
115 buf = wpabuf_alloc(4 + wpabuf_len(wpa_s->sae_commit_override));
116 if (!buf)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000117 goto fail;
Hai Shalom021b0b52019-04-10 11:17:58 -0700118 if (!external) {
119 wpabuf_put_le16(buf, 1); /* Transaction seq# */
120 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
121 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700122 wpabuf_put_buf(buf, wpa_s->sae_commit_override);
123 return buf;
124 }
125#endif /* CONFIG_TESTING_OPTIONS */
126
Sunil Ravi77d572f2023-01-17 23:58:31 +0000127 if (ssid->sae_password) {
128 password = os_strdup(ssid->sae_password);
129 if (!password) {
130 wpa_dbg(wpa_s, MSG_INFO,
131 "SAE: Failed to allocate password");
132 goto fail;
133 }
134 }
135 if (!password && ssid->passphrase) {
136 password = os_strdup(ssid->passphrase);
137 if (!password) {
138 wpa_dbg(wpa_s, MSG_INFO,
139 "SAE: Failed to allocate password");
140 goto fail;
141 }
142 }
143 if (!password && ssid->ext_psk) {
144 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
145 ssid->ext_psk);
146
147 if (!pw) {
148 wpa_msg(wpa_s, MSG_INFO,
149 "SAE: No password found from external storage");
150 goto fail;
151 }
152
153 password = os_malloc(wpabuf_len(pw) + 1);
154 if (!password) {
155 wpa_dbg(wpa_s, MSG_INFO,
156 "SAE: Failed to allocate password");
157 goto fail;
158 }
159 os_memcpy(password, wpabuf_head(pw), wpabuf_len(pw));
160 password[wpabuf_len(pw)] = '\0';
161 ext_password_free(pw);
162 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700163 if (!password) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800164 wpa_printf(MSG_DEBUG, "SAE: No password available");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000165 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800166 }
167
Hai Shalom021b0b52019-04-10 11:17:58 -0700168 if (reuse && wpa_s->sme.sae.tmp &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000169 ether_addr_equal(addr, wpa_s->sme.sae.tmp->bssid)) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700170 wpa_printf(MSG_DEBUG,
171 "SAE: Reuse previously generated PWE on a retry with the same AP");
Hai Shalom899fcc72020-10-19 14:38:18 -0700172 use_pt = wpa_s->sme.sae.h2e;
173 use_pk = wpa_s->sme.sae.pk;
Hai Shalom021b0b52019-04-10 11:17:58 -0700174 goto reuse_data;
175 }
Sunil Ravi77d572f2023-01-17 23:58:31 +0000176 if (sme_set_sae_group(wpa_s, external) < 0) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800177 wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000178 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800179 }
180
Hai Shalom899fcc72020-10-19 14:38:18 -0700181 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800182 if (!bss) {
183 wpa_printf(MSG_DEBUG,
184 "SAE: BSS not available, update scan result to get BSS");
Sunil Ravi88611412024-06-28 17:34:56 +0000185 wpa_supplicant_update_scan_results(wpa_s);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800186 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
187 }
Hai Shalom899fcc72020-10-19 14:38:18 -0700188 if (bss) {
189 const u8 *rsnxe;
190
191 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
192 if (rsnxe && rsnxe[1] >= 1)
193 rsnxe_capa = rsnxe[2];
194 }
195
Sunil Ravi77d572f2023-01-17 23:58:31 +0000196 if (ssid->sae_password_id &&
197 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Hai Shalomfdcde762020-04-02 11:19:20 -0700198 use_pt = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000199 if (wpa_key_mgmt_sae_ext_key(key_mgmt) &&
200 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -0700201 use_pt = 1;
Sunil Ravi036cec52023-03-29 11:35:17 -0700202 if (bss && is_6ghz_freq(bss->freq) &&
203 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
204 use_pt = 1;
Hai Shalom899fcc72020-10-19 14:38:18 -0700205#ifdef CONFIG_SAE_PK
206 if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
207 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
208 ((ssid->sae_password &&
209 sae_pk_valid_password(ssid->sae_password)) ||
210 (!ssid->sae_password && ssid->passphrase &&
211 sae_pk_valid_password(ssid->passphrase)))) {
212 use_pt = 1;
213 use_pk = true;
214 }
215
216 if (ssid->sae_pk == SAE_PK_MODE_ONLY && !use_pk) {
217 wpa_printf(MSG_DEBUG,
218 "SAE: Cannot use PK with the selected AP");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000219 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -0700220 }
221#endif /* CONFIG_SAE_PK */
Hai Shalomfdcde762020-04-02 11:19:20 -0700222
Sunil Ravi77d572f2023-01-17 23:58:31 +0000223 if (use_pt || wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
224 wpa_s->conf->sae_pwe == SAE_PWE_BOTH) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700225 use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
Hai Shalomc3565922019-10-28 11:58:20 -0700226
Sunil Ravi77d572f2023-01-17 23:58:31 +0000227 if ((wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
228 ssid->sae_password_id ||
229 wpa_key_mgmt_sae_ext_key(key_mgmt)) &&
230 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
Hai Shalomfdcde762020-04-02 11:19:20 -0700231 !use_pt) {
Hai Shalomc3565922019-10-28 11:58:20 -0700232 wpa_printf(MSG_DEBUG,
233 "SAE: Cannot use H2E with the selected AP");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000234 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -0700235 }
236 }
237
Sunil Ravi036cec52023-03-29 11:35:17 -0700238 if (use_pt && !ssid->pt)
239 wpa_s_setup_sae_pt(wpa_s->conf, ssid, true);
Hai Shalomc3565922019-10-28 11:58:20 -0700240 if (use_pt &&
241 sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000242 wpa_s->own_addr, addr,
Hai Shalom899fcc72020-10-19 14:38:18 -0700243 wpa_s->sme.sae_rejected_groups, NULL) < 0)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000244 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -0700245 if (!use_pt &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000246 sae_prepare_commit(wpa_s->own_addr, addr,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700247 (u8 *) password, os_strlen(password),
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800248 &wpa_s->sme.sae) < 0) {
249 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000250 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800251 }
Hai Shalom899fcc72020-10-19 14:38:18 -0700252 if (wpa_s->sme.sae.tmp) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000253 os_memcpy(wpa_s->sme.sae.tmp->bssid, addr, ETH_ALEN);
Hai Shalom899fcc72020-10-19 14:38:18 -0700254 if (use_pt && use_pk)
255 wpa_s->sme.sae.pk = 1;
256#ifdef CONFIG_SAE_PK
257 os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr,
258 ETH_ALEN);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000259 os_memcpy(wpa_s->sme.sae.tmp->peer_addr, addr, ETH_ALEN);
Hai Shalom899fcc72020-10-19 14:38:18 -0700260 sae_pk_set_password(&wpa_s->sme.sae, password);
261#endif /* CONFIG_SAE_PK */
262 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800263
Hai Shalom021b0b52019-04-10 11:17:58 -0700264reuse_data:
Hai Shalomfdcde762020-04-02 11:19:20 -0700265 len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700266 if (ssid->sae_password_id)
267 len += 4 + os_strlen(ssid->sae_password_id);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800268 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800269 if (buf == NULL)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000270 goto fail;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700271 if (!external) {
272 wpabuf_put_le16(buf, 1); /* Transaction seq# */
Hai Shalom899fcc72020-10-19 14:38:18 -0700273 if (use_pk)
274 wpabuf_put_le16(buf, WLAN_STATUS_SAE_PK);
275 else if (use_pt)
276 wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
277 else
278 wpabuf_put_le16(buf,WLAN_STATUS_SUCCESS);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700279 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700280 if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
281 ssid->sae_password_id) < 0) {
282 wpabuf_free(buf);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000283 goto fail;
Hai Shalomfdcde762020-04-02 11:19:20 -0700284 }
Hai Shalomc3565922019-10-28 11:58:20 -0700285 if (ret_use_pt)
286 *ret_use_pt = use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -0700287 if (ret_use_pk)
288 *ret_use_pk = use_pk;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800289
Sunil Ravi77d572f2023-01-17 23:58:31 +0000290 str_clear_free(password);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800291 return buf;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000292
293fail:
294 str_clear_free(password);
295 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800296}
297
298
Roshan Pius3a1667e2018-07-03 15:17:14 -0700299static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s,
300 int external)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800301{
302 struct wpabuf *buf;
303
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800304 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800305 if (buf == NULL)
306 return NULL;
307
Roshan Pius3a1667e2018-07-03 15:17:14 -0700308 if (!external) {
309 wpabuf_put_le16(buf, 2); /* Transaction seq# */
310 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
311 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800312 sae_write_confirm(&wpa_s->sme.sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800313
314 return buf;
315}
316
317#endif /* CONFIG_SAE */
318
319
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800320/**
321 * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt
322 * @wpa_s: Pointer to wpa_supplicant data
323 * @bss: Pointer to the bss which is the target of authentication attempt
324 */
325static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
326 struct wpa_bss *bss)
327{
328 const u8 rrm_ie_len = 5;
329 u8 *pos;
330 const u8 *rrm_ie;
331
332 wpa_s->rrm.rrm_used = 0;
333
334 wpa_printf(MSG_DEBUG,
335 "RRM: Determining whether RRM can be used - device support: 0x%x",
336 wpa_s->drv_rrm_flags);
337
338 rrm_ie = wpa_bss_get_ie(bss, WLAN_EID_RRM_ENABLED_CAPABILITIES);
339 if (!rrm_ie || !(bss->caps & IEEE80211_CAP_RRM)) {
340 wpa_printf(MSG_DEBUG, "RRM: No RRM in network");
341 return;
342 }
343
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700344 if (!((wpa_s->drv_rrm_flags &
345 WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
346 (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
347 !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800348 wpa_printf(MSG_DEBUG,
349 "RRM: Insufficient RRM support in driver - do not use RRM");
350 return;
351 }
352
353 if (sizeof(wpa_s->sme.assoc_req_ie) <
354 wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) {
355 wpa_printf(MSG_INFO,
356 "RRM: Unable to use RRM, no room for RRM IE");
357 return;
358 }
359
360 wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to Association Request");
361 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
362 os_memset(pos, 0, 2 + rrm_ie_len);
363 *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
364 *pos++ = rrm_ie_len;
365
Hai Shalom60840252021-02-19 19:02:11 -0800366 /* Set supported capabilities flags */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800367 if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
368 *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
369
Dmitry Shmidt29333592017-01-09 12:27:11 -0800370 *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
371 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
372 WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
373
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700374 if (wpa_s->lci)
375 pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
376
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800377 wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
378 wpa_s->rrm.rrm_used = 1;
379}
380
381
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000382static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s,
383 struct wpa_bss *bss)
384{
385 u16 removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, bss);
386
387 wpa_s->valid_links &= ~removed_links;
388}
389
390
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000391#ifdef CONFIG_TESTING_OPTIONS
392static struct wpa_bss * wpas_ml_connect_pref(struct wpa_supplicant *wpa_s,
393 struct wpa_bss *bss)
394{
395 unsigned int low, high, i;
396
397 wpa_printf(MSG_DEBUG,
398 "MLD: valid_links=%d, band_pref=%u, bssid_pref=" MACSTR,
399 wpa_s->valid_links,
400 wpa_s->conf->mld_connect_band_pref,
401 MAC2STR(wpa_s->conf->mld_connect_bssid_pref));
402
403 /* Check if there are more than one link */
404 if (!(wpa_s->valid_links & (wpa_s->valid_links - 1)))
405 return bss;
406
407 if (!is_zero_ether_addr(wpa_s->conf->mld_connect_bssid_pref)) {
408 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
409 if (!(wpa_s->valid_links & BIT(i)))
410 continue;
411
412 if (wpa_s->mlo_assoc_link_id == i)
413 continue;
414
415 if (ether_addr_equal(
416 wpa_s->links[i].bssid,
417 wpa_s->conf->mld_connect_bssid_pref))
418 goto found;
419 }
420 }
421
422 if (wpa_s->conf->mld_connect_band_pref == MLD_CONNECT_BAND_PREF_AUTO)
423 return bss;
424
425 switch (wpa_s->conf->mld_connect_band_pref) {
426 case MLD_CONNECT_BAND_PREF_2GHZ:
427 low = 2412;
428 high = 2472;
429 break;
430 case MLD_CONNECT_BAND_PREF_5GHZ:
431 low = 5180;
432 high = 5985;
433 break;
434 case MLD_CONNECT_BAND_PREF_6GHZ:
435 low = 5955;
436 high = 7125;
437 break;
438 default:
439 return bss;
440 }
441
442 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
443 if (!(wpa_s->valid_links & BIT(i)))
444 continue;
445
446 if (wpa_s->mlo_assoc_link_id == i)
447 continue;
448
449 if (wpa_s->links[i].freq >= low && wpa_s->links[i].freq <= high)
450 goto found;
451 }
452
453found:
454 if (i == MAX_NUM_MLD_LINKS) {
455 wpa_printf(MSG_DEBUG, "MLD: No match for connect/band pref");
456 return bss;
457 }
458
459 wpa_printf(MSG_DEBUG,
460 "MLD: Change BSS for connect: " MACSTR " -> " MACSTR,
461 MAC2STR(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid),
462 MAC2STR(wpa_s->links[i].bssid));
463
464 /* Get the BSS entry and do the switch */
465 bss = wpa_bss_get_bssid(wpa_s, wpa_s->links[i].bssid);
466 wpa_s->mlo_assoc_link_id = i;
467
468 return bss;
469}
470#endif /* CONFIG_TESTING_OPTIONS */
471
472
473static int wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
474 union wpa_event_data *data,
475 int ie_offset)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000476{
477 struct ieee802_11_elems elems;
478 const u8 *mld_addr;
Sunil Ravi640215c2023-06-28 23:08:09 +0000479 u16 status_code = data->auth.status_code;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000480
481 if (!wpa_s->valid_links)
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000482 return 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000483
484 if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
485 data->auth.ies_len - ie_offset,
Sunil Ravi640215c2023-06-28 23:08:09 +0000486 &elems, 0) == ParseFailed) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000487 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
488 goto out;
489 }
490
491 if (!elems.basic_mle || !elems.basic_mle_len) {
492 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
Sunil Ravi640215c2023-06-28 23:08:09 +0000493 if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
494 status_code == WLAN_STATUS_SUCCESS ||
495 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
496 status_code == WLAN_STATUS_SAE_PK)
497 goto out;
498 /* Accept missing Multi-Link element in failed authentication
499 * cases. */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000500 return 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000501 }
502
503 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
504 if (!mld_addr)
505 goto out;
506
507 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
508
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000509 if (!ether_addr_equal(wpa_s->ap_mld_addr, mld_addr)) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000510 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
511 MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
512 goto out;
513 }
514
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000515 return 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000516out:
517 wpa_printf(MSG_DEBUG, "MLD: Authentication - clearing MLD state");
518 wpas_reset_mlo_info(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000519 return -1;
520}
521
522
523static void wpas_sme_set_mlo_links(struct wpa_supplicant *wpa_s,
524 struct wpa_bss *bss)
525{
526 int i;
527
528 wpa_s->valid_links = 0;
529
530 for (i = 0; i < bss->n_mld_links; i++) {
531 u8 link_id = bss->mld_links[i].link_id;
532 const u8 *bssid = bss->mld_links[i].bssid;
533
534 if (i == 0)
535 wpa_s->mlo_assoc_link_id = link_id;
536 wpa_s->valid_links |= BIT(link_id);
537 os_memcpy(wpa_s->links[link_id].bssid, bssid, ETH_ALEN);
538 wpa_s->links[link_id].freq = bss->mld_links[i].freq;
539 wpa_s->links[link_id].bss = wpa_bss_get_bssid(wpa_s, bssid);
540 wpa_s->links[link_id].disabled = bss->mld_links[i].disabled;
541 }
Sunil Ravi77d572f2023-01-17 23:58:31 +0000542}
543
544
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800545static void sme_send_authentication(struct wpa_supplicant *wpa_s,
546 struct wpa_bss *bss, struct wpa_ssid *ssid,
547 int start)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700548{
549 struct wpa_driver_auth_params params;
550 struct wpa_ssid *old_ssid;
551#ifdef CONFIG_IEEE80211R
552 const u8 *ie;
553#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700554#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700555 const u8 *md = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700556#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Hai Shalomfdcde762020-04-02 11:19:20 -0700557 int bssid_changed;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800558 struct wpabuf *resp = NULL;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700559 u8 ext_capab[18];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800560 int ext_capab_len;
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800561 int skip_auth;
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800562 u8 *wpa_ie;
563 size_t wpa_ie_len;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700564#ifdef CONFIG_MBO
565 const u8 *mbo_ie;
566#endif /* CONFIG_MBO */
Hai Shalomfdcde762020-04-02 11:19:20 -0700567 int omit_rsnxe = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700568
569 if (bss == NULL) {
570 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
571 "the network");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800572 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573 return;
574 }
575
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000576 os_memset(&params, 0, sizeof(params));
577
578 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
579 !wpa_bss_parse_basic_ml_element(wpa_s, bss, wpa_s->ap_mld_addr,
580 NULL, ssid, NULL) &&
581 bss->n_mld_links) {
582 wpa_printf(MSG_DEBUG, "MLD: In authentication");
583 wpas_sme_set_mlo_links(wpa_s, bss);
584
585#ifdef CONFIG_TESTING_OPTIONS
586 bss = wpas_ml_connect_pref(wpa_s, bss);
587
588 if (wpa_s->conf->mld_force_single_link) {
589 wpa_printf(MSG_DEBUG, "MLD: Force single link");
590 wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
591 }
592#endif /* CONFIG_TESTING_OPTIONS */
593 params.mld = true;
594 params.mld_link_id = wpa_s->mlo_assoc_link_id;
595 params.ap_mld_addr = wpa_s->ap_mld_addr;
596 wpas_ml_handle_removed_links(wpa_s, bss);
597 }
598
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800599 skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
600 wpa_s->reassoc_same_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601 wpa_s->current_bss = bss;
602
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700603 wpa_s->reassociate = 0;
604
605 params.freq = bss->freq;
606 params.bssid = bss->bssid;
607 params.ssid = bss->ssid;
608 params.ssid_len = bss->ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800609 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700610
611 if (wpa_s->sme.ssid_len != params.ssid_len ||
612 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
613 wpa_s->sme.prev_bssid_set = 0;
614
615 wpa_s->sme.freq = params.freq;
616 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
617 wpa_s->sme.ssid_len = params.ssid_len;
618
619 params.auth_alg = WPA_AUTH_ALG_OPEN;
620#ifdef IEEE8021X_EAPOL
621 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
622 if (ssid->leap) {
623 if (ssid->non_leap == 0)
624 params.auth_alg = WPA_AUTH_ALG_LEAP;
625 else
626 params.auth_alg |= WPA_AUTH_ALG_LEAP;
627 }
628 }
629#endif /* IEEE8021X_EAPOL */
630 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
631 params.auth_alg);
632 if (ssid->auth_alg) {
633 params.auth_alg = ssid->auth_alg;
634 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
635 "0x%x", params.auth_alg);
636 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800637#ifdef CONFIG_SAE
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800638 wpa_s->sme.sae_pmksa_caching = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800639 if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
640 const u8 *rsn;
641 struct wpa_ie_data ied;
642
643 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800644 if (!rsn) {
645 wpa_dbg(wpa_s, MSG_DEBUG,
646 "SAE enabled, but target BSS does not advertise RSN");
Hai Shalom021b0b52019-04-10 11:17:58 -0700647#ifdef CONFIG_DPP
648 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
649 (ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
650 (ied.key_mgmt & WPA_KEY_MGMT_DPP)) {
651 wpa_dbg(wpa_s, MSG_DEBUG, "Prefer DPP over SAE when both are enabled");
652#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800653 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
654 wpa_key_mgmt_sae(ied.key_mgmt)) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000655 if (wpas_is_sae_avoided(wpa_s, ssid, &ied)) {
656 wpa_dbg(wpa_s, MSG_DEBUG,
657 "SAE enabled, but disallowing SAE auth_alg without PMF");
658 } else {
659 wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
660 params.auth_alg = WPA_AUTH_ALG_SAE;
661 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800662 } else {
663 wpa_dbg(wpa_s, MSG_DEBUG,
664 "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800665 }
666 }
667#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700668
Hai Shalomfdcde762020-04-02 11:19:20 -0700669#ifdef CONFIG_WEP
670 {
671 int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700672
Hai Shalomfdcde762020-04-02 11:19:20 -0700673 for (i = 0; i < NUM_WEP_KEYS; i++) {
674 if (ssid->wep_key_len[i])
675 params.wep_key[i] = ssid->wep_key[i];
676 params.wep_key_len[i] = ssid->wep_key_len[i];
677 }
678 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
679 }
680#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700681
682 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
683 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800684 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685 int try_opportunistic;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700686 const u8 *cache_id = NULL;
687
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800688 try_opportunistic = (ssid->proactive_key_caching < 0 ?
689 wpa_s->conf->okc :
690 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691 (ssid->proto & WPA_PROTO_RSN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700692#ifdef CONFIG_FILS
693 if (wpa_key_mgmt_fils(ssid->key_mgmt))
694 cache_id = wpa_bss_get_fils_cache_id(bss);
695#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000696 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
697 params.mld ? params.ap_mld_addr :
698 bss->bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700699 wpa_s->current_ssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700700 try_opportunistic, cache_id,
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000701 0, false) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800702 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700703 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
704 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
705 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000706 &wpa_s->sme.assoc_req_ie_len,
707 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700708 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
709 "key management and encryption suites");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800710 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700711 return;
712 }
Hai Shalom74f70d42019-02-11 14:42:39 -0800713#ifdef CONFIG_HS20
714 } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
715 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
716 /* No PMKSA caching, but otherwise similar to RSN/WPA */
717 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
718 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
719 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000720 &wpa_s->sme.assoc_req_ie_len,
721 false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800722 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
723 "key management and encryption suites");
724 wpas_connect_work_done(wpa_s);
725 return;
726 }
727#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700728 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
729 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
730 /*
731 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
732 * use non-WPA since the scan results did not indicate that the
733 * AP is using WPA or WPA2.
734 */
735 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
736 wpa_s->sme.assoc_req_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800737 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700738 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
739 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
740 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000741 &wpa_s->sme.assoc_req_ie_len,
742 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
744 "key management and encryption suites (no "
745 "scan results)");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800746 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700747 return;
748 }
749#ifdef CONFIG_WPS
750 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
751 struct wpabuf *wps_ie;
752 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
753 if (wps_ie && wpabuf_len(wps_ie) <=
754 sizeof(wpa_s->sme.assoc_req_ie)) {
755 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
756 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
757 wpa_s->sme.assoc_req_ie_len);
758 } else
759 wpa_s->sme.assoc_req_ie_len = 0;
760 wpabuf_free(wps_ie);
761 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
762#endif /* CONFIG_WPS */
763 } else {
764 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
765 wpa_s->sme.assoc_req_ie_len = 0;
766 }
767
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800768 /* In case the WPA vendor IE is used, it should be placed after all the
769 * non-vendor IEs, as the lower layer expects the IEs to be ordered as
770 * defined in the standard. Store the WPA IE so it can later be
771 * inserted at the correct location.
772 */
773 wpa_ie = NULL;
774 wpa_ie_len = 0;
775 if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
776 wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
777 wpa_s->sme.assoc_req_ie_len);
778 if (wpa_ie) {
779 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
780
781 wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
782 wpa_s->sme.assoc_req_ie_len = 0;
783 } else {
784 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
785 wpas_connect_work_done(wpa_s);
786 return;
787 }
788 }
789
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700790#ifdef CONFIG_IEEE80211R
791 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
792 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
793 md = ie + 2;
794 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
Hai Shalom021b0b52019-04-10 11:17:58 -0700795 if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
796 !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
797 md = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798 if (md) {
799 /* Prepare for the next transition */
800 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
801 }
802
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700803 if (md) {
804 wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
805 md[0], md[1]);
806
Hai Shalomfdcde762020-04-02 11:19:20 -0700807 omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700808 if (wpa_s->sme.assoc_req_ie_len + 5 <
809 sizeof(wpa_s->sme.assoc_req_ie)) {
810 struct rsn_mdie *mdie;
811 u8 *pos = wpa_s->sme.assoc_req_ie +
812 wpa_s->sme.assoc_req_ie_len;
813 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
814 *pos++ = sizeof(*mdie);
815 mdie = (struct rsn_mdie *) pos;
816 os_memcpy(mdie->mobility_domain, md,
817 MOBILITY_DOMAIN_ID_LEN);
818 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
819 wpa_s->sme.assoc_req_ie_len += 5;
820 }
821
Hai Shalom74f70d42019-02-11 14:42:39 -0800822 if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700823 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
Sunil Ravi77d572f2023-01-17 23:58:31 +0000824 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700825 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
826 "over-the-air");
827 params.auth_alg = WPA_AUTH_ALG_FT;
828 params.ie = wpa_s->sme.ft_ies;
829 params.ie_len = wpa_s->sme.ft_ies_len;
830 }
831 }
832#endif /* CONFIG_IEEE80211R */
833
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800834 wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800835 if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700836 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
837 struct wpa_ie_data _ie;
838 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
839 _ie.capabilities &
840 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
841 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
842 "MFP: require MFP");
843 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
844 }
845 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700846
847#ifdef CONFIG_P2P
848 if (wpa_s->global->p2p) {
849 u8 *pos;
850 size_t len;
851 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700852 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
853 len = sizeof(wpa_s->sme.assoc_req_ie) -
854 wpa_s->sme.assoc_req_ie_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800855 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
856 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700857 if (res >= 0)
858 wpa_s->sme.assoc_req_ie_len += res;
859 }
860#endif /* CONFIG_P2P */
861
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800862#ifdef CONFIG_FST
863 if (wpa_s->fst_ies) {
864 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
865
866 if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <=
867 sizeof(wpa_s->sme.assoc_req_ie)) {
868 os_memcpy(wpa_s->sme.assoc_req_ie +
869 wpa_s->sme.assoc_req_ie_len,
870 wpabuf_head(wpa_s->fst_ies),
871 fst_ies_len);
872 wpa_s->sme.assoc_req_ie_len += fst_ies_len;
873 }
874 }
875#endif /* CONFIG_FST */
876
877 sme_auth_handle_rrm(wpa_s, bss);
878
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000879#ifndef CONFIG_NO_RRM
Dmitry Shmidt29333592017-01-09 12:27:11 -0800880 wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
Hai Shalomfdcde762020-04-02 11:19:20 -0700881 wpa_s, ssid, bss,
Dmitry Shmidt29333592017-01-09 12:27:11 -0800882 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
883 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000884#endif /* CONFIG_NO_RRM */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800885
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700886 if (params.p2p)
887 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
888 else
889 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
890
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800891 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000892 sizeof(ext_capab), bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800893 if (ext_capab_len > 0) {
894 u8 *pos = wpa_s->sme.assoc_req_ie;
895 if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
896 pos += 2 + pos[1];
897 os_memmove(pos + ext_capab_len, pos,
898 wpa_s->sme.assoc_req_ie_len -
899 (pos - wpa_s->sme.assoc_req_ie));
900 wpa_s->sme.assoc_req_ie_len += ext_capab_len;
901 os_memcpy(pos, ext_capab, ext_capab_len);
902 }
903
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800904#ifdef CONFIG_TESTING_OPTIONS
905 if (wpa_s->rsnxe_override_assoc &&
906 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
907 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
908 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
909 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
910 wpabuf_head(wpa_s->rsnxe_override_assoc),
911 wpabuf_len(wpa_s->rsnxe_override_assoc));
912 wpa_s->sme.assoc_req_ie_len +=
913 wpabuf_len(wpa_s->rsnxe_override_assoc);
914 } else
915#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -0700916 if (wpa_s->rsnxe_len > 0 &&
917 wpa_s->rsnxe_len <=
Hai Shalomfdcde762020-04-02 11:19:20 -0700918 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len &&
919 !omit_rsnxe) {
Hai Shalomc3565922019-10-28 11:58:20 -0700920 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
921 wpa_s->rsnxe, wpa_s->rsnxe_len);
922 wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
923 }
924
Dmitry Shmidt04949592012-07-19 12:16:46 -0700925#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -0800926 if (is_hs20_network(wpa_s, ssid, bss)
927#ifndef ANDROID /* Android does not use the native HS 2.0 config */
928 && is_hs20_config(wpa_s)
929#endif /* ANDROID */
930 ) {
Dmitry Shmidt04949592012-07-19 12:16:46 -0700931 struct wpabuf *hs20;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800932
Roshan Pius3a1667e2018-07-03 15:17:14 -0700933 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700934 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800935 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700936 size_t len;
937
Hai Shalom74f70d42019-02-11 14:42:39 -0800938 wpas_hs20_add_indication(hs20, pps_mo_id,
939 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -0700940 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700941 len = sizeof(wpa_s->sme.assoc_req_ie) -
942 wpa_s->sme.assoc_req_ie_len;
943 if (wpabuf_len(hs20) <= len) {
944 os_memcpy(wpa_s->sme.assoc_req_ie +
945 wpa_s->sme.assoc_req_ie_len,
946 wpabuf_head(hs20), wpabuf_len(hs20));
947 wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
948 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700949 wpabuf_free(hs20);
950 }
951 }
952#endif /* CONFIG_HS20 */
953
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800954 if (wpa_ie) {
955 size_t len;
956
957 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
958
959 len = sizeof(wpa_s->sme.assoc_req_ie) -
960 wpa_s->sme.assoc_req_ie_len;
961
962 if (len > wpa_ie_len) {
963 os_memcpy(wpa_s->sme.assoc_req_ie +
964 wpa_s->sme.assoc_req_ie_len,
965 wpa_ie, wpa_ie_len);
966 wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
967 } else {
968 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
969 }
970
971 os_free(wpa_ie);
972 }
973
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800974 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
975 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
976 size_t len;
977
978 len = sizeof(wpa_s->sme.assoc_req_ie) -
979 wpa_s->sme.assoc_req_ie_len;
980 if (wpabuf_len(buf) <= len) {
981 os_memcpy(wpa_s->sme.assoc_req_ie +
982 wpa_s->sme.assoc_req_ie_len,
983 wpabuf_head(buf), wpabuf_len(buf));
984 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
985 }
986 }
987
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800988#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -0700989 mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -0700990 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800991 int len;
992
993 len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
994 wpa_s->sme.assoc_req_ie_len,
995 sizeof(wpa_s->sme.assoc_req_ie) -
Hai Shalomce48b4a2018-09-05 11:41:35 -0700996 wpa_s->sme.assoc_req_ie_len,
997 !!mbo_attr_from_mbo_ie(mbo_ie,
998 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800999 if (len >= 0)
1000 wpa_s->sme.assoc_req_ie_len += len;
1001 }
1002#endif /* CONFIG_MBO */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001003
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001004#ifdef CONFIG_SAE
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001005 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001006 pmksa_cache_set_current(wpa_s->wpa, NULL,
1007 params.mld ? params.ap_mld_addr :
1008 bss->bssid,
1009 ssid, 0,
Hai Shalom021b0b52019-04-10 11:17:58 -07001010 NULL,
Sunil Ravi89eba102022-09-13 21:04:37 -07001011 wpa_key_mgmt_sae(wpa_s->key_mgmt) ?
1012 wpa_s->key_mgmt :
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001013 (int) WPA_KEY_MGMT_SAE, false) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001014 wpa_dbg(wpa_s, MSG_DEBUG,
1015 "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001016 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001017 params.auth_alg = WPA_AUTH_ALG_OPEN;
1018 wpa_s->sme.sae_pmksa_caching = 1;
1019 }
1020
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001021 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001022 if (start)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001023 resp = sme_auth_build_sae_commit(wpa_s, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001024 bss->bssid,
1025 params.mld ?
1026 params.ap_mld_addr :
1027 NULL, 0,
Hai Shalom899fcc72020-10-19 14:38:18 -07001028 start == 2, NULL,
1029 NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001030 else
Roshan Pius3a1667e2018-07-03 15:17:14 -07001031 resp = sme_auth_build_sae_confirm(wpa_s, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001032 if (resp == NULL) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001033 wpas_connection_failed(wpa_s, bss->bssid, NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001034 return;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001035 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001036 params.auth_data = wpabuf_head(resp);
1037 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001038 wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001039 }
1040#endif /* CONFIG_SAE */
1041
Hai Shalomfdcde762020-04-02 11:19:20 -07001042 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1043 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1044 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1045 if (bssid_changed)
1046 wpas_notify_bssid_changed(wpa_s);
1047
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001048 old_ssid = wpa_s->current_ssid;
1049 wpa_s->current_ssid = ssid;
1050 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1051 wpa_supplicant_initiate_eapol(wpa_s);
1052
1053#ifdef CONFIG_FILS
1054 /* TODO: FILS operations can in some cases be done between different
1055 * network_ctx (i.e., same credentials can be used with multiple
1056 * networks). */
1057 if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
1058 wpa_key_mgmt_fils(ssid->key_mgmt)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001059 const u8 *indic;
1060 u16 fils_info;
Hai Shalomce48b4a2018-09-05 11:41:35 -07001061 const u8 *realm, *username, *rrk;
1062 size_t realm_len, username_len, rrk_len;
1063 u16 next_seq_num;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001064
1065 /*
1066 * Check FILS Indication element (FILS Information field) bits
1067 * indicating supported authentication algorithms against local
1068 * configuration (ssid->fils_dh_group). Try to use FILS
1069 * authentication only if the AP supports the combination in the
1070 * network profile. */
1071 indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
1072 if (!indic || indic[1] < 2) {
1073 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1074 " does not include FILS Indication element - cannot use FILS authentication with it",
1075 MAC2STR(bss->bssid));
1076 goto no_fils;
1077 }
1078
1079 fils_info = WPA_GET_LE16(indic + 2);
1080 if (ssid->fils_dh_group == 0 && !(fils_info & BIT(9))) {
1081 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1082 " does not support FILS SK without PFS - cannot use FILS authentication with it",
1083 MAC2STR(bss->bssid));
1084 goto no_fils;
1085 }
1086 if (ssid->fils_dh_group != 0 && !(fils_info & BIT(10))) {
1087 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1088 " does not support FILS SK with PFS - cannot use FILS authentication with it",
1089 MAC2STR(bss->bssid));
1090 goto no_fils;
1091 }
1092
Hai Shalomce48b4a2018-09-05 11:41:35 -07001093 if (wpa_s->last_con_fail_realm &&
1094 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
1095 &username, &username_len,
1096 &realm, &realm_len, &next_seq_num,
1097 &rrk, &rrk_len) == 0 &&
1098 realm && realm_len == wpa_s->last_con_fail_realm_len &&
1099 os_memcmp(realm, wpa_s->last_con_fail_realm,
1100 realm_len) == 0) {
1101 wpa_printf(MSG_DEBUG,
1102 "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
1103 goto no_fils;
1104 }
1105
Sunil Ravi77d572f2023-01-17 23:58:31 +00001106 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
1107 params.mld ? params.ap_mld_addr :
1108 bss->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001109 ssid, 0,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001110 wpa_bss_get_fils_cache_id(bss),
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001111 0, false) == 0)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001112 wpa_printf(MSG_DEBUG,
1113 "SME: Try to use FILS with PMKSA caching");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001114 resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001115 if (resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001116 int auth_alg;
1117
1118 if (ssid->fils_dh_group)
1119 wpa_printf(MSG_DEBUG,
1120 "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
1121 ssid->fils_dh_group);
1122 else
1123 wpa_printf(MSG_DEBUG,
1124 "SME: Try to use FILS SK authentication without PFS");
1125 auth_alg = ssid->fils_dh_group ?
1126 WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
1127 params.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001128 params.auth_data = wpabuf_head(resp);
1129 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001130 wpa_s->sme.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001131 }
1132 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001133no_fils:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001134#endif /* CONFIG_FILS */
1135
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001136 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001137 wpa_supplicant_cancel_scan(wpa_s);
1138
1139 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
1140 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
1141 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
1142
Hai Shalome21d4e82020-04-29 16:34:06 -07001143 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001144 wpa_clear_keys(wpa_s, bss->bssid);
1145 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001146 if (old_ssid != wpa_s->current_ssid)
1147 wpas_notify_network_changed(wpa_s);
1148
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001149#ifdef CONFIG_HS20
1150 hs20_configure_frame_filters(wpa_s);
1151#endif /* CONFIG_HS20 */
1152
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001153#ifdef CONFIG_P2P
1154 /*
1155 * If multi-channel concurrency is not supported, check for any
1156 * frequency conflict. In case of any frequency conflict, remove the
1157 * least prioritized connection.
1158 */
1159 if (wpa_s->num_multichan_concurrent < 2) {
1160 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001161 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001162 if (num > 0 && freq > 0 && freq != params.freq) {
1163 wpa_printf(MSG_DEBUG,
1164 "Conflicting frequency found (%d != %d)",
1165 freq, params.freq);
1166 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1167 params.freq,
1168 ssid) < 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001169 wpas_connection_failed(wpa_s, bss->bssid, NULL);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001170 wpa_supplicant_mark_disassoc(wpa_s);
1171 wpabuf_free(resp);
1172 wpas_connect_work_done(wpa_s);
1173 return;
1174 }
1175 }
1176 }
1177#endif /* CONFIG_P2P */
1178
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001179 if (skip_auth) {
1180 wpa_msg(wpa_s, MSG_DEBUG,
1181 "SME: Skip authentication step on reassoc-to-same-BSS");
1182 wpabuf_free(resp);
1183 sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN);
1184 return;
1185 }
1186
1187
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001188 wpa_s->sme.auth_alg = params.auth_alg;
1189 if (wpa_drv_authenticate(wpa_s, &params) < 0) {
1190 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
1191 "driver failed");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001192 wpas_connection_failed(wpa_s, bss->bssid, NULL);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001193 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001194 wpabuf_free(resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001195 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001196 return;
1197 }
1198
1199 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
1200 NULL);
1201
1202 /*
1203 * Association will be started based on the authentication event from
1204 * the driver.
1205 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001206
1207 wpabuf_free(resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001208}
1209
1210
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001211static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
1212{
1213 struct wpa_connect_work *cwork = work->ctx;
1214 struct wpa_supplicant *wpa_s = work->wpa_s;
1215
Hai Shaloma20dcd72022-02-04 13:43:00 -08001216 wpa_s->roam_in_progress = false;
1217#ifdef CONFIG_WNM
1218 wpa_s->bss_trans_mgmt_in_progress = false;
1219#endif /* CONFIG_WNM */
1220
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001221 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001222 if (work->started)
1223 wpa_s->connect_work = NULL;
1224
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001225 wpas_connect_work_free(cwork);
1226 return;
1227 }
1228
1229 wpa_s->connect_work = work;
1230
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001231 if (cwork->bss_removed ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001232 !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
1233 wpas_network_disabled(wpa_s, cwork->ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001234 wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
1235 wpas_connect_work_done(wpa_s);
1236 return;
1237 }
1238
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001239 /* Starting new connection, so clear the possibly used WPA IE from the
1240 * previous association. */
1241 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07001242 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
1243 wpa_s->rsnxe_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001244
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001245 sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001246 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001247}
1248
1249
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001250void sme_authenticate(struct wpa_supplicant *wpa_s,
1251 struct wpa_bss *bss, struct wpa_ssid *ssid)
1252{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001253 struct wpa_connect_work *cwork;
1254
1255 if (bss == NULL || ssid == NULL)
1256 return;
1257 if (wpa_s->connect_work) {
1258 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
1259 return;
1260 }
1261
Hai Shaloma20dcd72022-02-04 13:43:00 -08001262 if (wpa_s->roam_in_progress) {
1263 wpa_dbg(wpa_s, MSG_DEBUG,
1264 "SME: Reject sme_authenticate() in favor of explicit roam request");
1265 return;
1266 }
1267#ifdef CONFIG_WNM
1268 if (wpa_s->bss_trans_mgmt_in_progress) {
1269 wpa_dbg(wpa_s, MSG_DEBUG,
1270 "SME: Reject sme_authenticate() in favor of BSS transition management request");
1271 return;
1272 }
1273#endif /* CONFIG_WNM */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001274 if (radio_work_pending(wpa_s, "sme-connect")) {
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001275 /*
1276 * The previous sme-connect work might no longer be valid due to
1277 * the fact that the BSS list was updated. In addition, it makes
1278 * sense to adhere to the 'newer' decision.
1279 */
1280 wpa_dbg(wpa_s, MSG_DEBUG,
1281 "SME: Remove previous pending sme-connect");
1282 radio_remove_works(wpa_s, "sme-connect", 0);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001283 }
1284
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001285 wpas_abort_ongoing_scan(wpa_s);
1286
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001287 cwork = os_zalloc(sizeof(*cwork));
1288 if (cwork == NULL)
1289 return;
1290 cwork->bss = bss;
1291 cwork->ssid = ssid;
1292 cwork->sme = 1;
1293
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001294#ifdef CONFIG_SAE
1295 wpa_s->sme.sae.state = SAE_NOTHING;
1296 wpa_s->sme.sae.send_confirm = 0;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001297 wpa_s->sme.sae_group_index = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001298#endif /* CONFIG_SAE */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001299
1300 if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
1301 sme_auth_start_cb, cwork) < 0)
1302 wpas_connect_work_free(cwork);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001303}
1304
1305
1306#ifdef CONFIG_SAE
1307
Sunil Ravi036cec52023-03-29 11:35:17 -07001308#define WPA_AUTH_FRAME_ML_IE_LEN (6 + ETH_ALEN)
1309
1310static void wpa_auth_ml_ie(struct wpabuf *buf, const u8 *mld_addr)
1311{
1312
1313 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1314 wpabuf_put_u8(buf, 4 + ETH_ALEN);
1315 wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK);
1316
1317 /* Basic Multi-Link element Control field */
1318 wpabuf_put_u8(buf, 0x0);
1319 wpabuf_put_u8(buf, 0x0);
1320
1321 /* Common Info */
1322 wpabuf_put_u8(buf, 0x7); /* length = Length field + MLD MAC address */
1323 wpabuf_put_data(buf, mld_addr, ETH_ALEN);
1324}
1325
1326
Roshan Pius3a1667e2018-07-03 15:17:14 -07001327static int sme_external_auth_build_buf(struct wpabuf *buf,
1328 struct wpabuf *params,
1329 const u8 *sa, const u8 *da,
Hai Shalomc3565922019-10-28 11:58:20 -07001330 u16 auth_transaction, u16 seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001331 u16 status_code, const u8 *mld_addr)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001332{
1333 struct ieee80211_mgmt *resp;
1334
1335 resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
1336 u.auth.variable));
1337
1338 resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
1339 (WLAN_FC_STYPE_AUTH << 4));
1340 os_memcpy(resp->da, da, ETH_ALEN);
1341 os_memcpy(resp->sa, sa, ETH_ALEN);
1342 os_memcpy(resp->bssid, da, ETH_ALEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08001343 resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
1344 resp->seq_ctrl = host_to_le16(seq_num << 4);
1345 resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
Hai Shalomc3565922019-10-28 11:58:20 -07001346 resp->u.auth.status_code = host_to_le16(status_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001347 if (params)
1348 wpabuf_put_buf(buf, params);
1349
Sunil Ravi036cec52023-03-29 11:35:17 -07001350 if (mld_addr)
1351 wpa_auth_ml_ie(buf, mld_addr);
1352
Roshan Pius3a1667e2018-07-03 15:17:14 -07001353 return 0;
1354}
1355
1356
Hai Shalom81f62d82019-07-22 12:10:00 -07001357static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
1358 const u8 *bssid,
1359 struct wpa_ssid *ssid)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001360{
1361 struct wpabuf *resp, *buf;
Hai Shalomc3565922019-10-28 11:58:20 -07001362 int use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -07001363 bool use_pk;
1364 u16 status;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001365
Sunil Ravi036cec52023-03-29 11:35:17 -07001366 resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid,
1367 wpa_s->sme.ext_ml_auth ?
1368 wpa_s->sme.ext_auth_ap_mld_addr : NULL,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001369 1, 0, &use_pt, &use_pk);
Hai Shalom81f62d82019-07-22 12:10:00 -07001370 if (!resp) {
1371 wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
1372 return -1;
1373 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001374
1375 wpa_s->sme.sae.state = SAE_COMMITTED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001376 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp) +
1377 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1378 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001379 if (!buf) {
1380 wpabuf_free(resp);
Hai Shalom81f62d82019-07-22 12:10:00 -07001381 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001382 }
1383
1384 wpa_s->sme.seq_num++;
Hai Shalom899fcc72020-10-19 14:38:18 -07001385 if (use_pk)
1386 status = WLAN_STATUS_SAE_PK;
1387 else if (use_pt)
1388 status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
1389 else
1390 status = WLAN_STATUS_SUCCESS;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001391 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Sunil Ravi036cec52023-03-29 11:35:17 -07001392 wpa_s->sme.ext_ml_auth ?
1393 wpa_s->sme.ext_auth_ap_mld_addr : bssid, 1,
1394 wpa_s->sme.seq_num, status,
1395 wpa_s->sme.ext_ml_auth ?
1396 wpa_s->own_addr : NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07001397 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001398 wpabuf_free(resp);
1399 wpabuf_free(buf);
Hai Shalom81f62d82019-07-22 12:10:00 -07001400
1401 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001402}
1403
1404
1405static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
1406 u16 status)
1407{
1408 struct external_auth params;
1409
Sunil Ravi89eba102022-09-13 21:04:37 -07001410 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001411 os_memset(&params, 0, sizeof(params));
1412 params.status = status;
Hai Shalom66904732019-05-29 11:54:04 -07001413 params.ssid = wpa_s->sme.ext_auth_ssid;
1414 params.ssid_len = wpa_s->sme.ext_auth_ssid_len;
1415 params.bssid = wpa_s->sme.ext_auth_bssid;
Hai Shalomc3565922019-10-28 11:58:20 -07001416 if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
1417 params.pmkid = wpa_s->sme.sae.pmkid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001418 wpa_drv_send_external_auth_status(wpa_s, &params);
1419}
1420
1421
Hai Shalom81f62d82019-07-22 12:10:00 -07001422static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
1423 union wpa_event_data *data)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001424{
1425 struct wpa_ssid *ssid;
1426 size_t ssid_str_len = data->external_auth.ssid_len;
Hai Shalom5f92bc92019-04-18 11:54:11 -07001427 const u8 *ssid_str = data->external_auth.ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001428
Sunil Ravi89eba102022-09-13 21:04:37 -07001429 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001430 /* Get the SSID conf from the ssid string obtained */
1431 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1432 if (!wpas_network_disabled(wpa_s, ssid) &&
1433 ssid_str_len == ssid->ssid_len &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001434 os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001435 wpa_key_mgmt_sae(ssid->key_mgmt)) {
1436 /* Make sure PT is derived */
Sunil Ravi036cec52023-03-29 11:35:17 -07001437 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Sunil Ravi89eba102022-09-13 21:04:37 -07001438 wpa_s->sme.ext_auth_wpa_ssid = ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001439 break;
Sunil Ravi89eba102022-09-13 21:04:37 -07001440 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001441 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001442 if (!ssid ||
1443 sme_external_auth_send_sae_commit(wpa_s, data->external_auth.bssid,
1444 ssid) < 0)
1445 return -1;
1446
1447 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001448}
1449
1450
1451static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
1452 const u8 *da)
1453{
1454 struct wpabuf *resp, *buf;
1455
1456 resp = sme_auth_build_sae_confirm(wpa_s, 1);
1457 if (!resp) {
1458 wpa_printf(MSG_DEBUG, "SAE: Confirm message buf alloc failure");
1459 return;
1460 }
1461
1462 wpa_s->sme.sae.state = SAE_CONFIRMED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001463 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp) +
1464 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1465 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001466 if (!buf) {
1467 wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure");
1468 wpabuf_free(resp);
1469 return;
1470 }
1471 wpa_s->sme.seq_num++;
1472 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Hai Shalomc3565922019-10-28 11:58:20 -07001473 da, 2, wpa_s->sme.seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001474 WLAN_STATUS_SUCCESS,
1475 wpa_s->sme.ext_ml_auth ?
1476 wpa_s->own_addr : NULL);
1477
Hai Shalomfdcde762020-04-02 11:19:20 -07001478 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001479 wpabuf_free(resp);
1480 wpabuf_free(buf);
1481}
1482
1483
Sunil Ravi77d572f2023-01-17 23:58:31 +00001484static bool is_sae_key_mgmt_suite(struct wpa_supplicant *wpa_s, u32 suite)
1485{
1486 /* suite is supposed to be the selector value in host byte order with
1487 * the OUI in three most significant octets. However, the initial
1488 * implementation swapped that byte order and did not work with drivers
1489 * that followed the expected byte order. Keep a workaround here to
1490 * match that initial implementation so that already deployed use cases
1491 * remain functional. */
1492 if (RSN_SELECTOR_GET(&suite) == RSN_AUTH_KEY_MGMT_SAE) {
1493 /* Old drivers which follow initial implementation send SAE AKM
1494 * for both SAE and FT-SAE connections. In that case, determine
1495 * the actual AKM from wpa_s->key_mgmt. */
1496 wpa_s->sme.ext_auth_key_mgmt = wpa_s->key_mgmt;
1497 return true;
1498 }
1499
1500 if (suite == RSN_AUTH_KEY_MGMT_SAE)
1501 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE;
1502 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE)
1503 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE;
1504 else if (suite == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
1505 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1506 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
1507 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1508 else
1509 return false;
1510
1511 return true;
1512}
1513
1514
Roshan Pius3a1667e2018-07-03 15:17:14 -07001515void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
1516 union wpa_event_data *data)
1517{
Sunil Ravi77d572f2023-01-17 23:58:31 +00001518 if (!is_sae_key_mgmt_suite(wpa_s, data->external_auth.key_mgmt_suite))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001519 return;
1520
1521 if (data->external_auth.action == EXT_AUTH_START) {
Hai Shalom66904732019-05-29 11:54:04 -07001522 if (!data->external_auth.bssid || !data->external_auth.ssid)
1523 return;
1524 os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid,
1525 ETH_ALEN);
1526 os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid,
1527 data->external_auth.ssid_len);
1528 wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len;
Sunil Ravi036cec52023-03-29 11:35:17 -07001529 if (data->external_auth.mld_addr) {
1530 wpa_s->sme.ext_ml_auth = true;
1531 os_memcpy(wpa_s->sme.ext_auth_ap_mld_addr,
1532 data->external_auth.mld_addr, ETH_ALEN);
1533 } else {
1534 wpa_s->sme.ext_ml_auth = false;
1535 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001536 wpa_s->sme.seq_num = 0;
1537 wpa_s->sme.sae.state = SAE_NOTHING;
1538 wpa_s->sme.sae.send_confirm = 0;
1539 wpa_s->sme.sae_group_index = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001540 if (sme_handle_external_auth_start(wpa_s, data) < 0)
1541 sme_send_external_auth_status(wpa_s,
1542 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001543 } else if (data->external_auth.action == EXT_AUTH_ABORT) {
1544 /* Report failure to driver for the wrong trigger */
1545 sme_send_external_auth_status(wpa_s,
1546 WLAN_STATUS_UNSPECIFIED_FAILURE);
1547 }
1548}
1549
1550
Hai Shalomc3565922019-10-28 11:58:20 -07001551static int sme_sae_is_group_enabled(struct wpa_supplicant *wpa_s, int group)
1552{
1553 int *groups = wpa_s->conf->sae_groups;
1554 int default_groups[] = { 19, 20, 21, 0 };
1555 int i;
1556
1557 if (!groups)
1558 groups = default_groups;
1559
1560 for (i = 0; groups[i] > 0; i++) {
1561 if (groups[i] == group)
1562 return 1;
1563 }
1564
1565 return 0;
1566}
1567
1568
1569static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
1570 const struct wpabuf *groups)
1571{
1572 size_t i, count;
1573 const u8 *pos;
1574
1575 if (!groups)
1576 return 0;
1577
1578 pos = wpabuf_head(groups);
1579 count = wpabuf_len(groups) / 2;
1580 for (i = 0; i < count; i++) {
1581 int enabled;
1582 u16 group;
1583
1584 group = WPA_GET_LE16(pos);
1585 pos += 2;
1586 enabled = sme_sae_is_group_enabled(wpa_s, group);
1587 wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
1588 group, enabled ? "enabled" : "disabled");
1589 if (enabled)
1590 return 1;
1591 }
1592
1593 return 0;
1594}
1595
1596
Sunil Ravi036cec52023-03-29 11:35:17 -07001597static int sme_external_ml_auth(struct wpa_supplicant *wpa_s,
Sunil Ravi640215c2023-06-28 23:08:09 +00001598 const u8 *data, size_t len, int ie_offset,
1599 u16 status_code)
Sunil Ravi036cec52023-03-29 11:35:17 -07001600{
1601 struct ieee802_11_elems elems;
1602 const u8 *mld_addr;
1603
1604 if (ieee802_11_parse_elems(data + ie_offset, len - ie_offset,
Sunil Ravi640215c2023-06-28 23:08:09 +00001605 &elems, 0) == ParseFailed) {
Sunil Ravi036cec52023-03-29 11:35:17 -07001606 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
1607 return -1;
1608 }
1609
1610 if (!elems.basic_mle || !elems.basic_mle_len) {
1611 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
Sunil Ravi640215c2023-06-28 23:08:09 +00001612 if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
1613 status_code == WLAN_STATUS_SUCCESS ||
1614 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
1615 status_code == WLAN_STATUS_SAE_PK)
1616 return -1;
1617 /* Accept missing Multi-Link element in failed authentication
1618 * cases. */
1619 return 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07001620 }
1621
1622 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
1623 if (!mld_addr) {
1624 wpa_printf(MSG_DEBUG, "MLD: No MLD address in ML element");
1625 return -1;
1626 }
1627
1628 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
1629
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001630 if (!ether_addr_equal(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr)) {
Sunil Ravi036cec52023-03-29 11:35:17 -07001631 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
Sunil Ravi640215c2023-06-28 23:08:09 +00001632 MACSTR ")",
1633 MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr));
Sunil Ravi036cec52023-03-29 11:35:17 -07001634 return -1;
1635 }
1636
1637 return 0;
1638}
1639
1640
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001641static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001642 u16 status_code, const u8 *data, size_t len,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001643 int external, const u8 *sa, int *ie_offset)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001644{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001645 int *groups;
1646
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001647 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
1648 "status code %u", auth_transaction, status_code);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001649
1650 if (auth_transaction == 1 &&
1651 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1652 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001653 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1654 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001655 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001656 u16 group;
Hai Shalomfdcde762020-04-02 11:19:20 -07001657 const u8 *token_pos;
1658 size_t token_len;
1659 int h2e = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001660
1661 groups = wpa_s->conf->sae_groups;
1662 if (!groups || groups[0] <= 0)
1663 groups = default_groups;
1664
Hai Shalomfdcde762020-04-02 11:19:20 -07001665 wpa_hexdump(MSG_DEBUG, "SME: SAE anti-clogging token request",
1666 data, len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001667 if (len < sizeof(le16)) {
1668 wpa_dbg(wpa_s, MSG_DEBUG,
1669 "SME: Too short SAE anti-clogging token request");
1670 return -1;
1671 }
1672 group = WPA_GET_LE16(data);
1673 wpa_dbg(wpa_s, MSG_DEBUG,
1674 "SME: SAE anti-clogging token requested (group %u)",
1675 group);
1676 if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
1677 WLAN_STATUS_SUCCESS) {
1678 wpa_dbg(wpa_s, MSG_ERROR,
1679 "SME: SAE group %u of anti-clogging request is invalid",
1680 group);
1681 return -1;
1682 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001683 wpabuf_free(wpa_s->sme.sae_token);
Hai Shalomfdcde762020-04-02 11:19:20 -07001684 token_pos = data + sizeof(le16);
1685 token_len = len - sizeof(le16);
Hai Shalom899fcc72020-10-19 14:38:18 -07001686 h2e = wpa_s->sme.sae.h2e;
Hai Shalomfdcde762020-04-02 11:19:20 -07001687 if (h2e) {
Sunil8cd6f4d2022-06-28 18:40:46 +00001688 u8 id, elen, extid;
1689
Hai Shalomfdcde762020-04-02 11:19:20 -07001690 if (token_len < 3) {
1691 wpa_dbg(wpa_s, MSG_DEBUG,
1692 "SME: Too short SAE anti-clogging token container");
1693 return -1;
1694 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001695 id = *token_pos++;
1696 elen = *token_pos++;
1697 extid = *token_pos++;
1698 if (id != WLAN_EID_EXTENSION ||
1699 elen == 0 || elen > token_len - 2 ||
1700 extid != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001701 wpa_dbg(wpa_s, MSG_DEBUG,
1702 "SME: Invalid SAE anti-clogging token container header");
1703 return -1;
1704 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001705 token_len = elen - 1;
Hai Shalomfdcde762020-04-02 11:19:20 -07001706 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00001707
Sunil Ravi036cec52023-03-29 11:35:17 -07001708 *ie_offset = token_pos + token_len - data;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001709
Hai Shalomfdcde762020-04-02 11:19:20 -07001710 wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001711 if (!wpa_s->sme.sae_token) {
1712 wpa_dbg(wpa_s, MSG_ERROR,
1713 "SME: Failed to allocate SAE token");
1714 return -1;
1715 }
1716
Hai Shalomfdcde762020-04-02 11:19:20 -07001717 wpa_hexdump_buf(MSG_DEBUG, "SME: Requested anti-clogging token",
1718 wpa_s->sme.sae_token);
Sunil Ravi036cec52023-03-29 11:35:17 -07001719 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001720 sme_send_authentication(wpa_s, wpa_s->current_bss,
Hai Shalom021b0b52019-04-10 11:17:58 -07001721 wpa_s->current_ssid, 2);
Sunil Ravi036cec52023-03-29 11:35:17 -07001722 } else {
1723 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001724 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1725 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001726 return -1;
1727
Roshan Pius3a1667e2018-07-03 15:17:14 -07001728 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001729 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001730 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001731 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001732 return 0;
1733 }
1734
1735 if (auth_transaction == 1 &&
1736 status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1737 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001738 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1739 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001740 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
Hai Shalomc3565922019-10-28 11:58:20 -07001741 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1742 wpa_s->sme.sae.group);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001743 wpa_s->sme.sae_group_index++;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001744 if (sme_set_sae_group(wpa_s, external) < 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001745 return -1; /* no other groups enabled */
1746 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
Sunil Ravi036cec52023-03-29 11:35:17 -07001747 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001748 sme_send_authentication(wpa_s, wpa_s->current_bss,
1749 wpa_s->current_ssid, 1);
Sunil Ravi036cec52023-03-29 11:35:17 -07001750 } else {
1751 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001752 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1753 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001754 return -1;
1755
Roshan Pius3a1667e2018-07-03 15:17:14 -07001756 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001757 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001758 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001759 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001760 return 0;
1761 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001762
Roshan Pius3a1667e2018-07-03 15:17:14 -07001763 if (auth_transaction == 1 &&
1764 status_code == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1765 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1766
1767 wpa_msg(wpa_s, MSG_INFO,
1768 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR,
1769 MAC2STR(bssid));
1770 return -1;
1771 }
1772
Hai Shalomc3565922019-10-28 11:58:20 -07001773 if (status_code != WLAN_STATUS_SUCCESS &&
Hai Shalom899fcc72020-10-19 14:38:18 -07001774 status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08001775 status_code != WLAN_STATUS_SAE_PK) {
1776 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1777
1778 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
1779 " auth_type=%u auth_transaction=%u status_code=%u",
1780 MAC2STR(bssid), WLAN_AUTH_SAE,
1781 auth_transaction, status_code);
Sunil Ravia04bd252022-05-02 22:54:18 -07001782 return -2;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001783 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001784
1785 if (auth_transaction == 1) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07001786 u16 res;
1787
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001788 groups = wpa_s->conf->sae_groups;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001789
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001790 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
Sunil Ravi89eba102022-09-13 21:04:37 -07001791 if ((external && !wpa_s->sme.ext_auth_wpa_ssid) ||
1792 (!external &&
1793 (!wpa_s->current_bss || !wpa_s->current_ssid)))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001794 return -1;
Hai Shalomc3565922019-10-28 11:58:20 -07001795 if (wpa_s->sme.sae.state != SAE_COMMITTED) {
1796 wpa_printf(MSG_DEBUG,
1797 "SAE: Ignore commit message while waiting for confirm");
1798 return 0;
1799 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001800 if (wpa_s->sme.sae.h2e && status_code == WLAN_STATUS_SUCCESS) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001801 wpa_printf(MSG_DEBUG,
1802 "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
1803 return -1;
1804 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001805 if ((!wpa_s->sme.sae.h2e || wpa_s->sme.sae.pk) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001806 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
1807 wpa_printf(MSG_DEBUG,
1808 "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
1809 return -1;
1810 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001811 if (!wpa_s->sme.sae.pk &&
1812 status_code == WLAN_STATUS_SAE_PK) {
1813 wpa_printf(MSG_DEBUG,
1814 "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected");
1815 return -1;
1816 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001817
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001818 if (groups && groups[0] <= 0)
1819 groups = NULL;
Dmitry Shmidt41712582015-06-29 11:02:15 -07001820 res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
Hai Shalomc3565922019-10-28 11:58:20 -07001821 groups, status_code ==
Hai Shalom899fcc72020-10-19 14:38:18 -07001822 WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001823 status_code == WLAN_STATUS_SAE_PK,
1824 ie_offset);
Dmitry Shmidt41712582015-06-29 11:02:15 -07001825 if (res == SAE_SILENTLY_DISCARD) {
1826 wpa_printf(MSG_DEBUG,
1827 "SAE: Drop commit message due to reflection attack");
1828 return 0;
1829 }
1830 if (res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001831 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001832
Hai Shalomc3565922019-10-28 11:58:20 -07001833 if (wpa_s->sme.sae.tmp &&
1834 sme_check_sae_rejected_groups(
1835 wpa_s,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001836 wpa_s->sme.sae.tmp->peer_rejected_groups))
Hai Shalomc3565922019-10-28 11:58:20 -07001837 return -1;
1838
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001839 if (sae_process_commit(&wpa_s->sme.sae) < 0) {
1840 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
1841 "commit");
1842 return -1;
1843 }
1844
1845 wpabuf_free(wpa_s->sme.sae_token);
1846 wpa_s->sme.sae_token = NULL;
Sunil Ravi036cec52023-03-29 11:35:17 -07001847 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001848 sme_send_authentication(wpa_s, wpa_s->current_bss,
1849 wpa_s->current_ssid, 0);
Sunil Ravi036cec52023-03-29 11:35:17 -07001850 } else {
1851 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001852 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1853 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001854 return -1;
1855
Roshan Pius3a1667e2018-07-03 15:17:14 -07001856 sme_external_auth_send_sae_confirm(wpa_s, sa);
Sunil Ravi036cec52023-03-29 11:35:17 -07001857 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001858 return 0;
1859 } else if (auth_transaction == 2) {
Hai Shalomc3565922019-10-28 11:58:20 -07001860 if (status_code != WLAN_STATUS_SUCCESS)
1861 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001862 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001863 if (wpa_s->sme.sae.state != SAE_CONFIRMED)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001864 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001865 if (sae_check_confirm(&wpa_s->sme.sae, data, len,
1866 ie_offset) < 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001867 return -1;
Sunil Ravi036cec52023-03-29 11:35:17 -07001868 if (external && wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001869 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1870 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001871 return -1;
1872
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001873 wpa_s->sme.sae.state = SAE_ACCEPTED;
1874 sae_clear_temp_data(&wpa_s->sme.sae);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001875
1876 if (external) {
1877 /* Report success to driver */
1878 sme_send_external_auth_status(wpa_s,
1879 WLAN_STATUS_SUCCESS);
1880 }
1881
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001882 return 1;
1883 }
1884
1885 return -1;
1886}
Roshan Pius3a1667e2018-07-03 15:17:14 -07001887
1888
Hai Shalomc3565922019-10-28 11:58:20 -07001889static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
1890{
1891 wpa_printf(MSG_DEBUG,
1892 "SME: SAE completed - setting PMK for 4-way handshake");
Sunil Ravi89eba102022-09-13 21:04:37 -07001893 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 -07001894 wpa_s->sme.sae.pmkid, bssid);
1895 if (wpa_s->conf->sae_pmkid_in_assoc) {
1896 /* Update the own RSNE contents now that we have set the PMK
1897 * and added a PMKSA cache entry based on the successfully
1898 * completed SAE exchange. In practice, this will add the PMKID
1899 * into RSNE. */
1900 if (wpa_s->sme.assoc_req_ie_len + 2 + PMKID_LEN >
1901 sizeof(wpa_s->sme.assoc_req_ie)) {
1902 wpa_msg(wpa_s, MSG_WARNING,
1903 "RSN: Not enough room for inserting own PMKID into RSNE");
1904 return -1;
1905 }
1906 if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
1907 &wpa_s->sme.assoc_req_ie_len,
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001908 wpa_s->sme.sae.pmkid, true) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07001909 return -1;
1910 wpa_hexdump(MSG_DEBUG,
1911 "SME: Updated Association Request IEs",
1912 wpa_s->sme.assoc_req_ie,
1913 wpa_s->sme.assoc_req_ie_len);
1914 }
1915
1916 return 0;
1917}
1918
1919
Roshan Pius3a1667e2018-07-03 15:17:14 -07001920void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
1921 const u8 *auth_frame, size_t len)
1922{
1923 const struct ieee80211_mgmt *header;
1924 size_t auth_length;
1925
1926 header = (const struct ieee80211_mgmt *) auth_frame;
1927 auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);
1928
1929 if (len < auth_length) {
1930 /* Notify failure to the driver */
1931 sme_send_external_auth_status(wpa_s,
1932 WLAN_STATUS_UNSPECIFIED_FAILURE);
1933 return;
1934 }
1935
Hai Shalom74f70d42019-02-11 14:42:39 -08001936 if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001937 int res;
Sunil Ravi036cec52023-03-29 11:35:17 -07001938 int ie_offset = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001939
Hai Shalom74f70d42019-02-11 14:42:39 -08001940 res = sme_sae_auth(
1941 wpa_s, le_to_host16(header->u.auth.auth_transaction),
1942 le_to_host16(header->u.auth.status_code),
1943 header->u.auth.variable,
Sunil Ravi036cec52023-03-29 11:35:17 -07001944 len - auth_length, 1, header->sa, &ie_offset);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001945 if (res < 0) {
1946 /* Notify failure to the driver */
1947 sme_send_external_auth_status(
Sunil Ravia04bd252022-05-02 22:54:18 -07001948 wpa_s,
1949 res == -2 ?
1950 le_to_host16(header->u.auth.status_code) :
1951 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001952 return;
1953 }
1954 if (res != 1)
1955 return;
1956
Sunil Ravi036cec52023-03-29 11:35:17 -07001957 if (sme_sae_set_pmk(wpa_s,
1958 wpa_s->sme.ext_ml_auth ?
1959 wpa_s->sme.ext_auth_ap_mld_addr :
1960 wpa_s->sme.ext_auth_bssid) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07001961 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001962 }
1963}
1964
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001965#endif /* CONFIG_SAE */
1966
1967
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
1969{
1970 struct wpa_ssid *ssid = wpa_s->current_ssid;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001971 int ie_offset = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001972
1973 if (ssid == NULL) {
1974 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1975 "when network is not selected");
1976 return;
1977 }
1978
1979 if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
1980 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1981 "when not in authenticating state");
1982 return;
1983 }
1984
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001985 if (!ether_addr_equal(wpa_s->pending_bssid, data->auth.peer) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001986 !(wpa_s->valid_links &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001987 ether_addr_equal(wpa_s->ap_mld_addr, data->auth.peer))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001988 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
1989 "unexpected peer " MACSTR,
1990 MAC2STR(data->auth.peer));
1991 return;
1992 }
1993
1994 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001995 " auth_type=%d auth_transaction=%d status_code=%d",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001996 MAC2STR(data->auth.peer), data->auth.auth_type,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001997 data->auth.auth_transaction, data->auth.status_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
1999 data->auth.ies, data->auth.ies_len);
2000
2001 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2002
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002003#ifdef CONFIG_SAE
2004 if (data->auth.auth_type == WLAN_AUTH_SAE) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002005 const u8 *addr = wpa_s->pending_bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002006 int res;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002007
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002008 res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
2009 data->auth.status_code, data->auth.ies,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002010 data->auth.ies_len, 0, data->auth.peer,
2011 &ie_offset);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002012 if (res < 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002013 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2014 NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002015 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2016
2017 }
2018 if (res != 1)
2019 return;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002020
Sunil Ravi77d572f2023-01-17 23:58:31 +00002021 if (wpa_s->valid_links)
2022 addr = wpa_s->ap_mld_addr;
2023
2024 if (sme_sae_set_pmk(wpa_s, addr) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002025 return;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002026 }
2027#endif /* CONFIG_SAE */
2028
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002029 if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002030 char *ie_txt = NULL;
2031
2032 if (data->auth.ies && data->auth.ies_len) {
2033 size_t buflen = 2 * data->auth.ies_len + 1;
2034 ie_txt = os_malloc(buflen);
2035 if (ie_txt) {
2036 wpa_snprintf_hex(ie_txt, buflen, data->auth.ies,
2037 data->auth.ies_len);
2038 }
2039 }
2040 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002041 " auth_type=%u auth_transaction=%u status_code=%u%s%s",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002042 MAC2STR(data->auth.peer), data->auth.auth_type,
2043 data->auth.auth_transaction, data->auth.status_code,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002044 ie_txt ? " ie=" : "",
2045 ie_txt ? ie_txt : "");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002046 os_free(ie_txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002047
Hai Shalomce48b4a2018-09-05 11:41:35 -07002048#ifdef CONFIG_FILS
2049 if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
2050 wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS)
2051 fils_connection_failure(wpa_s);
2052#endif /* CONFIG_FILS */
2053
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054 if (data->auth.status_code !=
2055 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
2056 wpa_s->sme.auth_alg == data->auth.auth_type ||
2057 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002058 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2059 NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002060 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061 return;
2062 }
2063
Dmitry Shmidt97672262014-02-03 13:02:54 -08002064 wpas_connect_work_done(wpa_s);
2065
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002066 switch (data->auth.auth_type) {
2067 case WLAN_AUTH_OPEN:
2068 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
2069
2070 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
2071 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2072 wpa_s->current_ssid);
2073 return;
2074
2075 case WLAN_AUTH_SHARED_KEY:
2076 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
2077
2078 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
2079 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2080 wpa_s->current_ssid);
2081 return;
2082
2083 default:
2084 return;
2085 }
2086 }
2087
2088#ifdef CONFIG_IEEE80211R
2089 if (data->auth.auth_type == WLAN_AUTH_FT) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002090 const u8 *ric_ies = NULL;
2091 size_t ric_ies_len = 0;
2092
2093 if (wpa_s->ric_ies) {
2094 ric_ies = wpabuf_head(wpa_s->ric_ies);
2095 ric_ies_len = wpabuf_len(wpa_s->ric_ies);
2096 }
Dmitry Shmidt41712582015-06-29 11:02:15 -07002097 if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
2098 data->auth.ies_len, 0,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002099 data->auth.peer,
2100 ric_ies, ric_ies_len) < 0) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07002101 wpa_dbg(wpa_s, MSG_DEBUG,
2102 "SME: FT Authentication response processing failed");
2103 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2104 MACSTR
2105 " reason=%d locally_generated=1",
2106 MAC2STR(wpa_s->pending_bssid),
2107 WLAN_REASON_DEAUTH_LEAVING);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002108 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2109 NULL);
Dmitry Shmidt41712582015-06-29 11:02:15 -07002110 wpa_supplicant_mark_disassoc(wpa_s);
2111 return;
2112 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002113 }
2114#endif /* CONFIG_IEEE80211R */
2115
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002116#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002117 if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
2118 data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
2119 u16 expect_auth_type;
2120
2121 expect_auth_type = wpa_s->sme.auth_alg ==
2122 WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
2123 WLAN_AUTH_FILS_SK;
2124 if (data->auth.auth_type != expect_auth_type) {
2125 wpa_dbg(wpa_s, MSG_DEBUG,
2126 "SME: FILS Authentication response used different auth alg (%u; expected %u)",
2127 data->auth.auth_type, expect_auth_type);
2128 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2129 MACSTR
2130 " reason=%d locally_generated=1",
2131 MAC2STR(wpa_s->pending_bssid),
2132 WLAN_REASON_DEAUTH_LEAVING);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002133 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2134 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002135 wpa_supplicant_mark_disassoc(wpa_s);
2136 return;
2137 }
2138
2139 if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
2140 data->auth.ies, data->auth.ies_len) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002141 wpa_dbg(wpa_s, MSG_DEBUG,
2142 "SME: FILS Authentication response processing failed");
2143 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2144 MACSTR
2145 " reason=%d locally_generated=1",
2146 MAC2STR(wpa_s->pending_bssid),
2147 WLAN_REASON_DEAUTH_LEAVING);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002148 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2149 NULL);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002150 wpa_supplicant_mark_disassoc(wpa_s);
2151 return;
2152 }
2153 }
2154#endif /* CONFIG_FILS */
2155
Sunil Ravi77d572f2023-01-17 23:58:31 +00002156 /* TODO: Support additional auth_type values as well */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002157 if ((data->auth.auth_type == WLAN_AUTH_OPEN ||
2158 data->auth.auth_type == WLAN_AUTH_SAE) &&
2159 wpas_sme_ml_auth(wpa_s, data, ie_offset) < 0) {
2160 wpa_dbg(wpa_s, MSG_DEBUG,
2161 "MLD: Failed to parse ML Authentication frame");
2162 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
2163 " reason=%d locally_generated=1",
2164 MAC2STR(wpa_s->pending_bssid),
2165 WLAN_REASON_DEAUTH_LEAVING);
2166 wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
2167 wpa_supplicant_mark_disassoc(wpa_s);
2168 return;
2169 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00002170
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002171 sme_associate(wpa_s, ssid->mode, data->auth.peer,
2172 data->auth.auth_type);
2173}
2174
2175
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002176#ifdef CONFIG_IEEE80211R
2177static void remove_ie(u8 *buf, size_t *len, u8 eid)
2178{
2179 u8 *pos, *next, *end;
2180
2181 pos = (u8 *) get_ie(buf, *len, eid);
2182 if (pos) {
2183 next = pos + 2 + pos[1];
2184 end = buf + *len;
2185 *len -= 2 + pos[1];
2186 os_memmove(pos, next, end - next);
2187 }
2188}
2189#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002190
2191
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002192void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
2193 const u8 *bssid, u16 auth_type)
2194{
2195 struct wpa_driver_associate_params params;
2196 struct ieee802_11_elems elems;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002197 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002198#ifdef CONFIG_FILS
2199 u8 nonces[2 * FILS_NONCE_LEN];
2200#endif /* CONFIG_FILS */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002201#ifdef CONFIG_HT_OVERRIDES
2202 struct ieee80211_ht_capabilities htcaps;
2203 struct ieee80211_ht_capabilities htcaps_mask;
2204#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002205#ifdef CONFIG_VHT_OVERRIDES
2206 struct ieee80211_vht_capabilities vhtcaps;
2207 struct ieee80211_vht_capabilities vhtcaps_mask;
2208#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002209
2210 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002211
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002212 /* Save auth type, in case we need to retry after comeback timer. */
2213 wpa_s->sme.assoc_auth_type = auth_type;
2214
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002215#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002216 if (auth_type == WLAN_AUTH_FILS_SK ||
2217 auth_type == WLAN_AUTH_FILS_SK_PFS) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002218 struct wpabuf *buf;
2219 const u8 *snonce, *anonce;
Paul Stewart092955c2017-02-06 09:13:09 -08002220 const unsigned int max_hlp = 20;
2221 struct wpabuf *hlp[max_hlp];
2222 unsigned int i, num_hlp = 0;
2223 struct fils_hlp_req *req;
2224
2225 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2226 list) {
2227 hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
2228 wpabuf_len(req->pkt));
2229 if (!hlp[num_hlp])
2230 break;
2231 wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
2232 wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
2233 ETH_ALEN);
2234 wpabuf_put_data(hlp[num_hlp],
2235 "\xaa\xaa\x03\x00\x00\x00", 6);
2236 wpabuf_put_buf(hlp[num_hlp], req->pkt);
2237 num_hlp++;
2238 if (num_hlp >= max_hlp)
2239 break;
2240 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002241
2242 buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
2243 &params.fils_kek_len, &snonce,
Paul Stewart092955c2017-02-06 09:13:09 -08002244 &anonce,
2245 (const struct wpabuf **) hlp,
2246 num_hlp);
2247 for (i = 0; i < num_hlp; i++)
2248 wpabuf_free(hlp[i]);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002249 if (!buf)
2250 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002251 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req before FILS elements",
2252 wpa_s->sme.assoc_req_ie,
2253 wpa_s->sme.assoc_req_ie_len);
2254#ifdef CONFIG_IEEE80211R
2255 if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
2256 /* Remove RSNE and MDE to allow them to be overridden
2257 * with FILS+FT specific values from
2258 * fils_build_assoc_req(). */
2259 remove_ie(wpa_s->sme.assoc_req_ie,
2260 &wpa_s->sme.assoc_req_ie_len,
2261 WLAN_EID_RSN);
2262 wpa_hexdump(MSG_DEBUG,
2263 "FILS: assoc_req after RSNE removal",
2264 wpa_s->sme.assoc_req_ie,
2265 wpa_s->sme.assoc_req_ie_len);
2266 remove_ie(wpa_s->sme.assoc_req_ie,
2267 &wpa_s->sme.assoc_req_ie_len,
2268 WLAN_EID_MOBILITY_DOMAIN);
2269 wpa_hexdump(MSG_DEBUG,
2270 "FILS: assoc_req after MDE removal",
2271 wpa_s->sme.assoc_req_ie,
2272 wpa_s->sme.assoc_req_ie_len);
2273 }
2274#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002275 /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
2276 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
2277 sizeof(wpa_s->sme.assoc_req_ie)) {
2278 wpa_printf(MSG_ERROR,
2279 "FILS: Not enough buffer room for own AssocReq elements");
2280 wpabuf_free(buf);
2281 return;
2282 }
2283 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2284 wpabuf_head(buf), wpabuf_len(buf));
2285 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
2286 wpabuf_free(buf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002287 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req after FILS elements",
2288 wpa_s->sme.assoc_req_ie,
2289 wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002290
2291 os_memcpy(nonces, snonce, FILS_NONCE_LEN);
2292 os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
2293 params.fils_nonces = nonces;
2294 params.fils_nonces_len = sizeof(nonces);
2295 }
2296#endif /* CONFIG_FILS */
2297
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002298#ifdef CONFIG_OWE
2299#ifdef CONFIG_TESTING_OPTIONS
2300 if (get_ie_ext(wpa_s->sme.assoc_req_ie, wpa_s->sme.assoc_req_ie_len,
2301 WLAN_EID_EXT_OWE_DH_PARAM)) {
2302 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2303 } else
2304#endif /* CONFIG_TESTING_OPTIONS */
2305 if (auth_type == WLAN_AUTH_OPEN &&
2306 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2307 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002308 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002309
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002310 if (ssid && ssid->owe_group) {
2311 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08002312 } else if (wpa_s->assoc_status_code ==
2313 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002314 if (wpa_s->last_owe_group == 19)
2315 group = 20;
2316 else if (wpa_s->last_owe_group == 20)
2317 group = 21;
2318 else
2319 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002320 } else {
2321 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002322 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002323
Roshan Pius3a1667e2018-07-03 15:17:14 -07002324 wpa_s->last_owe_group = group;
2325 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002326 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2327 if (!owe_ie) {
2328 wpa_printf(MSG_ERROR,
2329 "OWE: Failed to build IE for Association Request frame");
2330 return;
2331 }
2332 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(owe_ie) >
2333 sizeof(wpa_s->sme.assoc_req_ie)) {
2334 wpa_printf(MSG_ERROR,
2335 "OWE: Not enough buffer room for own Association Request frame elements");
2336 wpabuf_free(owe_ie);
2337 return;
2338 }
2339 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2340 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2341 wpa_s->sme.assoc_req_ie_len += wpabuf_len(owe_ie);
2342 wpabuf_free(owe_ie);
2343 }
2344#endif /* CONFIG_OWE */
2345
Hai Shalom021b0b52019-04-10 11:17:58 -07002346#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002347 if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid &&
2348 ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 &&
2349 !ssid->dpp_pfs_fallback) {
2350 struct rsn_pmksa_cache_entry *pmksa;
2351
2352 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2353 if (!pmksa || !pmksa->dpp_pfs)
2354 goto pfs_fail;
Hai Shalom021b0b52019-04-10 11:17:58 -07002355
2356 dpp_pfs_free(wpa_s->dpp_pfs);
2357 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
2358 ssid->dpp_netaccesskey_len);
2359 if (!wpa_s->dpp_pfs) {
2360 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
2361 /* Try to continue without PFS */
2362 goto pfs_fail;
2363 }
2364 if (wpa_s->sme.assoc_req_ie_len +
2365 wpabuf_len(wpa_s->dpp_pfs->ie) >
2366 sizeof(wpa_s->sme.assoc_req_ie)) {
2367 wpa_printf(MSG_ERROR,
2368 "DPP: Not enough buffer room for own Association Request frame elements");
2369 dpp_pfs_free(wpa_s->dpp_pfs);
2370 wpa_s->dpp_pfs = NULL;
2371 goto pfs_fail;
2372 }
2373 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2374 wpabuf_head(wpa_s->dpp_pfs->ie),
2375 wpabuf_len(wpa_s->dpp_pfs->ie));
2376 wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
2377 }
2378pfs_fail:
2379#endif /* CONFIG_DPP2 */
2380
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002381#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom899fcc72020-10-19 14:38:18 -07002382 wpa_s->mscs_setup_done = false;
Hai Shalom60840252021-02-19 19:02:11 -08002383 if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
2384 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002385 struct wpabuf *mscs_ie;
2386 size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len;
2387
Hai Shalom899fcc72020-10-19 14:38:18 -07002388 buf_len = 3 + /* MSCS descriptor IE header */
2389 1 + /* Request type */
2390 2 + /* User priority control */
2391 4 + /* Stream timeout */
2392 3 + /* TCLAS Mask IE header */
2393 wpa_s->robust_av.frame_classifier_len;
2394 mscs_ie = wpabuf_alloc(buf_len);
2395 if (!mscs_ie) {
2396 wpa_printf(MSG_INFO,
2397 "MSCS: Failed to allocate MSCS IE");
2398 goto mscs_fail;
2399 }
2400
2401 wpa_ie_len = &wpa_s->sme.assoc_req_ie_len;
2402 max_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
2403 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
2404 if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) {
2405 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
2406 mscs_ie_len = wpabuf_len(mscs_ie);
2407 os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len,
2408 wpabuf_head(mscs_ie), mscs_ie_len);
2409 *wpa_ie_len += mscs_ie_len;
2410 }
2411
2412 wpabuf_free(mscs_ie);
2413 }
2414mscs_fail:
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002415#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -07002416
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002417 if (ssid && ssid->multi_ap_backhaul_sta) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002418 size_t multi_ap_ie_len;
2419
2420 multi_ap_ie_len = add_multi_ap_ie(
2421 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2422 sizeof(wpa_s->sme.assoc_req_ie) -
2423 wpa_s->sme.assoc_req_ie_len,
Sunil Ravi88611412024-06-28 17:34:56 +00002424 MULTI_AP_BACKHAUL_STA);
Hai Shalom74f70d42019-02-11 14:42:39 -08002425 if (multi_ap_ie_len == 0) {
2426 wpa_printf(MSG_ERROR,
2427 "Multi-AP: Failed to build Multi-AP IE");
2428 return;
2429 }
2430 wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
2431 }
2432
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 params.bssid = bssid;
2434 params.ssid = wpa_s->sme.ssid;
2435 params.ssid_len = wpa_s->sme.ssid_len;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002436 params.freq.freq = wpa_s->sme.freq;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002437 params.bg_scan_period = ssid ? ssid->bg_scan_period : -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
2439 wpa_s->sme.assoc_req_ie : NULL;
2440 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08002441 wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
2442 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002443 params.pairwise_suite = wpa_s->pairwise_cipher;
2444 params.group_suite = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002445 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
Dmitry Shmidt15907092014-03-25 10:42:57 -07002446 params.key_mgmt_suite = wpa_s->key_mgmt;
2447 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002448#ifdef CONFIG_HT_OVERRIDES
2449 os_memset(&htcaps, 0, sizeof(htcaps));
2450 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2451 params.htcaps = (u8 *) &htcaps;
2452 params.htcaps_mask = (u8 *) &htcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002453 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002454#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002455#ifdef CONFIG_VHT_OVERRIDES
2456 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2457 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2458 params.vhtcaps = &vhtcaps;
2459 params.vhtcaps_mask = &vhtcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002460 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002461#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07002462#ifdef CONFIG_HE_OVERRIDES
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002463 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
Hai Shalomfdcde762020-04-02 11:19:20 -07002464#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00002465 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002466#ifdef CONFIG_IEEE80211R
Hai Shalom74f70d42019-02-11 14:42:39 -08002467 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
2468 get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
2469 WLAN_EID_RIC_DATA)) {
2470 /* There seems to be a pretty inconvenient bug in the Linux
2471 * kernel IE splitting functionality when RIC is used. For now,
2472 * skip correct behavior in IE construction here (i.e., drop the
2473 * additional non-FT-specific IEs) to avoid kernel issues. This
2474 * is fine since RIC is used only for testing purposes in the
2475 * current implementation. */
2476 wpa_printf(MSG_INFO,
2477 "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478 params.wpa_ie = wpa_s->sme.ft_ies;
2479 params.wpa_ie_len = wpa_s->sme.ft_ies_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08002480 } else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
2481 const u8 *rm_en, *pos, *end;
2482 size_t rm_en_len = 0;
2483 u8 *rm_en_dup = NULL, *wpos;
2484
2485 /* Remove RSNE, MDE, FTE to allow them to be overridden with
2486 * FT specific values */
2487 remove_ie(wpa_s->sme.assoc_req_ie,
2488 &wpa_s->sme.assoc_req_ie_len,
2489 WLAN_EID_RSN);
2490 remove_ie(wpa_s->sme.assoc_req_ie,
2491 &wpa_s->sme.assoc_req_ie_len,
2492 WLAN_EID_MOBILITY_DOMAIN);
2493 remove_ie(wpa_s->sme.assoc_req_ie,
2494 &wpa_s->sme.assoc_req_ie_len,
2495 WLAN_EID_FAST_BSS_TRANSITION);
2496 rm_en = get_ie(wpa_s->sme.assoc_req_ie,
2497 wpa_s->sme.assoc_req_ie_len,
2498 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2499 if (rm_en) {
2500 /* Need to remove RM Enabled Capabilities element as
2501 * well temporarily, so that it can be placed between
2502 * RSNE and MDE. */
2503 rm_en_len = 2 + rm_en[1];
2504 rm_en_dup = os_memdup(rm_en, rm_en_len);
2505 remove_ie(wpa_s->sme.assoc_req_ie,
2506 &wpa_s->sme.assoc_req_ie_len,
2507 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2508 }
2509 wpa_hexdump(MSG_DEBUG,
2510 "SME: Association Request IEs after FT IE removal",
2511 wpa_s->sme.assoc_req_ie,
2512 wpa_s->sme.assoc_req_ie_len);
2513 if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
2514 rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
2515 wpa_printf(MSG_ERROR,
2516 "SME: Not enough buffer room for FT IEs in Association Request frame");
2517 os_free(rm_en_dup);
2518 return;
2519 }
2520
2521 os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
2522 rm_en_len,
2523 wpa_s->sme.assoc_req_ie,
2524 wpa_s->sme.assoc_req_ie_len);
2525 pos = wpa_s->sme.ft_ies;
2526 end = pos + wpa_s->sme.ft_ies_len;
2527 wpos = wpa_s->sme.assoc_req_ie;
2528 if (*pos == WLAN_EID_RSN) {
2529 os_memcpy(wpos, pos, 2 + pos[1]);
2530 wpos += 2 + pos[1];
2531 pos += 2 + pos[1];
2532 }
2533 if (rm_en_dup) {
2534 os_memcpy(wpos, rm_en_dup, rm_en_len);
2535 wpos += rm_en_len;
2536 os_free(rm_en_dup);
2537 }
2538 os_memcpy(wpos, pos, end - pos);
2539 wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
2540 rm_en_len;
2541 params.wpa_ie = wpa_s->sme.assoc_req_ie;
2542 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
2543 wpa_hexdump(MSG_DEBUG,
2544 "SME: Association Request IEs after FT override",
2545 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002546 }
2547#endif /* CONFIG_IEEE80211R */
2548 params.mode = mode;
2549 params.mgmt_frame_protection = wpa_s->sme.mfp;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002550 params.rrm_used = wpa_s->rrm.rrm_used;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 if (wpa_s->sme.prev_bssid_set)
2552 params.prev_bssid = wpa_s->sme.prev_bssid;
2553
2554 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2555 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
2556 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002557 params.freq.freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558
2559 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2560
2561 if (params.wpa_ie == NULL ||
2562 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
2563 < 0) {
2564 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
2565 os_memset(&elems, 0, sizeof(elems));
2566 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002567 if (elems.rsn_ie) {
2568 params.wpa_proto = WPA_PROTO_RSN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
2570 elems.rsn_ie_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002571 } else if (elems.wpa_ie) {
2572 params.wpa_proto = WPA_PROTO_WPA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
2574 elems.wpa_ie_len + 2);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002575 } else if (elems.osen) {
2576 params.wpa_proto = WPA_PROTO_OSEN;
2577 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
2578 elems.osen_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002579 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002580 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07002581 if (elems.rsnxe)
2582 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, elems.rsnxe - 2,
2583 elems.rsnxe_len + 2);
2584 else
2585 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002586 if (ssid && ssid->p2p_group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 params.p2p = 1;
2588
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002589 if (wpa_s->p2pdev->set_sta_uapsd)
2590 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 else
2592 params.uapsd = -1;
2593
Sunil Ravi77d572f2023-01-17 23:58:31 +00002594 if (wpa_s->valid_links) {
2595 unsigned int i;
2596
2597 wpa_printf(MSG_DEBUG,
2598 "MLD: In association. assoc_link_id=%u, valid_links=0x%x",
2599 wpa_s->mlo_assoc_link_id, wpa_s->valid_links);
2600
2601 params.mld_params.mld_addr = wpa_s->ap_mld_addr;
2602 params.mld_params.valid_links = wpa_s->valid_links;
2603 params.mld_params.assoc_link_id = wpa_s->mlo_assoc_link_id;
Sunil Ravi88611412024-06-28 17:34:56 +00002604 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
2605 if (!(wpa_s->valid_links & BIT(i)))
2606 continue;
2607
Sunil Ravi77d572f2023-01-17 23:58:31 +00002608 params.mld_params.mld_links[i].bssid =
2609 wpa_s->links[i].bssid;
2610 params.mld_params.mld_links[i].freq =
2611 wpa_s->links[i].freq;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002612 params.mld_params.mld_links[i].disabled =
2613 wpa_s->links[i].disabled;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002614
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002615 wpa_printf(MSG_DEBUG,
2616 "MLD: id=%u, freq=%d, disabled=%u, " MACSTR,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002617 i, wpa_s->links[i].freq,
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002618 wpa_s->links[i].disabled,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002619 MAC2STR(wpa_s->links[i].bssid));
2620 }
2621 }
2622
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002623 if (wpa_drv_associate(wpa_s, &params) < 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002624 unsigned int n_failed_links = 0;
2625 int i;
2626
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002627 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
2628 "driver failed");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002629
2630 /* Prepare list of failed links for error report */
2631 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
2632 if (!(wpa_s->valid_links & BIT(i)) ||
2633 wpa_s->mlo_assoc_link_id == i ||
2634 !params.mld_params.mld_links[i].error)
2635 continue;
2636
2637 wpa_bssid_ignore_add(wpa_s, wpa_s->links[i].bssid);
2638 n_failed_links++;
2639 }
2640
2641 if (n_failed_links) {
2642 /* Deauth and connect (possibly to the same AP MLD) */
2643 wpa_drv_deauthenticate(wpa_s, wpa_s->ap_mld_addr,
2644 WLAN_REASON_DEAUTH_LEAVING);
2645 wpas_connect_work_done(wpa_s);
2646 wpa_supplicant_mark_disassoc(wpa_s);
2647 wpas_request_connection(wpa_s);
2648 } else {
2649 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2650 NULL);
2651 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2652 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2653 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 return;
2655 }
2656
2657 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
2658 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002659
2660#ifdef CONFIG_TESTING_OPTIONS
2661 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
2662 wpa_s->last_assoc_req_wpa_ie = NULL;
2663 if (params.wpa_ie)
2664 wpa_s->last_assoc_req_wpa_ie =
2665 wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len);
2666#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667}
2668
2669
2670int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
2671 const u8 *ies, size_t ies_len)
2672{
2673 if (md == NULL || ies == NULL) {
2674 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
2675 os_free(wpa_s->sme.ft_ies);
2676 wpa_s->sme.ft_ies = NULL;
2677 wpa_s->sme.ft_ies_len = 0;
2678 wpa_s->sme.ft_used = 0;
2679 return 0;
2680 }
2681
2682 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
2683 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
2684 os_free(wpa_s->sme.ft_ies);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002685 wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002686 if (wpa_s->sme.ft_ies == NULL)
2687 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002688 wpa_s->sme.ft_ies_len = ies_len;
2689 return 0;
2690}
2691
2692
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002693static void sme_deauth(struct wpa_supplicant *wpa_s, const u8 **link_bssids)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002694{
2695 int bssid_changed;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002696 const u8 *bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002697
2698 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2699
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002700 if (wpa_s->valid_links)
2701 bssid = wpa_s->ap_mld_addr;
2702 else
2703 bssid = wpa_s->pending_bssid;
2704
2705 if (wpa_drv_deauthenticate(wpa_s, bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002706 WLAN_REASON_DEAUTH_LEAVING) < 0) {
2707 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
2708 "failed");
2709 }
2710 wpa_s->sme.prev_bssid_set = 0;
2711
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002712 wpas_connection_failed(wpa_s, wpa_s->pending_bssid, link_bssids);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2714 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2715 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2716 if (bssid_changed)
2717 wpas_notify_bssid_changed(wpa_s);
2718}
2719
2720
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002721static void sme_assoc_comeback_timer(void *eloop_ctx, void *timeout_ctx)
Sunil Ravi72e01222024-03-09 01:25:43 +00002722{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002723 struct wpa_supplicant *wpa_s = eloop_ctx;
2724
2725 if (!wpa_s->current_bss || !wpa_s->current_ssid) {
2726 wpa_msg(wpa_s, MSG_DEBUG,
2727 "SME: Comeback timeout expired; SSID/BSSID cleared; ignoring");
2728 return;
2729 }
2730
2731 wpa_msg(wpa_s, MSG_DEBUG,
2732 "SME: Comeback timeout expired; retry associating with "
2733 MACSTR "; mode=%d auth_type=%u",
2734 MAC2STR(wpa_s->current_bss->bssid),
2735 wpa_s->current_ssid->mode,
2736 wpa_s->sme.assoc_auth_type);
2737
2738 /* Authentication state was completed already; just try association
2739 * again. */
2740 sme_associate(wpa_s, wpa_s->current_ssid->mode,
2741 wpa_s->current_bss->bssid,
2742 wpa_s->sme.assoc_auth_type);
2743}
2744
2745
2746static bool sme_try_assoc_comeback(struct wpa_supplicant *wpa_s,
2747 union wpa_event_data *data)
2748{
2749 struct ieee802_11_elems elems;
2750 u32 timeout_interval;
2751 unsigned long comeback_usec;
2752 u8 type = WLAN_TIMEOUT_ASSOC_COMEBACK;
2753
2754#ifdef CONFIG_TESTING_OPTIONS
2755 if (wpa_s->test_assoc_comeback_type != -1)
2756 type = wpa_s->test_assoc_comeback_type;
2757#endif /* CONFIG_TESTING_OPTIONS */
2758
2759 if (ieee802_11_parse_elems(data->assoc_reject.resp_ies,
2760 data->assoc_reject.resp_ies_len,
2761 &elems, 0) == ParseFailed) {
2762 wpa_msg(wpa_s, MSG_INFO,
2763 "SME: Temporary assoc reject: failed to parse (Re)Association Response frame elements");
2764 return false;
2765 }
2766
2767 if (!elems.timeout_int) {
2768 wpa_msg(wpa_s, MSG_INFO,
2769 "SME: Temporary assoc reject: missing timeout interval IE");
2770 return false;
2771 }
2772
2773 if (elems.timeout_int[0] != type) {
2774 wpa_msg(wpa_s, MSG_INFO,
2775 "SME: Temporary assoc reject: missing association comeback time");
2776 return false;
2777 }
2778
2779 timeout_interval = WPA_GET_LE32(&elems.timeout_int[1]);
2780 if (timeout_interval > 60000) {
2781 /* This is unprotected information and there is no point in
2782 * getting stuck waiting for very long duration based on it */
2783 wpa_msg(wpa_s, MSG_DEBUG,
2784 "SME: Ignore overly long association comeback interval: %u TUs",
2785 timeout_interval);
2786 return false;
2787 }
2788 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association comeback interval: %u TUs",
2789 timeout_interval);
2790
2791 comeback_usec = timeout_interval * 1024;
2792 eloop_register_timeout(comeback_usec / 1000000, comeback_usec % 1000000,
2793 sme_assoc_comeback_timer, wpa_s, NULL);
2794 return true;
2795}
2796
2797
2798void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
2799 union wpa_event_data *data,
2800 const u8 **link_bssids)
2801{
2802 const u8 *bssid;
2803
2804 if (wpa_s->valid_links)
2805 bssid = wpa_s->ap_mld_addr;
2806 else
2807 bssid = wpa_s->pending_bssid;
2808
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002809 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
2810 "status code %d", MAC2STR(wpa_s->pending_bssid),
2811 data->assoc_reject.status_code);
2812
2813 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002814 eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
2815
2816 /* Authentication phase has been completed at this point. Check whether
2817 * the AP rejected association temporarily due to still holding a
2818 * security associationis with us (MFP). If so, we must wait for the
2819 * AP's association comeback timeout period before associating again. */
2820 if (data->assoc_reject.status_code ==
2821 WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
2822 wpa_msg(wpa_s, MSG_DEBUG,
2823 "SME: Temporary association reject from BSS " MACSTR,
2824 MAC2STR(bssid));
2825 if (sme_try_assoc_comeback(wpa_s, data)) {
2826 /* Break out early; comeback error is not a failure. */
2827 return;
2828 }
2829 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002830
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002831#ifdef CONFIG_SAE
2832 if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
2833 wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
2834 wpa_dbg(wpa_s, MSG_DEBUG,
2835 "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
2836 wpa_sm_aborted_cached(wpa_s->wpa);
2837 wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
2838 if (wpa_s->current_bss) {
2839 struct wpa_bss *bss = wpa_s->current_bss;
2840 struct wpa_ssid *ssid = wpa_s->current_ssid;
2841
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002842 wpa_drv_deauthenticate(wpa_s, bssid,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002843 WLAN_REASON_DEAUTH_LEAVING);
2844 wpas_connect_work_done(wpa_s);
2845 wpa_supplicant_mark_disassoc(wpa_s);
2846 wpa_supplicant_connect(wpa_s, bss, ssid);
2847 return;
2848 }
2849 }
2850#endif /* CONFIG_SAE */
2851
Sunil Ravi77d572f2023-01-17 23:58:31 +00002852#ifdef CONFIG_DPP
2853 if (wpa_s->current_ssid &&
2854 wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
2855 !data->assoc_reject.timed_out &&
2856 data->assoc_reject.status_code == WLAN_STATUS_INVALID_PMKID) {
2857 struct rsn_pmksa_cache_entry *pmksa;
2858
2859 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2860 if (pmksa) {
2861 wpa_dbg(wpa_s, MSG_DEBUG,
2862 "DPP: Drop PMKSA cache entry for the BSS due to invalid PMKID report");
2863 wpa_sm_pmksa_cache_remove(wpa_s->wpa, pmksa);
2864 }
2865 wpa_sm_aborted_cached(wpa_s->wpa);
2866 if (wpa_s->current_bss) {
2867 struct wpa_bss *bss = wpa_s->current_bss;
2868 struct wpa_ssid *ssid = wpa_s->current_ssid;
2869
2870 wpa_dbg(wpa_s, MSG_DEBUG,
2871 "DPP: Try network introduction again");
2872 wpas_connect_work_done(wpa_s);
2873 wpa_supplicant_mark_disassoc(wpa_s);
2874 wpa_supplicant_connect(wpa_s, bss, ssid);
2875 return;
2876 }
2877 }
2878#endif /* CONFIG_DPP */
2879
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002880 /*
2881 * For now, unconditionally terminate the previous authentication. In
2882 * theory, this should not be needed, but mac80211 gets quite confused
2883 * if the authentication is left pending.. Some roaming cases might
2884 * benefit from using the previous authentication, so this could be
2885 * optimized in the future.
2886 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002887 sme_deauth(wpa_s, link_bssids);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002888}
2889
2890
2891void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
2892 union wpa_event_data *data)
2893{
2894 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002895 wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002896 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002897}
2898
2899
2900void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
2901 union wpa_event_data *data)
2902{
2903 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002904 wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002905 wpa_supplicant_mark_disassoc(wpa_s);
2906}
2907
2908
2909void sme_event_disassoc(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002910 struct disassoc_info *info)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002911{
2912 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002913 if (wpa_s->sme.prev_bssid_set) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002914 /*
2915 * cfg80211/mac80211 can get into somewhat confused state if
2916 * the AP only disassociates us and leaves us in authenticated
2917 * state. For now, force the state to be cleared to avoid
2918 * confusing errors if we try to associate with the AP again.
2919 */
2920 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
2921 "driver state");
2922 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
2923 WLAN_REASON_DEAUTH_LEAVING);
2924 }
2925}
2926
2927
2928static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
2929{
2930 struct wpa_supplicant *wpa_s = eloop_ctx;
2931 if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
2932 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002933 sme_deauth(wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002934 }
2935}
2936
2937
2938static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
2939{
2940 struct wpa_supplicant *wpa_s = eloop_ctx;
2941 if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2942 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002943 sme_deauth(wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002944 }
2945}
2946
2947
2948void sme_state_changed(struct wpa_supplicant *wpa_s)
2949{
2950 /* Make sure timers are cleaned up appropriately. */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002951 if (wpa_s->wpa_state != WPA_ASSOCIATING) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002952 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002953 eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
2954 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002955 if (wpa_s->wpa_state != WPA_AUTHENTICATING)
2956 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2957}
2958
2959
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002960void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
2961{
2962 wpa_s->sme.prev_bssid_set = 0;
2963#ifdef CONFIG_SAE
2964 wpabuf_free(wpa_s->sme.sae_token);
2965 wpa_s->sme.sae_token = NULL;
2966 sae_clear_data(&wpa_s->sme.sae);
2967#endif /* CONFIG_SAE */
2968#ifdef CONFIG_IEEE80211R
Roshan Pius3a1667e2018-07-03 15:17:14 -07002969 if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002970 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
2971#endif /* CONFIG_IEEE80211R */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002972 sme_stop_sa_query(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002973}
2974
2975
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002976void sme_deinit(struct wpa_supplicant *wpa_s)
2977{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002978 sme_clear_on_disassoc(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002979#ifdef CONFIG_SAE
2980 os_free(wpa_s->sme.sae_rejected_groups);
2981 wpa_s->sme.sae_rejected_groups = NULL;
2982#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002983
2984 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2985 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002986 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002987 eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002988}
2989
2990
2991static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
2992 const u8 *chan_list, u8 num_channels,
2993 u8 num_intol)
2994{
2995 struct ieee80211_2040_bss_coex_ie *bc_ie;
2996 struct ieee80211_2040_intol_chan_report *ic_report;
2997 struct wpabuf *buf;
2998
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002999 wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
3000 " (num_channels=%u num_intol=%u)",
3001 MAC2STR(wpa_s->bssid), num_channels, num_intol);
3002 wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
3003 chan_list, num_channels);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003004
3005 buf = wpabuf_alloc(2 + /* action.category + action_code */
3006 sizeof(struct ieee80211_2040_bss_coex_ie) +
3007 sizeof(struct ieee80211_2040_intol_chan_report) +
3008 num_channels);
3009 if (buf == NULL)
3010 return;
3011
3012 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
3013 wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
3014
3015 bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
3016 bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
3017 bc_ie->length = 1;
3018 if (num_intol)
3019 bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
3020
3021 if (num_channels > 0) {
3022 ic_report = wpabuf_put(buf, sizeof(*ic_report));
3023 ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
3024 ic_report->length = num_channels + 1;
3025 ic_report->op_class = 0;
3026 os_memcpy(wpabuf_put(buf, num_channels), chan_list,
3027 num_channels);
3028 }
3029
3030 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3031 wpa_s->own_addr, wpa_s->bssid,
3032 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
3033 wpa_msg(wpa_s, MSG_INFO,
3034 "SME: Failed to send 20/40 BSS Coexistence frame");
3035 }
3036
3037 wpabuf_free(buf);
3038}
3039
3040
Hai Shaloma20dcd72022-02-04 13:43:00 -08003041int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003042{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003043 struct wpa_bss *bss;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003044 const u8 *ie;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003045 u16 ht_cap;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003046 u8 chan_list[P2P_MAX_CHANNELS], channel;
3047 u8 num_channels = 0, num_intol = 0, i;
3048
3049 if (!wpa_s->sme.sched_obss_scan)
3050 return 0;
3051
3052 wpa_s->sme.sched_obss_scan = 0;
3053 if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
3054 return 1;
3055
3056 /*
3057 * Check whether AP uses regulatory triplet or channel triplet in
3058 * country info. Right now the operating class of the BSS channel
3059 * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
3060 * based on the assumption that operating class triplet is not used in
3061 * beacon frame. If the First Channel Number/Operating Extension
3062 * Identifier octet has a positive integer value of 201 or greater,
3063 * then its operating class triplet.
3064 *
3065 * TODO: If Supported Operating Classes element is present in beacon
3066 * frame, have to lookup operating class in Annex E and fill them in
3067 * 2040 coex frame.
3068 */
3069 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
3070 if (ie && (ie[1] >= 6) && (ie[5] >= 201))
3071 return 1;
3072
3073 os_memset(chan_list, 0, sizeof(chan_list));
3074
Hai Shaloma20dcd72022-02-04 13:43:00 -08003075 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003076 /* Skip other band bss */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003077 enum hostapd_hw_mode mode;
Dmitry Shmidt4b060592013-04-29 16:42:49 -07003078 mode = ieee80211_freq_to_chan(bss->freq, &channel);
3079 if (mode != HOSTAPD_MODE_IEEE80211G &&
3080 mode != HOSTAPD_MODE_IEEE80211B)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003081 continue;
3082
Hai Shaloma20dcd72022-02-04 13:43:00 -08003083 ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
3084 ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
3085 wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
3086 " freq=%u chan=%u ht_cap=0x%x",
3087 MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
3088
3089 if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
3090 if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003091 num_intol++;
3092
Dmitry Shmidt04949592012-07-19 12:16:46 -07003093 /* Check whether the channel is already considered */
3094 for (i = 0; i < num_channels; i++) {
3095 if (channel == chan_list[i])
3096 break;
3097 }
3098 if (i != num_channels)
3099 continue;
3100
Dmitry Shmidt04949592012-07-19 12:16:46 -07003101 chan_list[num_channels++] = channel;
3102 }
3103 }
3104
3105 sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
3106 return 1;
3107}
3108
3109
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003110static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
3111 struct wpa_driver_scan_params *params)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003112{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003113 /* Include only affected channels */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003114 struct hostapd_hw_modes *mode;
3115 int count, i;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003116 int start, end;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003117
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003118 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08003119 HOSTAPD_MODE_IEEE80211G, false);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003120 if (mode == NULL) {
3121 /* No channels supported in this band - use empty list */
3122 params->freqs = os_zalloc(sizeof(int));
3123 return;
3124 }
3125
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003126 if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
3127 wpa_s->current_bss) {
3128 const u8 *ie;
3129
3130 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
3131 if (ie && ie[1] >= 2) {
3132 u8 o;
3133
3134 o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
3135 if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
3136 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
3137 else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
3138 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
3139 }
3140 }
3141
3142 start = wpa_s->assoc_freq - 10;
3143 end = wpa_s->assoc_freq + 10;
3144 switch (wpa_s->sme.ht_sec_chan) {
3145 case HT_SEC_CHAN_UNKNOWN:
3146 /* HT40+ possible on channels 1..9 */
3147 if (wpa_s->assoc_freq <= 2452)
3148 start -= 20;
3149 /* HT40- possible on channels 5-13 */
3150 if (wpa_s->assoc_freq >= 2432)
3151 end += 20;
3152 break;
3153 case HT_SEC_CHAN_ABOVE:
3154 end += 20;
3155 break;
3156 case HT_SEC_CHAN_BELOW:
3157 start -= 20;
3158 break;
3159 }
3160 wpa_printf(MSG_DEBUG,
3161 "OBSS: assoc_freq %d possible affected range %d-%d",
3162 wpa_s->assoc_freq, start, end);
3163
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003164 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
Dmitry Shmidt04949592012-07-19 12:16:46 -07003165 if (params->freqs == NULL)
3166 return;
3167 for (count = 0, i = 0; i < mode->num_channels; i++) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003168 int freq;
3169
Dmitry Shmidt04949592012-07-19 12:16:46 -07003170 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
3171 continue;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003172 freq = mode->channels[i].freq;
3173 if (freq - 10 >= end || freq + 10 <= start)
3174 continue; /* not affected */
3175 params->freqs[count++] = freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003176 }
3177}
3178
3179
3180static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
3181{
3182 struct wpa_supplicant *wpa_s = eloop_ctx;
3183 struct wpa_driver_scan_params params;
3184
3185 if (!wpa_s->current_bss) {
3186 wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
3187 return;
3188 }
3189
3190 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003191 wpa_obss_scan_freqs_list(wpa_s, &params);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003192 params.low_priority = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003193 wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
3194
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003195 if (wpa_supplicant_trigger_scan(wpa_s, &params, true, false))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003196 wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
3197 else
3198 wpa_s->sme.sched_obss_scan = 1;
3199 os_free(params.freqs);
3200
3201 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3202 sme_obss_scan_timeout, wpa_s, NULL);
3203}
3204
3205
3206void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
3207{
3208 const u8 *ie;
3209 struct wpa_bss *bss = wpa_s->current_bss;
3210 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003211 struct hostapd_hw_modes *hw_mode = NULL;
3212 int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003213
3214 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
3215 wpa_s->sme.sched_obss_scan = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003216 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003217 if (!enable)
3218 return;
3219
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003220 /*
3221 * Schedule OBSS scan if driver is using station SME in wpa_supplicant
3222 * or it expects OBSS scan to be performed by wpa_supplicant.
3223 */
3224 if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
3225 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
Hai Shalom81f62d82019-07-22 12:10:00 -07003226 ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003227 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003228
Hai Shaloma20dcd72022-02-04 13:43:00 -08003229#ifdef CONFIG_HT_OVERRIDES
3230 /* No need for OBSS scan if HT40 is explicitly disabled */
3231 if (ssid->disable_ht40)
3232 return;
3233#endif /* CONFIG_HT_OVERRIDES */
3234
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003235 if (!wpa_s->hw.modes)
3236 return;
3237
3238 /* only HT caps in 11g mode are relevant */
3239 for (i = 0; i < wpa_s->hw.num_modes; i++) {
3240 hw_mode = &wpa_s->hw.modes[i];
3241 if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
3242 break;
3243 }
3244
3245 /* Driver does not support HT40 for 11g or doesn't have 11g. */
3246 if (i == wpa_s->hw.num_modes || !hw_mode ||
3247 !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3248 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003249
3250 if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
3251 return; /* Not associated on 2.4 GHz band */
3252
3253 /* Check whether AP supports HT40 */
3254 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
3255 if (!ie || ie[1] < 2 ||
3256 !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3257 return; /* AP does not support HT40 */
3258
3259 ie = wpa_bss_get_ie(wpa_s->current_bss,
3260 WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
3261 if (!ie || ie[1] < 14)
3262 return; /* AP does not request OBSS scans */
3263
3264 wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
3265 if (wpa_s->sme.obss_scan_int < 10) {
3266 wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
3267 "replaced with the minimum 10 sec",
3268 wpa_s->sme.obss_scan_int);
3269 wpa_s->sme.obss_scan_int = 10;
3270 }
3271 wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
3272 wpa_s->sme.obss_scan_int);
3273 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3274 sme_obss_scan_timeout, wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003275}
3276
3277
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003278static const unsigned int sa_query_max_timeout = 1000;
3279static const unsigned int sa_query_retry_timeout = 201;
Hai Shalom74f70d42019-02-11 14:42:39 -08003280static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003281
3282static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
3283{
3284 u32 tu;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003285 struct os_reltime now, passed;
3286 os_get_reltime(&now);
3287 os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003288 tu = (passed.sec * 1000000 + passed.usec) / 1024;
3289 if (sa_query_max_timeout < tu) {
3290 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
3291 sme_stop_sa_query(wpa_s);
3292 wpa_supplicant_deauthenticate(
3293 wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
3294 return 1;
3295 }
3296
3297 return 0;
3298}
3299
3300
3301static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
3302 const u8 *trans_id)
3303{
Hai Shalom74f70d42019-02-11 14:42:39 -08003304 u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3305 u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3306
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003307 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
3308 MACSTR, MAC2STR(wpa_s->bssid));
3309 wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
3310 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
3311 req[0] = WLAN_ACTION_SA_QUERY;
3312 req[1] = WLAN_SA_QUERY_REQUEST;
3313 os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08003314
3315#ifdef CONFIG_OCV
3316 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3317 struct wpa_channel_info ci;
3318
3319 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3320 wpa_printf(MSG_WARNING,
3321 "Failed to get channel info for OCI element in SA Query Request frame");
3322 return;
3323 }
3324
Hai Shalom899fcc72020-10-19 14:38:18 -07003325#ifdef CONFIG_TESTING_OPTIONS
3326 if (wpa_s->oci_freq_override_saquery_req) {
3327 wpa_printf(MSG_INFO,
3328 "TEST: Override SA Query Request OCI frequency %d -> %d MHz",
3329 ci.frequency,
3330 wpa_s->oci_freq_override_saquery_req);
3331 ci.frequency = wpa_s->oci_freq_override_saquery_req;
3332 }
3333#endif /* CONFIG_TESTING_OPTIONS */
3334
Hai Shalom74f70d42019-02-11 14:42:39 -08003335 if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
3336 return;
3337
3338 req_len += OCV_OCI_EXTENDED_LEN;
3339 }
3340#endif /* CONFIG_OCV */
3341
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3343 wpa_s->own_addr, wpa_s->bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08003344 req, req_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003345 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
3346 "Request");
3347}
3348
3349
3350static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
3351{
3352 struct wpa_supplicant *wpa_s = eloop_ctx;
3353 unsigned int timeout, sec, usec;
3354 u8 *trans_id, *nbuf;
3355
3356 if (wpa_s->sme.sa_query_count > 0 &&
3357 sme_check_sa_query_timeout(wpa_s))
3358 return;
3359
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003360 nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
3361 wpa_s->sme.sa_query_count + 1,
3362 WLAN_SA_QUERY_TR_ID_LEN);
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003363 if (nbuf == NULL) {
3364 sme_stop_sa_query(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003365 return;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003366 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003367 if (wpa_s->sme.sa_query_count == 0) {
3368 /* Starting a new SA Query procedure */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003369 os_get_reltime(&wpa_s->sme.sa_query_start);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003370 }
3371 trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
3372 wpa_s->sme.sa_query_trans_id = nbuf;
3373 wpa_s->sme.sa_query_count++;
3374
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003375 if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
3376 wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003377 sme_stop_sa_query(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003378 return;
3379 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003380
3381 timeout = sa_query_retry_timeout;
3382 sec = ((timeout / 1000) * 1024) / 1000;
3383 usec = (timeout % 1000) * 1024;
3384 eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
3385
3386 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
3387 wpa_s->sme.sa_query_count);
3388
3389 sme_send_sa_query_req(wpa_s, trans_id);
3390}
3391
3392
3393static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
3394{
3395 sme_sa_query_timer(wpa_s, NULL);
3396}
3397
3398
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003399static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003400{
Hai Shalom5f92bc92019-04-18 11:54:11 -07003401 if (wpa_s->sme.sa_query_trans_id)
3402 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003403 eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
3404 os_free(wpa_s->sme.sa_query_trans_id);
3405 wpa_s->sme.sa_query_trans_id = NULL;
3406 wpa_s->sme.sa_query_count = 0;
3407}
3408
3409
3410void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
3411 const u8 *da, u16 reason_code)
3412{
3413 struct wpa_ssid *ssid;
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003414 struct os_reltime now;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003415
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003416 if (wpa_s->wpa_state != WPA_COMPLETED)
3417 return;
3418 ssid = wpa_s->current_ssid;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003419 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003420 return;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003421 if (!ether_addr_equal(sa, wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003422 return;
3423 if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
3424 reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
3425 return;
3426 if (wpa_s->sme.sa_query_count > 0)
3427 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07003428#ifdef CONFIG_TESTING_OPTIONS
3429 if (wpa_s->disable_sa_query)
3430 return;
3431#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003432
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003433 os_get_reltime(&now);
3434 if (wpa_s->sme.last_unprot_disconnect.sec &&
3435 !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
3436 return; /* limit SA Query procedure frequency */
3437 wpa_s->sme.last_unprot_disconnect = now;
3438
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003439 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
3440 "possible AP/STA state mismatch - trigger SA Query");
3441 sme_start_sa_query(wpa_s);
3442}
3443
3444
Hai Shalom74f70d42019-02-11 14:42:39 -08003445void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
3446{
3447 unsigned int usec;
3448 u32 _rand;
3449
3450 if (wpa_s->wpa_state != WPA_COMPLETED ||
3451 !wpa_sm_ocv_enabled(wpa_s->wpa))
3452 return;
3453
3454 wpa_dbg(wpa_s, MSG_DEBUG,
3455 "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
3456 sme_stop_sa_query(wpa_s);
3457
3458 if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
3459 _rand = os_random();
3460 usec = _rand % (sa_query_ch_switch_max_delay + 1);
3461 eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
3462}
3463
3464
3465static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
3466 const u8 *sa, const u8 *data,
3467 size_t len)
3468{
3469 u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3470 u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3471
3472 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
3473 MACSTR, MAC2STR(wpa_s->bssid));
3474
3475 resp[0] = WLAN_ACTION_SA_QUERY;
3476 resp[1] = WLAN_SA_QUERY_RESPONSE;
3477 os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
3478
3479#ifdef CONFIG_OCV
3480 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3481 struct wpa_channel_info ci;
3482
3483 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3484 wpa_printf(MSG_WARNING,
3485 "Failed to get channel info for OCI element in SA Query Response frame");
3486 return;
3487 }
3488
Hai Shalom899fcc72020-10-19 14:38:18 -07003489#ifdef CONFIG_TESTING_OPTIONS
3490 if (wpa_s->oci_freq_override_saquery_resp) {
3491 wpa_printf(MSG_INFO,
3492 "TEST: Override SA Query Response OCI frequency %d -> %d MHz",
3493 ci.frequency,
3494 wpa_s->oci_freq_override_saquery_resp);
3495 ci.frequency = wpa_s->oci_freq_override_saquery_resp;
3496 }
3497#endif /* CONFIG_TESTING_OPTIONS */
3498
Hai Shalom74f70d42019-02-11 14:42:39 -08003499 if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
3500 return;
3501
3502 resp_len += OCV_OCI_EXTENDED_LEN;
3503 }
3504#endif /* CONFIG_OCV */
3505
3506 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3507 wpa_s->own_addr, wpa_s->bssid,
3508 resp, resp_len, 0) < 0)
3509 wpa_msg(wpa_s, MSG_INFO,
3510 "SME: Failed to send SA Query Response");
3511}
3512
3513
3514static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
3515 const u8 *sa, const u8 *data,
3516 size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003517{
3518 int i;
3519
Hai Shalom74f70d42019-02-11 14:42:39 -08003520 if (!wpa_s->sme.sa_query_trans_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003521 return;
Hai Shalom74f70d42019-02-11 14:42:39 -08003522
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003523 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
3524 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3525
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003526 if (!ether_addr_equal(sa, wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527 return;
3528
3529 for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
3530 if (os_memcmp(wpa_s->sme.sa_query_trans_id +
3531 i * WLAN_SA_QUERY_TR_ID_LEN,
3532 data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
3533 break;
3534 }
3535
3536 if (i >= wpa_s->sme.sa_query_count) {
3537 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
3538 "transaction identifier found");
3539 return;
3540 }
3541
3542 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
3543 "from " MACSTR, MAC2STR(sa));
3544 sme_stop_sa_query(wpa_s);
3545}
3546
Hai Shalom74f70d42019-02-11 14:42:39 -08003547
Hai Shaloma20dcd72022-02-04 13:43:00 -08003548void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
Hai Shalom74f70d42019-02-11 14:42:39 -08003549 const u8 *data, size_t len)
3550{
3551 if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
3552 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003553 if (is_multicast_ether_addr(da)) {
3554 wpa_printf(MSG_DEBUG,
3555 "IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
3556 MAC2STR(da), MAC2STR(sa));
3557 return;
3558 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003559
3560 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
3561 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3562
3563#ifdef CONFIG_OCV
3564 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3565 struct ieee802_11_elems elems;
3566 struct wpa_channel_info ci;
3567
3568 if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
3569 len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
3570 &elems, 1) == ParseFailed) {
3571 wpa_printf(MSG_DEBUG,
3572 "SA Query: Failed to parse elements");
3573 return;
3574 }
3575
3576 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3577 wpa_printf(MSG_WARNING,
3578 "Failed to get channel info to validate received OCI in SA Query Action frame");
3579 return;
3580 }
3581
3582 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
3583 channel_width_to_int(ci.chanwidth),
Hai Shalom899fcc72020-10-19 14:38:18 -07003584 ci.seg1_idx) != OCI_SUCCESS) {
3585 wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR
3586 " frame=saquery%s error=%s",
3587 MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ?
3588 "req" : "resp", ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003589 return;
3590 }
3591 }
3592#endif /* CONFIG_OCV */
3593
3594 if (data[0] == WLAN_SA_QUERY_REQUEST)
3595 sme_process_sa_query_request(wpa_s, sa, data, len);
3596 else if (data[0] == WLAN_SA_QUERY_RESPONSE)
3597 sme_process_sa_query_response(wpa_s, sa, data, len);
3598}