blob: be0bc0d52bb82b1788c63a04b84413e465e3a498 [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 Ravi99c035e2024-07-12 01:42:03 +0000185 wpa_supplicant_update_scan_results(wpa_s, bssid);
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)) {
Sunil Ravi99c035e2024-07-12 01:42:03 +0000408 for_each_link(wpa_s->valid_links, i) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000409 if (wpa_s->mlo_assoc_link_id == i)
410 continue;
411
412 if (ether_addr_equal(
413 wpa_s->links[i].bssid,
414 wpa_s->conf->mld_connect_bssid_pref))
415 goto found;
416 }
417 }
418
419 if (wpa_s->conf->mld_connect_band_pref == MLD_CONNECT_BAND_PREF_AUTO)
420 return bss;
421
422 switch (wpa_s->conf->mld_connect_band_pref) {
423 case MLD_CONNECT_BAND_PREF_2GHZ:
424 low = 2412;
425 high = 2472;
426 break;
427 case MLD_CONNECT_BAND_PREF_5GHZ:
428 low = 5180;
429 high = 5985;
430 break;
431 case MLD_CONNECT_BAND_PREF_6GHZ:
432 low = 5955;
433 high = 7125;
434 break;
435 default:
436 return bss;
437 }
438
Sunil Ravi99c035e2024-07-12 01:42:03 +0000439 for_each_link(wpa_s->valid_links, i) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000440 if (wpa_s->mlo_assoc_link_id == i)
441 continue;
442
443 if (wpa_s->links[i].freq >= low && wpa_s->links[i].freq <= high)
444 goto found;
445 }
446
447found:
448 if (i == MAX_NUM_MLD_LINKS) {
449 wpa_printf(MSG_DEBUG, "MLD: No match for connect/band pref");
450 return bss;
451 }
452
453 wpa_printf(MSG_DEBUG,
454 "MLD: Change BSS for connect: " MACSTR " -> " MACSTR,
455 MAC2STR(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid),
456 MAC2STR(wpa_s->links[i].bssid));
457
458 /* Get the BSS entry and do the switch */
459 bss = wpa_bss_get_bssid(wpa_s, wpa_s->links[i].bssid);
460 wpa_s->mlo_assoc_link_id = i;
461
462 return bss;
463}
464#endif /* CONFIG_TESTING_OPTIONS */
465
466
467static int wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
468 union wpa_event_data *data,
469 int ie_offset)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000470{
471 struct ieee802_11_elems elems;
472 const u8 *mld_addr;
Sunil Ravi640215c2023-06-28 23:08:09 +0000473 u16 status_code = data->auth.status_code;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000474
475 if (!wpa_s->valid_links)
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000476 return 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000477
478 if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
479 data->auth.ies_len - ie_offset,
Sunil Ravi640215c2023-06-28 23:08:09 +0000480 &elems, 0) == ParseFailed) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000481 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
482 goto out;
483 }
484
485 if (!elems.basic_mle || !elems.basic_mle_len) {
486 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
Sunil Ravi640215c2023-06-28 23:08:09 +0000487 if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
488 status_code == WLAN_STATUS_SUCCESS ||
489 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
490 status_code == WLAN_STATUS_SAE_PK)
491 goto out;
492 /* Accept missing Multi-Link element in failed authentication
493 * cases. */
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000494 return 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000495 }
496
497 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
498 if (!mld_addr)
499 goto out;
500
501 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
502
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000503 if (!ether_addr_equal(wpa_s->ap_mld_addr, mld_addr)) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000504 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
505 MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
506 goto out;
507 }
508
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000509 return 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000510out:
511 wpa_printf(MSG_DEBUG, "MLD: Authentication - clearing MLD state");
512 wpas_reset_mlo_info(wpa_s);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000513 return -1;
514}
515
516
517static void wpas_sme_set_mlo_links(struct wpa_supplicant *wpa_s,
518 struct wpa_bss *bss)
519{
Sunil Ravi99c035e2024-07-12 01:42:03 +0000520 u8 i;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000521
522 wpa_s->valid_links = 0;
Sunil Ravi99c035e2024-07-12 01:42:03 +0000523 wpa_s->mlo_assoc_link_id = bss->mld_link_id;
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000524
Sunil Ravi99c035e2024-07-12 01:42:03 +0000525 for_each_link(bss->valid_links, i) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000526 const u8 *bssid = bss->mld_links[i].bssid;
527
Sunil Ravi99c035e2024-07-12 01:42:03 +0000528 wpa_s->valid_links |= BIT(i);
529 os_memcpy(wpa_s->links[i].bssid, bssid, ETH_ALEN);
530 wpa_s->links[i].freq = bss->mld_links[i].freq;
531 wpa_s->links[i].disabled = bss->mld_links[i].disabled;
532
533 if (bss->mld_link_id == i)
534 wpa_s->links[i].bss = bss;
535 else
536 wpa_s->links[i].bss = wpa_bss_get_bssid(wpa_s, bssid);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000537 }
Sunil Ravi77d572f2023-01-17 23:58:31 +0000538}
539
540
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800541static void sme_send_authentication(struct wpa_supplicant *wpa_s,
542 struct wpa_bss *bss, struct wpa_ssid *ssid,
543 int start)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700544{
545 struct wpa_driver_auth_params params;
546 struct wpa_ssid *old_ssid;
547#ifdef CONFIG_IEEE80211R
548 const u8 *ie;
549#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700550#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700551 const u8 *md = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700552#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Hai Shalomfdcde762020-04-02 11:19:20 -0700553 int bssid_changed;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800554 struct wpabuf *resp = NULL;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700555 u8 ext_capab[18];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800556 int ext_capab_len;
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800557 int skip_auth;
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800558 u8 *wpa_ie;
559 size_t wpa_ie_len;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700560#ifdef CONFIG_MBO
561 const u8 *mbo_ie;
562#endif /* CONFIG_MBO */
Hai Shalomfdcde762020-04-02 11:19:20 -0700563 int omit_rsnxe = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700564
565 if (bss == NULL) {
566 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
567 "the network");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800568 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700569 return;
570 }
571
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000572 os_memset(&params, 0, sizeof(params));
573
574 if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
575 !wpa_bss_parse_basic_ml_element(wpa_s, bss, wpa_s->ap_mld_addr,
576 NULL, ssid, NULL) &&
Sunil Ravi99c035e2024-07-12 01:42:03 +0000577 bss->valid_links) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000578 wpa_printf(MSG_DEBUG, "MLD: In authentication");
579 wpas_sme_set_mlo_links(wpa_s, bss);
580
581#ifdef CONFIG_TESTING_OPTIONS
582 bss = wpas_ml_connect_pref(wpa_s, bss);
583
584 if (wpa_s->conf->mld_force_single_link) {
585 wpa_printf(MSG_DEBUG, "MLD: Force single link");
586 wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
587 }
588#endif /* CONFIG_TESTING_OPTIONS */
589 params.mld = true;
590 params.mld_link_id = wpa_s->mlo_assoc_link_id;
591 params.ap_mld_addr = wpa_s->ap_mld_addr;
592 wpas_ml_handle_removed_links(wpa_s, bss);
593 }
594
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800595 skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
596 wpa_s->reassoc_same_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700597 wpa_s->current_bss = bss;
598
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700599 wpa_s->reassociate = 0;
600
601 params.freq = bss->freq;
602 params.bssid = bss->bssid;
603 params.ssid = bss->ssid;
604 params.ssid_len = bss->ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800605 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700606
607 if (wpa_s->sme.ssid_len != params.ssid_len ||
608 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
609 wpa_s->sme.prev_bssid_set = 0;
610
611 wpa_s->sme.freq = params.freq;
612 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
613 wpa_s->sme.ssid_len = params.ssid_len;
614
615 params.auth_alg = WPA_AUTH_ALG_OPEN;
616#ifdef IEEE8021X_EAPOL
617 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
618 if (ssid->leap) {
619 if (ssid->non_leap == 0)
620 params.auth_alg = WPA_AUTH_ALG_LEAP;
621 else
622 params.auth_alg |= WPA_AUTH_ALG_LEAP;
623 }
624 }
625#endif /* IEEE8021X_EAPOL */
626 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
627 params.auth_alg);
628 if (ssid->auth_alg) {
629 params.auth_alg = ssid->auth_alg;
630 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
631 "0x%x", params.auth_alg);
632 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800633#ifdef CONFIG_SAE
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800634 wpa_s->sme.sae_pmksa_caching = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800635 if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
636 const u8 *rsn;
637 struct wpa_ie_data ied;
638
639 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800640 if (!rsn) {
641 wpa_dbg(wpa_s, MSG_DEBUG,
642 "SAE enabled, but target BSS does not advertise RSN");
Hai Shalom021b0b52019-04-10 11:17:58 -0700643#ifdef CONFIG_DPP
644 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
645 (ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
646 (ied.key_mgmt & WPA_KEY_MGMT_DPP)) {
647 wpa_dbg(wpa_s, MSG_DEBUG, "Prefer DPP over SAE when both are enabled");
648#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800649 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
650 wpa_key_mgmt_sae(ied.key_mgmt)) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000651 if (wpas_is_sae_avoided(wpa_s, ssid, &ied)) {
652 wpa_dbg(wpa_s, MSG_DEBUG,
653 "SAE enabled, but disallowing SAE auth_alg without PMF");
654 } else {
655 wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
656 params.auth_alg = WPA_AUTH_ALG_SAE;
657 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800658 } else {
659 wpa_dbg(wpa_s, MSG_DEBUG,
660 "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800661 }
662 }
663#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700664
Hai Shalomfdcde762020-04-02 11:19:20 -0700665#ifdef CONFIG_WEP
666 {
667 int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700668
Hai Shalomfdcde762020-04-02 11:19:20 -0700669 for (i = 0; i < NUM_WEP_KEYS; i++) {
670 if (ssid->wep_key_len[i])
671 params.wep_key[i] = ssid->wep_key[i];
672 params.wep_key_len[i] = ssid->wep_key_len[i];
673 }
674 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
675 }
676#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677
678 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
679 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800680 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700681 int try_opportunistic;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700682 const u8 *cache_id = NULL;
683
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800684 try_opportunistic = (ssid->proactive_key_caching < 0 ?
685 wpa_s->conf->okc :
686 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700687 (ssid->proto & WPA_PROTO_RSN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700688#ifdef CONFIG_FILS
689 if (wpa_key_mgmt_fils(ssid->key_mgmt))
690 cache_id = wpa_bss_get_fils_cache_id(bss);
691#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000692 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
693 params.mld ? params.ap_mld_addr :
694 bss->bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700695 wpa_s->current_ssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700696 try_opportunistic, cache_id,
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000697 0, false) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800698 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700699 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
700 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
701 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000702 &wpa_s->sme.assoc_req_ie_len,
703 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700704 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
705 "key management and encryption suites");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800706 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707 return;
708 }
Hai Shalom74f70d42019-02-11 14:42:39 -0800709#ifdef CONFIG_HS20
710 } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
711 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
712 /* No PMKSA caching, but otherwise similar to RSN/WPA */
713 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
714 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
715 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000716 &wpa_s->sme.assoc_req_ie_len,
717 false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800718 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
719 "key management and encryption suites");
720 wpas_connect_work_done(wpa_s);
721 return;
722 }
723#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700724 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
725 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
726 /*
727 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
728 * use non-WPA since the scan results did not indicate that the
729 * AP is using WPA or WPA2.
730 */
731 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
732 wpa_s->sme.assoc_req_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800733 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
735 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
736 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000737 &wpa_s->sme.assoc_req_ie_len,
738 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
740 "key management and encryption suites (no "
741 "scan results)");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800742 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743 return;
744 }
745#ifdef CONFIG_WPS
746 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
747 struct wpabuf *wps_ie;
748 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
749 if (wps_ie && wpabuf_len(wps_ie) <=
750 sizeof(wpa_s->sme.assoc_req_ie)) {
751 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
752 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
753 wpa_s->sme.assoc_req_ie_len);
754 } else
755 wpa_s->sme.assoc_req_ie_len = 0;
756 wpabuf_free(wps_ie);
757 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
758#endif /* CONFIG_WPS */
759 } else {
760 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
761 wpa_s->sme.assoc_req_ie_len = 0;
762 }
763
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800764 /* In case the WPA vendor IE is used, it should be placed after all the
765 * non-vendor IEs, as the lower layer expects the IEs to be ordered as
766 * defined in the standard. Store the WPA IE so it can later be
767 * inserted at the correct location.
768 */
769 wpa_ie = NULL;
770 wpa_ie_len = 0;
771 if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
772 wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
773 wpa_s->sme.assoc_req_ie_len);
774 if (wpa_ie) {
775 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
776
777 wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
778 wpa_s->sme.assoc_req_ie_len = 0;
779 } else {
780 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
781 wpas_connect_work_done(wpa_s);
782 return;
783 }
784 }
785
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700786#ifdef CONFIG_IEEE80211R
787 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
788 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
789 md = ie + 2;
790 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
Hai Shalom021b0b52019-04-10 11:17:58 -0700791 if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
792 !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
793 md = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700794 if (md) {
795 /* Prepare for the next transition */
796 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
797 }
798
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700799 if (md) {
800 wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
801 md[0], md[1]);
802
Hai Shalomfdcde762020-04-02 11:19:20 -0700803 omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 if (wpa_s->sme.assoc_req_ie_len + 5 <
805 sizeof(wpa_s->sme.assoc_req_ie)) {
806 struct rsn_mdie *mdie;
807 u8 *pos = wpa_s->sme.assoc_req_ie +
808 wpa_s->sme.assoc_req_ie_len;
809 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
810 *pos++ = sizeof(*mdie);
811 mdie = (struct rsn_mdie *) pos;
812 os_memcpy(mdie->mobility_domain, md,
813 MOBILITY_DOMAIN_ID_LEN);
814 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
815 wpa_s->sme.assoc_req_ie_len += 5;
816 }
817
Hai Shalom74f70d42019-02-11 14:42:39 -0800818 if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
Sunil Ravi77d572f2023-01-17 23:58:31 +0000820 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700821 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
822 "over-the-air");
823 params.auth_alg = WPA_AUTH_ALG_FT;
824 params.ie = wpa_s->sme.ft_ies;
825 params.ie_len = wpa_s->sme.ft_ies_len;
826 }
827 }
828#endif /* CONFIG_IEEE80211R */
829
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800830 wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800831 if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700832 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
833 struct wpa_ie_data _ie;
834 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
835 _ie.capabilities &
836 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
837 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
838 "MFP: require MFP");
839 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
840 }
841 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700842
843#ifdef CONFIG_P2P
844 if (wpa_s->global->p2p) {
845 u8 *pos;
846 size_t len;
847 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700848 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
849 len = sizeof(wpa_s->sme.assoc_req_ie) -
850 wpa_s->sme.assoc_req_ie_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800851 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
852 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700853 if (res >= 0)
854 wpa_s->sme.assoc_req_ie_len += res;
855 }
856#endif /* CONFIG_P2P */
857
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800858#ifdef CONFIG_FST
859 if (wpa_s->fst_ies) {
860 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
861
862 if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <=
863 sizeof(wpa_s->sme.assoc_req_ie)) {
864 os_memcpy(wpa_s->sme.assoc_req_ie +
865 wpa_s->sme.assoc_req_ie_len,
866 wpabuf_head(wpa_s->fst_ies),
867 fst_ies_len);
868 wpa_s->sme.assoc_req_ie_len += fst_ies_len;
869 }
870 }
871#endif /* CONFIG_FST */
872
873 sme_auth_handle_rrm(wpa_s, bss);
874
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000875#ifndef CONFIG_NO_RRM
Dmitry Shmidt29333592017-01-09 12:27:11 -0800876 wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
Hai Shalomfdcde762020-04-02 11:19:20 -0700877 wpa_s, ssid, bss,
Dmitry Shmidt29333592017-01-09 12:27:11 -0800878 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
879 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
Sunil Ravib0ac25f2024-07-12 01:42:03 +0000880#endif /* CONFIG_NO_RRM */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800881
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700882 if (params.p2p)
883 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
884 else
885 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
886
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800887 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
Sunil Ravi2a14cf12023-11-21 00:54:38 +0000888 sizeof(ext_capab), bss);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800889 if (ext_capab_len > 0) {
890 u8 *pos = wpa_s->sme.assoc_req_ie;
891 if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
892 pos += 2 + pos[1];
893 os_memmove(pos + ext_capab_len, pos,
894 wpa_s->sme.assoc_req_ie_len -
895 (pos - wpa_s->sme.assoc_req_ie));
896 wpa_s->sme.assoc_req_ie_len += ext_capab_len;
897 os_memcpy(pos, ext_capab, ext_capab_len);
898 }
899
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800900#ifdef CONFIG_TESTING_OPTIONS
901 if (wpa_s->rsnxe_override_assoc &&
902 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
903 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
904 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
905 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
906 wpabuf_head(wpa_s->rsnxe_override_assoc),
907 wpabuf_len(wpa_s->rsnxe_override_assoc));
908 wpa_s->sme.assoc_req_ie_len +=
909 wpabuf_len(wpa_s->rsnxe_override_assoc);
910 } else
911#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -0700912 if (wpa_s->rsnxe_len > 0 &&
913 wpa_s->rsnxe_len <=
Hai Shalomfdcde762020-04-02 11:19:20 -0700914 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len &&
915 !omit_rsnxe) {
Hai Shalomc3565922019-10-28 11:58:20 -0700916 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
917 wpa_s->rsnxe, wpa_s->rsnxe_len);
918 wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
919 }
920
Dmitry Shmidt04949592012-07-19 12:16:46 -0700921#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -0800922 if (is_hs20_network(wpa_s, ssid, bss)
923#ifndef ANDROID /* Android does not use the native HS 2.0 config */
924 && is_hs20_config(wpa_s)
925#endif /* ANDROID */
926 ) {
Dmitry Shmidt04949592012-07-19 12:16:46 -0700927 struct wpabuf *hs20;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800928
Roshan Pius3a1667e2018-07-03 15:17:14 -0700929 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700930 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800931 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700932 size_t len;
933
Hai Shalom74f70d42019-02-11 14:42:39 -0800934 wpas_hs20_add_indication(hs20, pps_mo_id,
935 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -0700936 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700937 len = sizeof(wpa_s->sme.assoc_req_ie) -
938 wpa_s->sme.assoc_req_ie_len;
939 if (wpabuf_len(hs20) <= len) {
940 os_memcpy(wpa_s->sme.assoc_req_ie +
941 wpa_s->sme.assoc_req_ie_len,
942 wpabuf_head(hs20), wpabuf_len(hs20));
943 wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
944 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700945 wpabuf_free(hs20);
946 }
947 }
948#endif /* CONFIG_HS20 */
949
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800950 if (wpa_ie) {
951 size_t len;
952
953 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
954
955 len = sizeof(wpa_s->sme.assoc_req_ie) -
956 wpa_s->sme.assoc_req_ie_len;
957
958 if (len > wpa_ie_len) {
959 os_memcpy(wpa_s->sme.assoc_req_ie +
960 wpa_s->sme.assoc_req_ie_len,
961 wpa_ie, wpa_ie_len);
962 wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
963 } else {
964 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
965 }
966
967 os_free(wpa_ie);
968 }
969
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800970 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
971 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
972 size_t len;
973
974 len = sizeof(wpa_s->sme.assoc_req_ie) -
975 wpa_s->sme.assoc_req_ie_len;
976 if (wpabuf_len(buf) <= len) {
977 os_memcpy(wpa_s->sme.assoc_req_ie +
978 wpa_s->sme.assoc_req_ie_len,
979 wpabuf_head(buf), wpabuf_len(buf));
980 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
981 }
982 }
983
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800984#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -0700985 mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -0700986 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800987 int len;
988
989 len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
990 wpa_s->sme.assoc_req_ie_len,
991 sizeof(wpa_s->sme.assoc_req_ie) -
Hai Shalomce48b4a2018-09-05 11:41:35 -0700992 wpa_s->sme.assoc_req_ie_len,
993 !!mbo_attr_from_mbo_ie(mbo_ie,
994 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800995 if (len >= 0)
996 wpa_s->sme.assoc_req_ie_len += len;
997 }
998#endif /* CONFIG_MBO */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800999
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001000#ifdef CONFIG_SAE
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001001 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001002 pmksa_cache_set_current(wpa_s->wpa, NULL,
1003 params.mld ? params.ap_mld_addr :
1004 bss->bssid,
1005 ssid, 0,
Hai Shalom021b0b52019-04-10 11:17:58 -07001006 NULL,
Sunil Ravi89eba102022-09-13 21:04:37 -07001007 wpa_key_mgmt_sae(wpa_s->key_mgmt) ?
1008 wpa_s->key_mgmt :
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001009 (int) WPA_KEY_MGMT_SAE, false) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001010 wpa_dbg(wpa_s, MSG_DEBUG,
1011 "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001012 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001013 params.auth_alg = WPA_AUTH_ALG_OPEN;
1014 wpa_s->sme.sae_pmksa_caching = 1;
1015 }
1016
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001017 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001018 if (start)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001019 resp = sme_auth_build_sae_commit(wpa_s, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001020 bss->bssid,
1021 params.mld ?
1022 params.ap_mld_addr :
1023 NULL, 0,
Hai Shalom899fcc72020-10-19 14:38:18 -07001024 start == 2, NULL,
1025 NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001026 else
Roshan Pius3a1667e2018-07-03 15:17:14 -07001027 resp = sme_auth_build_sae_confirm(wpa_s, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001028 if (resp == NULL) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001029 wpas_connection_failed(wpa_s, bss->bssid, NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001030 return;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001031 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001032 params.auth_data = wpabuf_head(resp);
1033 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001034 wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001035 }
1036#endif /* CONFIG_SAE */
1037
Hai Shalomfdcde762020-04-02 11:19:20 -07001038 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1039 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1040 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1041 if (bssid_changed)
1042 wpas_notify_bssid_changed(wpa_s);
1043
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001044 old_ssid = wpa_s->current_ssid;
1045 wpa_s->current_ssid = ssid;
1046 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1047 wpa_supplicant_initiate_eapol(wpa_s);
1048
1049#ifdef CONFIG_FILS
1050 /* TODO: FILS operations can in some cases be done between different
1051 * network_ctx (i.e., same credentials can be used with multiple
1052 * networks). */
1053 if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
1054 wpa_key_mgmt_fils(ssid->key_mgmt)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001055 const u8 *indic;
1056 u16 fils_info;
Hai Shalomce48b4a2018-09-05 11:41:35 -07001057 const u8 *realm, *username, *rrk;
1058 size_t realm_len, username_len, rrk_len;
1059 u16 next_seq_num;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001060
1061 /*
1062 * Check FILS Indication element (FILS Information field) bits
1063 * indicating supported authentication algorithms against local
1064 * configuration (ssid->fils_dh_group). Try to use FILS
1065 * authentication only if the AP supports the combination in the
1066 * network profile. */
1067 indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
1068 if (!indic || indic[1] < 2) {
1069 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1070 " does not include FILS Indication element - cannot use FILS authentication with it",
1071 MAC2STR(bss->bssid));
1072 goto no_fils;
1073 }
1074
1075 fils_info = WPA_GET_LE16(indic + 2);
1076 if (ssid->fils_dh_group == 0 && !(fils_info & BIT(9))) {
1077 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1078 " does not support FILS SK without PFS - cannot use FILS authentication with it",
1079 MAC2STR(bss->bssid));
1080 goto no_fils;
1081 }
1082 if (ssid->fils_dh_group != 0 && !(fils_info & BIT(10))) {
1083 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1084 " does not support FILS SK with PFS - cannot use FILS authentication with it",
1085 MAC2STR(bss->bssid));
1086 goto no_fils;
1087 }
1088
Hai Shalomce48b4a2018-09-05 11:41:35 -07001089 if (wpa_s->last_con_fail_realm &&
1090 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
1091 &username, &username_len,
1092 &realm, &realm_len, &next_seq_num,
1093 &rrk, &rrk_len) == 0 &&
1094 realm && realm_len == wpa_s->last_con_fail_realm_len &&
1095 os_memcmp(realm, wpa_s->last_con_fail_realm,
1096 realm_len) == 0) {
1097 wpa_printf(MSG_DEBUG,
1098 "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
1099 goto no_fils;
1100 }
1101
Sunil Ravi77d572f2023-01-17 23:58:31 +00001102 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
1103 params.mld ? params.ap_mld_addr :
1104 bss->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001105 ssid, 0,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001106 wpa_bss_get_fils_cache_id(bss),
Sunil Ravi2a14cf12023-11-21 00:54:38 +00001107 0, false) == 0)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001108 wpa_printf(MSG_DEBUG,
1109 "SME: Try to use FILS with PMKSA caching");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001110 resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001111 if (resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001112 int auth_alg;
1113
1114 if (ssid->fils_dh_group)
1115 wpa_printf(MSG_DEBUG,
1116 "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
1117 ssid->fils_dh_group);
1118 else
1119 wpa_printf(MSG_DEBUG,
1120 "SME: Try to use FILS SK authentication without PFS");
1121 auth_alg = ssid->fils_dh_group ?
1122 WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
1123 params.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001124 params.auth_data = wpabuf_head(resp);
1125 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001126 wpa_s->sme.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001127 }
1128 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001129no_fils:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001130#endif /* CONFIG_FILS */
1131
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001132 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001133 wpa_supplicant_cancel_scan(wpa_s);
1134
1135 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
1136 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
1137 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
1138
Hai Shalome21d4e82020-04-29 16:34:06 -07001139 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001140 wpa_clear_keys(wpa_s, bss->bssid);
1141 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001142 if (old_ssid != wpa_s->current_ssid)
1143 wpas_notify_network_changed(wpa_s);
1144
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001145#ifdef CONFIG_HS20
1146 hs20_configure_frame_filters(wpa_s);
1147#endif /* CONFIG_HS20 */
1148
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001149#ifdef CONFIG_P2P
1150 /*
1151 * If multi-channel concurrency is not supported, check for any
1152 * frequency conflict. In case of any frequency conflict, remove the
1153 * least prioritized connection.
1154 */
1155 if (wpa_s->num_multichan_concurrent < 2) {
1156 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001157 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001158 if (num > 0 && freq > 0 && freq != params.freq) {
1159 wpa_printf(MSG_DEBUG,
1160 "Conflicting frequency found (%d != %d)",
1161 freq, params.freq);
1162 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1163 params.freq,
1164 ssid) < 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001165 wpas_connection_failed(wpa_s, bss->bssid, NULL);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001166 wpa_supplicant_mark_disassoc(wpa_s);
1167 wpabuf_free(resp);
1168 wpas_connect_work_done(wpa_s);
1169 return;
1170 }
1171 }
1172 }
1173#endif /* CONFIG_P2P */
1174
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001175 if (skip_auth) {
1176 wpa_msg(wpa_s, MSG_DEBUG,
1177 "SME: Skip authentication step on reassoc-to-same-BSS");
1178 wpabuf_free(resp);
1179 sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN);
1180 return;
1181 }
1182
1183
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001184 wpa_s->sme.auth_alg = params.auth_alg;
1185 if (wpa_drv_authenticate(wpa_s, &params) < 0) {
1186 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
1187 "driver failed");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001188 wpas_connection_failed(wpa_s, bss->bssid, NULL);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001189 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001190 wpabuf_free(resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001191 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001192 return;
1193 }
1194
1195 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
1196 NULL);
1197
1198 /*
1199 * Association will be started based on the authentication event from
1200 * the driver.
1201 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001202
1203 wpabuf_free(resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001204}
1205
1206
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001207static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
1208{
1209 struct wpa_connect_work *cwork = work->ctx;
1210 struct wpa_supplicant *wpa_s = work->wpa_s;
1211
Hai Shaloma20dcd72022-02-04 13:43:00 -08001212 wpa_s->roam_in_progress = false;
1213#ifdef CONFIG_WNM
1214 wpa_s->bss_trans_mgmt_in_progress = false;
1215#endif /* CONFIG_WNM */
1216
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001217 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001218 if (work->started)
1219 wpa_s->connect_work = NULL;
1220
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001221 wpas_connect_work_free(cwork);
1222 return;
1223 }
1224
1225 wpa_s->connect_work = work;
1226
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001227 if (cwork->bss_removed ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001228 !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
1229 wpas_network_disabled(wpa_s, cwork->ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001230 wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
1231 wpas_connect_work_done(wpa_s);
1232 return;
1233 }
1234
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001235 /* Starting new connection, so clear the possibly used WPA IE from the
1236 * previous association. */
1237 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07001238 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
1239 wpa_s->rsnxe_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001240
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001241 sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001242 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001243}
1244
1245
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001246void sme_authenticate(struct wpa_supplicant *wpa_s,
1247 struct wpa_bss *bss, struct wpa_ssid *ssid)
1248{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001249 struct wpa_connect_work *cwork;
1250
1251 if (bss == NULL || ssid == NULL)
1252 return;
1253 if (wpa_s->connect_work) {
1254 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
1255 return;
1256 }
1257
Hai Shaloma20dcd72022-02-04 13:43:00 -08001258 if (wpa_s->roam_in_progress) {
1259 wpa_dbg(wpa_s, MSG_DEBUG,
1260 "SME: Reject sme_authenticate() in favor of explicit roam request");
1261 return;
1262 }
1263#ifdef CONFIG_WNM
1264 if (wpa_s->bss_trans_mgmt_in_progress) {
1265 wpa_dbg(wpa_s, MSG_DEBUG,
1266 "SME: Reject sme_authenticate() in favor of BSS transition management request");
1267 return;
1268 }
1269#endif /* CONFIG_WNM */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001270 if (radio_work_pending(wpa_s, "sme-connect")) {
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001271 /*
1272 * The previous sme-connect work might no longer be valid due to
1273 * the fact that the BSS list was updated. In addition, it makes
1274 * sense to adhere to the 'newer' decision.
1275 */
1276 wpa_dbg(wpa_s, MSG_DEBUG,
1277 "SME: Remove previous pending sme-connect");
1278 radio_remove_works(wpa_s, "sme-connect", 0);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001279 }
1280
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001281 wpas_abort_ongoing_scan(wpa_s);
1282
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001283 cwork = os_zalloc(sizeof(*cwork));
1284 if (cwork == NULL)
1285 return;
1286 cwork->bss = bss;
1287 cwork->ssid = ssid;
1288 cwork->sme = 1;
1289
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001290#ifdef CONFIG_SAE
1291 wpa_s->sme.sae.state = SAE_NOTHING;
1292 wpa_s->sme.sae.send_confirm = 0;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001293 wpa_s->sme.sae_group_index = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001294#endif /* CONFIG_SAE */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001295
1296 if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
1297 sme_auth_start_cb, cwork) < 0)
1298 wpas_connect_work_free(cwork);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001299}
1300
1301
1302#ifdef CONFIG_SAE
1303
Sunil Ravi036cec52023-03-29 11:35:17 -07001304#define WPA_AUTH_FRAME_ML_IE_LEN (6 + ETH_ALEN)
1305
1306static void wpa_auth_ml_ie(struct wpabuf *buf, const u8 *mld_addr)
1307{
1308
1309 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1310 wpabuf_put_u8(buf, 4 + ETH_ALEN);
1311 wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK);
1312
1313 /* Basic Multi-Link element Control field */
1314 wpabuf_put_u8(buf, 0x0);
1315 wpabuf_put_u8(buf, 0x0);
1316
1317 /* Common Info */
1318 wpabuf_put_u8(buf, 0x7); /* length = Length field + MLD MAC address */
1319 wpabuf_put_data(buf, mld_addr, ETH_ALEN);
1320}
1321
1322
Roshan Pius3a1667e2018-07-03 15:17:14 -07001323static int sme_external_auth_build_buf(struct wpabuf *buf,
1324 struct wpabuf *params,
1325 const u8 *sa, const u8 *da,
Hai Shalomc3565922019-10-28 11:58:20 -07001326 u16 auth_transaction, u16 seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001327 u16 status_code, const u8 *mld_addr)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001328{
1329 struct ieee80211_mgmt *resp;
1330
1331 resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
1332 u.auth.variable));
1333
1334 resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
1335 (WLAN_FC_STYPE_AUTH << 4));
1336 os_memcpy(resp->da, da, ETH_ALEN);
1337 os_memcpy(resp->sa, sa, ETH_ALEN);
1338 os_memcpy(resp->bssid, da, ETH_ALEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08001339 resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
1340 resp->seq_ctrl = host_to_le16(seq_num << 4);
1341 resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
Hai Shalomc3565922019-10-28 11:58:20 -07001342 resp->u.auth.status_code = host_to_le16(status_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001343 if (params)
1344 wpabuf_put_buf(buf, params);
1345
Sunil Ravi036cec52023-03-29 11:35:17 -07001346 if (mld_addr)
1347 wpa_auth_ml_ie(buf, mld_addr);
1348
Roshan Pius3a1667e2018-07-03 15:17:14 -07001349 return 0;
1350}
1351
1352
Hai Shalom81f62d82019-07-22 12:10:00 -07001353static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
1354 const u8 *bssid,
1355 struct wpa_ssid *ssid)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001356{
1357 struct wpabuf *resp, *buf;
Hai Shalomc3565922019-10-28 11:58:20 -07001358 int use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -07001359 bool use_pk;
1360 u16 status;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001361
Sunil Ravi036cec52023-03-29 11:35:17 -07001362 resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid,
1363 wpa_s->sme.ext_ml_auth ?
1364 wpa_s->sme.ext_auth_ap_mld_addr : NULL,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001365 1, 0, &use_pt, &use_pk);
Hai Shalom81f62d82019-07-22 12:10:00 -07001366 if (!resp) {
1367 wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
1368 return -1;
1369 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001370
1371 wpa_s->sme.sae.state = SAE_COMMITTED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001372 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp) +
1373 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1374 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001375 if (!buf) {
1376 wpabuf_free(resp);
Hai Shalom81f62d82019-07-22 12:10:00 -07001377 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001378 }
1379
1380 wpa_s->sme.seq_num++;
Hai Shalom899fcc72020-10-19 14:38:18 -07001381 if (use_pk)
1382 status = WLAN_STATUS_SAE_PK;
1383 else if (use_pt)
1384 status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
1385 else
1386 status = WLAN_STATUS_SUCCESS;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001387 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Sunil Ravi036cec52023-03-29 11:35:17 -07001388 wpa_s->sme.ext_ml_auth ?
1389 wpa_s->sme.ext_auth_ap_mld_addr : bssid, 1,
1390 wpa_s->sme.seq_num, status,
1391 wpa_s->sme.ext_ml_auth ?
1392 wpa_s->own_addr : NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07001393 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001394 wpabuf_free(resp);
1395 wpabuf_free(buf);
Hai Shalom81f62d82019-07-22 12:10:00 -07001396
1397 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001398}
1399
1400
1401static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
1402 u16 status)
1403{
1404 struct external_auth params;
1405
Sunil Ravi89eba102022-09-13 21:04:37 -07001406 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001407 os_memset(&params, 0, sizeof(params));
1408 params.status = status;
Hai Shalom66904732019-05-29 11:54:04 -07001409 params.ssid = wpa_s->sme.ext_auth_ssid;
1410 params.ssid_len = wpa_s->sme.ext_auth_ssid_len;
1411 params.bssid = wpa_s->sme.ext_auth_bssid;
Hai Shalomc3565922019-10-28 11:58:20 -07001412 if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
1413 params.pmkid = wpa_s->sme.sae.pmkid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001414 wpa_drv_send_external_auth_status(wpa_s, &params);
1415}
1416
1417
Hai Shalom81f62d82019-07-22 12:10:00 -07001418static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
1419 union wpa_event_data *data)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001420{
1421 struct wpa_ssid *ssid;
1422 size_t ssid_str_len = data->external_auth.ssid_len;
Hai Shalom5f92bc92019-04-18 11:54:11 -07001423 const u8 *ssid_str = data->external_auth.ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001424
Sunil Ravi89eba102022-09-13 21:04:37 -07001425 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001426 /* Get the SSID conf from the ssid string obtained */
1427 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1428 if (!wpas_network_disabled(wpa_s, ssid) &&
1429 ssid_str_len == ssid->ssid_len &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001430 os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001431 wpa_key_mgmt_sae(ssid->key_mgmt)) {
1432 /* Make sure PT is derived */
Sunil Ravi036cec52023-03-29 11:35:17 -07001433 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Sunil Ravi89eba102022-09-13 21:04:37 -07001434 wpa_s->sme.ext_auth_wpa_ssid = ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001435 break;
Sunil Ravi89eba102022-09-13 21:04:37 -07001436 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001437 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001438 if (!ssid ||
1439 sme_external_auth_send_sae_commit(wpa_s, data->external_auth.bssid,
1440 ssid) < 0)
1441 return -1;
1442
1443 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001444}
1445
1446
1447static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
1448 const u8 *da)
1449{
1450 struct wpabuf *resp, *buf;
1451
1452 resp = sme_auth_build_sae_confirm(wpa_s, 1);
1453 if (!resp) {
1454 wpa_printf(MSG_DEBUG, "SAE: Confirm message buf alloc failure");
1455 return;
1456 }
1457
1458 wpa_s->sme.sae.state = SAE_CONFIRMED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001459 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp) +
1460 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1461 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001462 if (!buf) {
1463 wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure");
1464 wpabuf_free(resp);
1465 return;
1466 }
1467 wpa_s->sme.seq_num++;
1468 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Hai Shalomc3565922019-10-28 11:58:20 -07001469 da, 2, wpa_s->sme.seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001470 WLAN_STATUS_SUCCESS,
1471 wpa_s->sme.ext_ml_auth ?
1472 wpa_s->own_addr : NULL);
1473
Hai Shalomfdcde762020-04-02 11:19:20 -07001474 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001475 wpabuf_free(resp);
1476 wpabuf_free(buf);
1477}
1478
1479
Sunil Ravi77d572f2023-01-17 23:58:31 +00001480static bool is_sae_key_mgmt_suite(struct wpa_supplicant *wpa_s, u32 suite)
1481{
1482 /* suite is supposed to be the selector value in host byte order with
1483 * the OUI in three most significant octets. However, the initial
1484 * implementation swapped that byte order and did not work with drivers
1485 * that followed the expected byte order. Keep a workaround here to
1486 * match that initial implementation so that already deployed use cases
1487 * remain functional. */
1488 if (RSN_SELECTOR_GET(&suite) == RSN_AUTH_KEY_MGMT_SAE) {
1489 /* Old drivers which follow initial implementation send SAE AKM
1490 * for both SAE and FT-SAE connections. In that case, determine
1491 * the actual AKM from wpa_s->key_mgmt. */
1492 wpa_s->sme.ext_auth_key_mgmt = wpa_s->key_mgmt;
1493 return true;
1494 }
1495
1496 if (suite == RSN_AUTH_KEY_MGMT_SAE)
1497 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE;
1498 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE)
1499 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE;
1500 else if (suite == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
1501 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1502 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
1503 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1504 else
1505 return false;
1506
1507 return true;
1508}
1509
1510
Roshan Pius3a1667e2018-07-03 15:17:14 -07001511void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
1512 union wpa_event_data *data)
1513{
Sunil Ravi77d572f2023-01-17 23:58:31 +00001514 if (!is_sae_key_mgmt_suite(wpa_s, data->external_auth.key_mgmt_suite))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001515 return;
1516
1517 if (data->external_auth.action == EXT_AUTH_START) {
Hai Shalom66904732019-05-29 11:54:04 -07001518 if (!data->external_auth.bssid || !data->external_auth.ssid)
1519 return;
1520 os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid,
1521 ETH_ALEN);
1522 os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid,
1523 data->external_auth.ssid_len);
1524 wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len;
Sunil Ravi036cec52023-03-29 11:35:17 -07001525 if (data->external_auth.mld_addr) {
1526 wpa_s->sme.ext_ml_auth = true;
1527 os_memcpy(wpa_s->sme.ext_auth_ap_mld_addr,
1528 data->external_auth.mld_addr, ETH_ALEN);
1529 } else {
1530 wpa_s->sme.ext_ml_auth = false;
1531 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001532 wpa_s->sme.seq_num = 0;
1533 wpa_s->sme.sae.state = SAE_NOTHING;
1534 wpa_s->sme.sae.send_confirm = 0;
1535 wpa_s->sme.sae_group_index = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001536 if (sme_handle_external_auth_start(wpa_s, data) < 0)
1537 sme_send_external_auth_status(wpa_s,
1538 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001539 } else if (data->external_auth.action == EXT_AUTH_ABORT) {
1540 /* Report failure to driver for the wrong trigger */
1541 sme_send_external_auth_status(wpa_s,
1542 WLAN_STATUS_UNSPECIFIED_FAILURE);
1543 }
1544}
1545
1546
Hai Shalomc3565922019-10-28 11:58:20 -07001547static int sme_sae_is_group_enabled(struct wpa_supplicant *wpa_s, int group)
1548{
1549 int *groups = wpa_s->conf->sae_groups;
1550 int default_groups[] = { 19, 20, 21, 0 };
1551 int i;
1552
1553 if (!groups)
1554 groups = default_groups;
1555
1556 for (i = 0; groups[i] > 0; i++) {
1557 if (groups[i] == group)
1558 return 1;
1559 }
1560
1561 return 0;
1562}
1563
1564
1565static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
1566 const struct wpabuf *groups)
1567{
1568 size_t i, count;
1569 const u8 *pos;
1570
1571 if (!groups)
1572 return 0;
1573
1574 pos = wpabuf_head(groups);
1575 count = wpabuf_len(groups) / 2;
1576 for (i = 0; i < count; i++) {
1577 int enabled;
1578 u16 group;
1579
1580 group = WPA_GET_LE16(pos);
1581 pos += 2;
1582 enabled = sme_sae_is_group_enabled(wpa_s, group);
1583 wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
1584 group, enabled ? "enabled" : "disabled");
1585 if (enabled)
1586 return 1;
1587 }
1588
1589 return 0;
1590}
1591
1592
Sunil Ravi036cec52023-03-29 11:35:17 -07001593static int sme_external_ml_auth(struct wpa_supplicant *wpa_s,
Sunil Ravi640215c2023-06-28 23:08:09 +00001594 const u8 *data, size_t len, int ie_offset,
1595 u16 status_code)
Sunil Ravi036cec52023-03-29 11:35:17 -07001596{
1597 struct ieee802_11_elems elems;
1598 const u8 *mld_addr;
1599
1600 if (ieee802_11_parse_elems(data + ie_offset, len - ie_offset,
Sunil Ravi640215c2023-06-28 23:08:09 +00001601 &elems, 0) == ParseFailed) {
Sunil Ravi036cec52023-03-29 11:35:17 -07001602 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
1603 return -1;
1604 }
1605
1606 if (!elems.basic_mle || !elems.basic_mle_len) {
1607 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
Sunil Ravi640215c2023-06-28 23:08:09 +00001608 if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
1609 status_code == WLAN_STATUS_SUCCESS ||
1610 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
1611 status_code == WLAN_STATUS_SAE_PK)
1612 return -1;
1613 /* Accept missing Multi-Link element in failed authentication
1614 * cases. */
1615 return 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07001616 }
1617
1618 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
1619 if (!mld_addr) {
1620 wpa_printf(MSG_DEBUG, "MLD: No MLD address in ML element");
1621 return -1;
1622 }
1623
1624 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
1625
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001626 if (!ether_addr_equal(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr)) {
Sunil Ravi036cec52023-03-29 11:35:17 -07001627 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
Sunil Ravi640215c2023-06-28 23:08:09 +00001628 MACSTR ")",
1629 MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr));
Sunil Ravi036cec52023-03-29 11:35:17 -07001630 return -1;
1631 }
1632
1633 return 0;
1634}
1635
1636
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001637static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001638 u16 status_code, const u8 *data, size_t len,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001639 int external, const u8 *sa, int *ie_offset)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001640{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001641 int *groups;
1642
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001643 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
1644 "status code %u", auth_transaction, status_code);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001645
1646 if (auth_transaction == 1 &&
1647 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1648 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001649 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1650 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001651 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001652 u16 group;
Hai Shalomfdcde762020-04-02 11:19:20 -07001653 const u8 *token_pos;
1654 size_t token_len;
1655 int h2e = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001656
1657 groups = wpa_s->conf->sae_groups;
1658 if (!groups || groups[0] <= 0)
1659 groups = default_groups;
1660
Hai Shalomfdcde762020-04-02 11:19:20 -07001661 wpa_hexdump(MSG_DEBUG, "SME: SAE anti-clogging token request",
1662 data, len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001663 if (len < sizeof(le16)) {
1664 wpa_dbg(wpa_s, MSG_DEBUG,
1665 "SME: Too short SAE anti-clogging token request");
1666 return -1;
1667 }
1668 group = WPA_GET_LE16(data);
1669 wpa_dbg(wpa_s, MSG_DEBUG,
1670 "SME: SAE anti-clogging token requested (group %u)",
1671 group);
1672 if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
1673 WLAN_STATUS_SUCCESS) {
1674 wpa_dbg(wpa_s, MSG_ERROR,
1675 "SME: SAE group %u of anti-clogging request is invalid",
1676 group);
1677 return -1;
1678 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001679 wpabuf_free(wpa_s->sme.sae_token);
Hai Shalomfdcde762020-04-02 11:19:20 -07001680 token_pos = data + sizeof(le16);
1681 token_len = len - sizeof(le16);
Hai Shalom899fcc72020-10-19 14:38:18 -07001682 h2e = wpa_s->sme.sae.h2e;
Hai Shalomfdcde762020-04-02 11:19:20 -07001683 if (h2e) {
Sunil8cd6f4d2022-06-28 18:40:46 +00001684 u8 id, elen, extid;
1685
Hai Shalomfdcde762020-04-02 11:19:20 -07001686 if (token_len < 3) {
1687 wpa_dbg(wpa_s, MSG_DEBUG,
1688 "SME: Too short SAE anti-clogging token container");
1689 return -1;
1690 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001691 id = *token_pos++;
1692 elen = *token_pos++;
1693 extid = *token_pos++;
1694 if (id != WLAN_EID_EXTENSION ||
1695 elen == 0 || elen > token_len - 2 ||
1696 extid != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001697 wpa_dbg(wpa_s, MSG_DEBUG,
1698 "SME: Invalid SAE anti-clogging token container header");
1699 return -1;
1700 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001701 token_len = elen - 1;
Hai Shalomfdcde762020-04-02 11:19:20 -07001702 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00001703
Sunil Ravi036cec52023-03-29 11:35:17 -07001704 *ie_offset = token_pos + token_len - data;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001705
Hai Shalomfdcde762020-04-02 11:19:20 -07001706 wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001707 if (!wpa_s->sme.sae_token) {
1708 wpa_dbg(wpa_s, MSG_ERROR,
1709 "SME: Failed to allocate SAE token");
1710 return -1;
1711 }
1712
Hai Shalomfdcde762020-04-02 11:19:20 -07001713 wpa_hexdump_buf(MSG_DEBUG, "SME: Requested anti-clogging token",
1714 wpa_s->sme.sae_token);
Sunil Ravi036cec52023-03-29 11:35:17 -07001715 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001716 sme_send_authentication(wpa_s, wpa_s->current_bss,
Hai Shalom021b0b52019-04-10 11:17:58 -07001717 wpa_s->current_ssid, 2);
Sunil Ravi036cec52023-03-29 11:35:17 -07001718 } else {
1719 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001720 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1721 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001722 return -1;
1723
Roshan Pius3a1667e2018-07-03 15:17:14 -07001724 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001725 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001726 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001727 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001728 return 0;
1729 }
1730
1731 if (auth_transaction == 1 &&
1732 status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1733 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001734 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1735 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001736 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
Hai Shalomc3565922019-10-28 11:58:20 -07001737 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1738 wpa_s->sme.sae.group);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001739 wpa_s->sme.sae_group_index++;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001740 if (sme_set_sae_group(wpa_s, external) < 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001741 return -1; /* no other groups enabled */
1742 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
Sunil Ravi036cec52023-03-29 11:35:17 -07001743 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001744 sme_send_authentication(wpa_s, wpa_s->current_bss,
1745 wpa_s->current_ssid, 1);
Sunil Ravi036cec52023-03-29 11:35:17 -07001746 } else {
1747 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001748 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1749 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001750 return -1;
1751
Roshan Pius3a1667e2018-07-03 15:17:14 -07001752 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001753 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001754 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001755 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001756 return 0;
1757 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001758
Roshan Pius3a1667e2018-07-03 15:17:14 -07001759 if (auth_transaction == 1 &&
1760 status_code == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1761 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1762
1763 wpa_msg(wpa_s, MSG_INFO,
1764 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR,
1765 MAC2STR(bssid));
1766 return -1;
1767 }
1768
Hai Shalomc3565922019-10-28 11:58:20 -07001769 if (status_code != WLAN_STATUS_SUCCESS &&
Hai Shalom899fcc72020-10-19 14:38:18 -07001770 status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08001771 status_code != WLAN_STATUS_SAE_PK) {
1772 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1773
1774 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
1775 " auth_type=%u auth_transaction=%u status_code=%u",
1776 MAC2STR(bssid), WLAN_AUTH_SAE,
1777 auth_transaction, status_code);
Sunil Ravia04bd252022-05-02 22:54:18 -07001778 return -2;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001779 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001780
1781 if (auth_transaction == 1) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07001782 u16 res;
1783
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001784 groups = wpa_s->conf->sae_groups;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001785
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001786 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
Sunil Ravi89eba102022-09-13 21:04:37 -07001787 if ((external && !wpa_s->sme.ext_auth_wpa_ssid) ||
1788 (!external &&
1789 (!wpa_s->current_bss || !wpa_s->current_ssid)))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001790 return -1;
Hai Shalomc3565922019-10-28 11:58:20 -07001791 if (wpa_s->sme.sae.state != SAE_COMMITTED) {
1792 wpa_printf(MSG_DEBUG,
1793 "SAE: Ignore commit message while waiting for confirm");
1794 return 0;
1795 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001796 if (wpa_s->sme.sae.h2e && status_code == WLAN_STATUS_SUCCESS) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001797 wpa_printf(MSG_DEBUG,
1798 "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
1799 return -1;
1800 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001801 if ((!wpa_s->sme.sae.h2e || wpa_s->sme.sae.pk) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001802 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
1803 wpa_printf(MSG_DEBUG,
1804 "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
1805 return -1;
1806 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001807 if (!wpa_s->sme.sae.pk &&
1808 status_code == WLAN_STATUS_SAE_PK) {
1809 wpa_printf(MSG_DEBUG,
1810 "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected");
1811 return -1;
1812 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001813
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001814 if (groups && groups[0] <= 0)
1815 groups = NULL;
Dmitry Shmidt41712582015-06-29 11:02:15 -07001816 res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
Hai Shalomc3565922019-10-28 11:58:20 -07001817 groups, status_code ==
Hai Shalom899fcc72020-10-19 14:38:18 -07001818 WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001819 status_code == WLAN_STATUS_SAE_PK,
1820 ie_offset);
Dmitry Shmidt41712582015-06-29 11:02:15 -07001821 if (res == SAE_SILENTLY_DISCARD) {
1822 wpa_printf(MSG_DEBUG,
1823 "SAE: Drop commit message due to reflection attack");
1824 return 0;
1825 }
1826 if (res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001827 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001828
Hai Shalomc3565922019-10-28 11:58:20 -07001829 if (wpa_s->sme.sae.tmp &&
1830 sme_check_sae_rejected_groups(
1831 wpa_s,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001832 wpa_s->sme.sae.tmp->peer_rejected_groups))
Hai Shalomc3565922019-10-28 11:58:20 -07001833 return -1;
1834
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001835 if (sae_process_commit(&wpa_s->sme.sae) < 0) {
1836 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
1837 "commit");
1838 return -1;
1839 }
1840
1841 wpabuf_free(wpa_s->sme.sae_token);
1842 wpa_s->sme.sae_token = NULL;
Sunil Ravi036cec52023-03-29 11:35:17 -07001843 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001844 sme_send_authentication(wpa_s, wpa_s->current_bss,
1845 wpa_s->current_ssid, 0);
Sunil Ravi036cec52023-03-29 11:35:17 -07001846 } else {
1847 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001848 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1849 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001850 return -1;
1851
Roshan Pius3a1667e2018-07-03 15:17:14 -07001852 sme_external_auth_send_sae_confirm(wpa_s, sa);
Sunil Ravi036cec52023-03-29 11:35:17 -07001853 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001854 return 0;
1855 } else if (auth_transaction == 2) {
Hai Shalomc3565922019-10-28 11:58:20 -07001856 if (status_code != WLAN_STATUS_SUCCESS)
1857 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001858 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001859 if (wpa_s->sme.sae.state != SAE_CONFIRMED)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001860 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001861 if (sae_check_confirm(&wpa_s->sme.sae, data, len,
1862 ie_offset) < 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001863 return -1;
Sunil Ravi036cec52023-03-29 11:35:17 -07001864 if (external && wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001865 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1866 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001867 return -1;
1868
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001869 wpa_s->sme.sae.state = SAE_ACCEPTED;
1870 sae_clear_temp_data(&wpa_s->sme.sae);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001871
1872 if (external) {
1873 /* Report success to driver */
1874 sme_send_external_auth_status(wpa_s,
1875 WLAN_STATUS_SUCCESS);
1876 }
1877
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001878 return 1;
1879 }
1880
1881 return -1;
1882}
Roshan Pius3a1667e2018-07-03 15:17:14 -07001883
1884
Hai Shalomc3565922019-10-28 11:58:20 -07001885static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
1886{
1887 wpa_printf(MSG_DEBUG,
1888 "SME: SAE completed - setting PMK for 4-way handshake");
Sunil Ravi89eba102022-09-13 21:04:37 -07001889 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 -07001890 wpa_s->sme.sae.pmkid, bssid);
1891 if (wpa_s->conf->sae_pmkid_in_assoc) {
1892 /* Update the own RSNE contents now that we have set the PMK
1893 * and added a PMKSA cache entry based on the successfully
1894 * completed SAE exchange. In practice, this will add the PMKID
1895 * into RSNE. */
1896 if (wpa_s->sme.assoc_req_ie_len + 2 + PMKID_LEN >
1897 sizeof(wpa_s->sme.assoc_req_ie)) {
1898 wpa_msg(wpa_s, MSG_WARNING,
1899 "RSN: Not enough room for inserting own PMKID into RSNE");
1900 return -1;
1901 }
1902 if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
1903 &wpa_s->sme.assoc_req_ie_len,
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001904 wpa_s->sme.sae.pmkid, true) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07001905 return -1;
1906 wpa_hexdump(MSG_DEBUG,
1907 "SME: Updated Association Request IEs",
1908 wpa_s->sme.assoc_req_ie,
1909 wpa_s->sme.assoc_req_ie_len);
1910 }
1911
1912 return 0;
1913}
1914
1915
Roshan Pius3a1667e2018-07-03 15:17:14 -07001916void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
1917 const u8 *auth_frame, size_t len)
1918{
1919 const struct ieee80211_mgmt *header;
1920 size_t auth_length;
1921
1922 header = (const struct ieee80211_mgmt *) auth_frame;
1923 auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);
1924
1925 if (len < auth_length) {
1926 /* Notify failure to the driver */
1927 sme_send_external_auth_status(wpa_s,
1928 WLAN_STATUS_UNSPECIFIED_FAILURE);
1929 return;
1930 }
1931
Hai Shalom74f70d42019-02-11 14:42:39 -08001932 if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001933 int res;
Sunil Ravi036cec52023-03-29 11:35:17 -07001934 int ie_offset = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001935
Hai Shalom74f70d42019-02-11 14:42:39 -08001936 res = sme_sae_auth(
1937 wpa_s, le_to_host16(header->u.auth.auth_transaction),
1938 le_to_host16(header->u.auth.status_code),
1939 header->u.auth.variable,
Sunil Ravi036cec52023-03-29 11:35:17 -07001940 len - auth_length, 1, header->sa, &ie_offset);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001941 if (res < 0) {
1942 /* Notify failure to the driver */
1943 sme_send_external_auth_status(
Sunil Ravia04bd252022-05-02 22:54:18 -07001944 wpa_s,
1945 res == -2 ?
1946 le_to_host16(header->u.auth.status_code) :
1947 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001948 return;
1949 }
1950 if (res != 1)
1951 return;
1952
Sunil Ravi036cec52023-03-29 11:35:17 -07001953 if (sme_sae_set_pmk(wpa_s,
1954 wpa_s->sme.ext_ml_auth ?
1955 wpa_s->sme.ext_auth_ap_mld_addr :
1956 wpa_s->sme.ext_auth_bssid) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07001957 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001958 }
1959}
1960
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001961#endif /* CONFIG_SAE */
1962
1963
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001964void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
1965{
1966 struct wpa_ssid *ssid = wpa_s->current_ssid;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001967 int ie_offset = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968
1969 if (ssid == NULL) {
1970 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1971 "when network is not selected");
1972 return;
1973 }
1974
1975 if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
1976 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1977 "when not in authenticating state");
1978 return;
1979 }
1980
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001981 if (!ether_addr_equal(wpa_s->pending_bssid, data->auth.peer) &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001982 !(wpa_s->valid_links &&
Sunil Ravib0ac25f2024-07-12 01:42:03 +00001983 ether_addr_equal(wpa_s->ap_mld_addr, data->auth.peer))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
1985 "unexpected peer " MACSTR,
1986 MAC2STR(data->auth.peer));
1987 return;
1988 }
1989
1990 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001991 " auth_type=%d auth_transaction=%d status_code=%d",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001992 MAC2STR(data->auth.peer), data->auth.auth_type,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001993 data->auth.auth_transaction, data->auth.status_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001994 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
1995 data->auth.ies, data->auth.ies_len);
1996
1997 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
1998
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001999#ifdef CONFIG_SAE
2000 if (data->auth.auth_type == WLAN_AUTH_SAE) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002001 const u8 *addr = wpa_s->pending_bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002002 int res;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002003
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002004 res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
2005 data->auth.status_code, data->auth.ies,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002006 data->auth.ies_len, 0, data->auth.peer,
2007 &ie_offset);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002008 if (res < 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002009 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2010 NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002011 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2012
2013 }
2014 if (res != 1)
2015 return;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002016
Sunil Ravi77d572f2023-01-17 23:58:31 +00002017 if (wpa_s->valid_links)
2018 addr = wpa_s->ap_mld_addr;
2019
2020 if (sme_sae_set_pmk(wpa_s, addr) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002021 return;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002022 }
2023#endif /* CONFIG_SAE */
2024
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002025 if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002026 char *ie_txt = NULL;
2027
2028 if (data->auth.ies && data->auth.ies_len) {
2029 size_t buflen = 2 * data->auth.ies_len + 1;
2030 ie_txt = os_malloc(buflen);
2031 if (ie_txt) {
2032 wpa_snprintf_hex(ie_txt, buflen, data->auth.ies,
2033 data->auth.ies_len);
2034 }
2035 }
2036 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002037 " auth_type=%u auth_transaction=%u status_code=%u%s%s",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002038 MAC2STR(data->auth.peer), data->auth.auth_type,
2039 data->auth.auth_transaction, data->auth.status_code,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002040 ie_txt ? " ie=" : "",
2041 ie_txt ? ie_txt : "");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002042 os_free(ie_txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002043
Hai Shalomce48b4a2018-09-05 11:41:35 -07002044#ifdef CONFIG_FILS
2045 if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
2046 wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS)
2047 fils_connection_failure(wpa_s);
2048#endif /* CONFIG_FILS */
2049
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002050 if (data->auth.status_code !=
2051 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
2052 wpa_s->sme.auth_alg == data->auth.auth_type ||
2053 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002054 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2055 NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002056 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057 return;
2058 }
2059
Dmitry Shmidt97672262014-02-03 13:02:54 -08002060 wpas_connect_work_done(wpa_s);
2061
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002062 switch (data->auth.auth_type) {
2063 case WLAN_AUTH_OPEN:
2064 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
2065
2066 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
2067 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2068 wpa_s->current_ssid);
2069 return;
2070
2071 case WLAN_AUTH_SHARED_KEY:
2072 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
2073
2074 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
2075 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2076 wpa_s->current_ssid);
2077 return;
2078
2079 default:
2080 return;
2081 }
2082 }
2083
2084#ifdef CONFIG_IEEE80211R
2085 if (data->auth.auth_type == WLAN_AUTH_FT) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002086 const u8 *ric_ies = NULL;
2087 size_t ric_ies_len = 0;
2088
2089 if (wpa_s->ric_ies) {
2090 ric_ies = wpabuf_head(wpa_s->ric_ies);
2091 ric_ies_len = wpabuf_len(wpa_s->ric_ies);
2092 }
Dmitry Shmidt41712582015-06-29 11:02:15 -07002093 if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
2094 data->auth.ies_len, 0,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002095 data->auth.peer,
2096 ric_ies, ric_ies_len) < 0) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07002097 wpa_dbg(wpa_s, MSG_DEBUG,
2098 "SME: FT Authentication response processing failed");
2099 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2100 MACSTR
2101 " reason=%d locally_generated=1",
2102 MAC2STR(wpa_s->pending_bssid),
2103 WLAN_REASON_DEAUTH_LEAVING);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002104 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2105 NULL);
Dmitry Shmidt41712582015-06-29 11:02:15 -07002106 wpa_supplicant_mark_disassoc(wpa_s);
2107 return;
2108 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002109 }
2110#endif /* CONFIG_IEEE80211R */
2111
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002112#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002113 if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
2114 data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
2115 u16 expect_auth_type;
2116
2117 expect_auth_type = wpa_s->sme.auth_alg ==
2118 WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
2119 WLAN_AUTH_FILS_SK;
2120 if (data->auth.auth_type != expect_auth_type) {
2121 wpa_dbg(wpa_s, MSG_DEBUG,
2122 "SME: FILS Authentication response used different auth alg (%u; expected %u)",
2123 data->auth.auth_type, expect_auth_type);
2124 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2125 MACSTR
2126 " reason=%d locally_generated=1",
2127 MAC2STR(wpa_s->pending_bssid),
2128 WLAN_REASON_DEAUTH_LEAVING);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002129 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2130 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002131 wpa_supplicant_mark_disassoc(wpa_s);
2132 return;
2133 }
2134
2135 if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
2136 data->auth.ies, data->auth.ies_len) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002137 wpa_dbg(wpa_s, MSG_DEBUG,
2138 "SME: FILS Authentication response processing failed");
2139 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2140 MACSTR
2141 " reason=%d locally_generated=1",
2142 MAC2STR(wpa_s->pending_bssid),
2143 WLAN_REASON_DEAUTH_LEAVING);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002144 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2145 NULL);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002146 wpa_supplicant_mark_disassoc(wpa_s);
2147 return;
2148 }
2149 }
2150#endif /* CONFIG_FILS */
2151
Sunil Ravi77d572f2023-01-17 23:58:31 +00002152 /* TODO: Support additional auth_type values as well */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002153 if ((data->auth.auth_type == WLAN_AUTH_OPEN ||
2154 data->auth.auth_type == WLAN_AUTH_SAE) &&
2155 wpas_sme_ml_auth(wpa_s, data, ie_offset) < 0) {
2156 wpa_dbg(wpa_s, MSG_DEBUG,
2157 "MLD: Failed to parse ML Authentication frame");
2158 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
2159 " reason=%d locally_generated=1",
2160 MAC2STR(wpa_s->pending_bssid),
2161 WLAN_REASON_DEAUTH_LEAVING);
2162 wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
2163 wpa_supplicant_mark_disassoc(wpa_s);
2164 return;
2165 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00002166
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002167 sme_associate(wpa_s, ssid->mode, data->auth.peer,
2168 data->auth.auth_type);
2169}
2170
2171
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002172#ifdef CONFIG_IEEE80211R
2173static void remove_ie(u8 *buf, size_t *len, u8 eid)
2174{
2175 u8 *pos, *next, *end;
2176
2177 pos = (u8 *) get_ie(buf, *len, eid);
2178 if (pos) {
2179 next = pos + 2 + pos[1];
2180 end = buf + *len;
2181 *len -= 2 + pos[1];
2182 os_memmove(pos, next, end - next);
2183 }
2184}
2185#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002186
2187
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002188void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
2189 const u8 *bssid, u16 auth_type)
2190{
2191 struct wpa_driver_associate_params params;
2192 struct ieee802_11_elems elems;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002193 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002194#ifdef CONFIG_FILS
2195 u8 nonces[2 * FILS_NONCE_LEN];
2196#endif /* CONFIG_FILS */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002197#ifdef CONFIG_HT_OVERRIDES
2198 struct ieee80211_ht_capabilities htcaps;
2199 struct ieee80211_ht_capabilities htcaps_mask;
2200#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002201#ifdef CONFIG_VHT_OVERRIDES
2202 struct ieee80211_vht_capabilities vhtcaps;
2203 struct ieee80211_vht_capabilities vhtcaps_mask;
2204#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002205
2206 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002207
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002208 /* Save auth type, in case we need to retry after comeback timer. */
2209 wpa_s->sme.assoc_auth_type = auth_type;
2210
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002211#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002212 if (auth_type == WLAN_AUTH_FILS_SK ||
2213 auth_type == WLAN_AUTH_FILS_SK_PFS) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002214 struct wpabuf *buf;
2215 const u8 *snonce, *anonce;
Paul Stewart092955c2017-02-06 09:13:09 -08002216 const unsigned int max_hlp = 20;
2217 struct wpabuf *hlp[max_hlp];
2218 unsigned int i, num_hlp = 0;
2219 struct fils_hlp_req *req;
2220
2221 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2222 list) {
2223 hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
2224 wpabuf_len(req->pkt));
2225 if (!hlp[num_hlp])
2226 break;
2227 wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
2228 wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
2229 ETH_ALEN);
2230 wpabuf_put_data(hlp[num_hlp],
2231 "\xaa\xaa\x03\x00\x00\x00", 6);
2232 wpabuf_put_buf(hlp[num_hlp], req->pkt);
2233 num_hlp++;
2234 if (num_hlp >= max_hlp)
2235 break;
2236 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002237
2238 buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
2239 &params.fils_kek_len, &snonce,
Paul Stewart092955c2017-02-06 09:13:09 -08002240 &anonce,
2241 (const struct wpabuf **) hlp,
2242 num_hlp);
2243 for (i = 0; i < num_hlp; i++)
2244 wpabuf_free(hlp[i]);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002245 if (!buf)
2246 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002247 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req before FILS elements",
2248 wpa_s->sme.assoc_req_ie,
2249 wpa_s->sme.assoc_req_ie_len);
2250#ifdef CONFIG_IEEE80211R
2251 if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
2252 /* Remove RSNE and MDE to allow them to be overridden
2253 * with FILS+FT specific values from
2254 * fils_build_assoc_req(). */
2255 remove_ie(wpa_s->sme.assoc_req_ie,
2256 &wpa_s->sme.assoc_req_ie_len,
2257 WLAN_EID_RSN);
2258 wpa_hexdump(MSG_DEBUG,
2259 "FILS: assoc_req after RSNE removal",
2260 wpa_s->sme.assoc_req_ie,
2261 wpa_s->sme.assoc_req_ie_len);
2262 remove_ie(wpa_s->sme.assoc_req_ie,
2263 &wpa_s->sme.assoc_req_ie_len,
2264 WLAN_EID_MOBILITY_DOMAIN);
2265 wpa_hexdump(MSG_DEBUG,
2266 "FILS: assoc_req after MDE removal",
2267 wpa_s->sme.assoc_req_ie,
2268 wpa_s->sme.assoc_req_ie_len);
2269 }
2270#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002271 /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
2272 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
2273 sizeof(wpa_s->sme.assoc_req_ie)) {
2274 wpa_printf(MSG_ERROR,
2275 "FILS: Not enough buffer room for own AssocReq elements");
2276 wpabuf_free(buf);
2277 return;
2278 }
2279 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2280 wpabuf_head(buf), wpabuf_len(buf));
2281 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
2282 wpabuf_free(buf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002283 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req after FILS elements",
2284 wpa_s->sme.assoc_req_ie,
2285 wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002286
2287 os_memcpy(nonces, snonce, FILS_NONCE_LEN);
2288 os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
2289 params.fils_nonces = nonces;
2290 params.fils_nonces_len = sizeof(nonces);
2291 }
2292#endif /* CONFIG_FILS */
2293
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002294#ifdef CONFIG_OWE
2295#ifdef CONFIG_TESTING_OPTIONS
2296 if (get_ie_ext(wpa_s->sme.assoc_req_ie, wpa_s->sme.assoc_req_ie_len,
2297 WLAN_EID_EXT_OWE_DH_PARAM)) {
2298 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2299 } else
2300#endif /* CONFIG_TESTING_OPTIONS */
2301 if (auth_type == WLAN_AUTH_OPEN &&
2302 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2303 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002304 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002305
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002306 if (ssid && ssid->owe_group) {
2307 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08002308 } else if (wpa_s->assoc_status_code ==
2309 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002310 if (wpa_s->last_owe_group == 19)
2311 group = 20;
2312 else if (wpa_s->last_owe_group == 20)
2313 group = 21;
2314 else
2315 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002316 } else {
2317 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002318 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002319
Roshan Pius3a1667e2018-07-03 15:17:14 -07002320 wpa_s->last_owe_group = group;
2321 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002322 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2323 if (!owe_ie) {
2324 wpa_printf(MSG_ERROR,
2325 "OWE: Failed to build IE for Association Request frame");
2326 return;
2327 }
2328 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(owe_ie) >
2329 sizeof(wpa_s->sme.assoc_req_ie)) {
2330 wpa_printf(MSG_ERROR,
2331 "OWE: Not enough buffer room for own Association Request frame elements");
2332 wpabuf_free(owe_ie);
2333 return;
2334 }
2335 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2336 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2337 wpa_s->sme.assoc_req_ie_len += wpabuf_len(owe_ie);
2338 wpabuf_free(owe_ie);
2339 }
2340#endif /* CONFIG_OWE */
2341
Hai Shalom021b0b52019-04-10 11:17:58 -07002342#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002343 if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid &&
2344 ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 &&
2345 !ssid->dpp_pfs_fallback) {
2346 struct rsn_pmksa_cache_entry *pmksa;
2347
2348 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2349 if (!pmksa || !pmksa->dpp_pfs)
2350 goto pfs_fail;
Hai Shalom021b0b52019-04-10 11:17:58 -07002351
2352 dpp_pfs_free(wpa_s->dpp_pfs);
2353 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
2354 ssid->dpp_netaccesskey_len);
2355 if (!wpa_s->dpp_pfs) {
2356 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
2357 /* Try to continue without PFS */
2358 goto pfs_fail;
2359 }
2360 if (wpa_s->sme.assoc_req_ie_len +
2361 wpabuf_len(wpa_s->dpp_pfs->ie) >
2362 sizeof(wpa_s->sme.assoc_req_ie)) {
2363 wpa_printf(MSG_ERROR,
2364 "DPP: Not enough buffer room for own Association Request frame elements");
2365 dpp_pfs_free(wpa_s->dpp_pfs);
2366 wpa_s->dpp_pfs = NULL;
2367 goto pfs_fail;
2368 }
2369 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2370 wpabuf_head(wpa_s->dpp_pfs->ie),
2371 wpabuf_len(wpa_s->dpp_pfs->ie));
2372 wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
2373 }
2374pfs_fail:
2375#endif /* CONFIG_DPP2 */
2376
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002377#ifndef CONFIG_NO_ROBUST_AV
Hai Shalom899fcc72020-10-19 14:38:18 -07002378 wpa_s->mscs_setup_done = false;
Hai Shalom60840252021-02-19 19:02:11 -08002379 if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
2380 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002381 struct wpabuf *mscs_ie;
2382 size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len;
2383
Hai Shalom899fcc72020-10-19 14:38:18 -07002384 buf_len = 3 + /* MSCS descriptor IE header */
2385 1 + /* Request type */
2386 2 + /* User priority control */
2387 4 + /* Stream timeout */
2388 3 + /* TCLAS Mask IE header */
2389 wpa_s->robust_av.frame_classifier_len;
2390 mscs_ie = wpabuf_alloc(buf_len);
2391 if (!mscs_ie) {
2392 wpa_printf(MSG_INFO,
2393 "MSCS: Failed to allocate MSCS IE");
2394 goto mscs_fail;
2395 }
2396
2397 wpa_ie_len = &wpa_s->sme.assoc_req_ie_len;
2398 max_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
2399 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
2400 if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) {
2401 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
2402 mscs_ie_len = wpabuf_len(mscs_ie);
2403 os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len,
2404 wpabuf_head(mscs_ie), mscs_ie_len);
2405 *wpa_ie_len += mscs_ie_len;
2406 }
2407
2408 wpabuf_free(mscs_ie);
2409 }
2410mscs_fail:
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002411#endif /* CONFIG_NO_ROBUST_AV */
Hai Shalom899fcc72020-10-19 14:38:18 -07002412
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002413 if (ssid && ssid->multi_ap_backhaul_sta) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002414 size_t multi_ap_ie_len;
Sunil Ravi99c035e2024-07-12 01:42:03 +00002415 struct multi_ap_params multi_ap = { 0 };
2416
2417 multi_ap.capability = MULTI_AP_BACKHAUL_STA;
2418 multi_ap.profile = ssid->multi_ap_profile;
Hai Shalom74f70d42019-02-11 14:42:39 -08002419
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 Ravi99c035e2024-07-12 01:42:03 +00002424 &multi_ap);
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 Ravi99c035e2024-07-12 01:42:03 +00002604 for_each_link(wpa_s->valid_links, i) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002605 params.mld_params.mld_links[i].bssid =
2606 wpa_s->links[i].bssid;
2607 params.mld_params.mld_links[i].freq =
2608 wpa_s->links[i].freq;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002609 params.mld_params.mld_links[i].disabled =
2610 wpa_s->links[i].disabled;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002611
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002612 wpa_printf(MSG_DEBUG,
2613 "MLD: id=%u, freq=%d, disabled=%u, " MACSTR,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002614 i, wpa_s->links[i].freq,
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002615 wpa_s->links[i].disabled,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002616 MAC2STR(wpa_s->links[i].bssid));
2617 }
2618 }
2619
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 if (wpa_drv_associate(wpa_s, &params) < 0) {
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002621 unsigned int n_failed_links = 0;
2622 int i;
2623
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
2625 "driver failed");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002626
2627 /* Prepare list of failed links for error report */
2628 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
2629 if (!(wpa_s->valid_links & BIT(i)) ||
2630 wpa_s->mlo_assoc_link_id == i ||
2631 !params.mld_params.mld_links[i].error)
2632 continue;
2633
2634 wpa_bssid_ignore_add(wpa_s, wpa_s->links[i].bssid);
2635 n_failed_links++;
2636 }
2637
2638 if (n_failed_links) {
2639 /* Deauth and connect (possibly to the same AP MLD) */
2640 wpa_drv_deauthenticate(wpa_s, wpa_s->ap_mld_addr,
2641 WLAN_REASON_DEAUTH_LEAVING);
2642 wpas_connect_work_done(wpa_s);
2643 wpa_supplicant_mark_disassoc(wpa_s);
2644 wpas_request_connection(wpa_s);
2645 } else {
2646 wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2647 NULL);
2648 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2649 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2650 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 return;
2652 }
2653
2654 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
2655 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002656
2657#ifdef CONFIG_TESTING_OPTIONS
2658 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
2659 wpa_s->last_assoc_req_wpa_ie = NULL;
2660 if (params.wpa_ie)
2661 wpa_s->last_assoc_req_wpa_ie =
2662 wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len);
2663#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664}
2665
2666
2667int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
2668 const u8 *ies, size_t ies_len)
2669{
2670 if (md == NULL || ies == NULL) {
2671 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
2672 os_free(wpa_s->sme.ft_ies);
2673 wpa_s->sme.ft_ies = NULL;
2674 wpa_s->sme.ft_ies_len = 0;
2675 wpa_s->sme.ft_used = 0;
2676 return 0;
2677 }
2678
2679 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
2680 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
2681 os_free(wpa_s->sme.ft_ies);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002682 wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002683 if (wpa_s->sme.ft_ies == NULL)
2684 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002685 wpa_s->sme.ft_ies_len = ies_len;
2686 return 0;
2687}
2688
2689
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002690static void sme_deauth(struct wpa_supplicant *wpa_s, const u8 **link_bssids)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691{
2692 int bssid_changed;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002693 const u8 *bssid;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002694
2695 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2696
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002697 if (wpa_s->valid_links)
2698 bssid = wpa_s->ap_mld_addr;
2699 else
2700 bssid = wpa_s->pending_bssid;
2701
2702 if (wpa_drv_deauthenticate(wpa_s, bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002703 WLAN_REASON_DEAUTH_LEAVING) < 0) {
2704 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
2705 "failed");
2706 }
2707 wpa_s->sme.prev_bssid_set = 0;
2708
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002709 wpas_connection_failed(wpa_s, wpa_s->pending_bssid, link_bssids);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002710 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2711 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2712 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2713 if (bssid_changed)
2714 wpas_notify_bssid_changed(wpa_s);
2715}
2716
2717
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002718static void sme_assoc_comeback_timer(void *eloop_ctx, void *timeout_ctx)
Sunil Ravi72e01222024-03-09 01:25:43 +00002719{
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002720 struct wpa_supplicant *wpa_s = eloop_ctx;
2721
2722 if (!wpa_s->current_bss || !wpa_s->current_ssid) {
2723 wpa_msg(wpa_s, MSG_DEBUG,
2724 "SME: Comeback timeout expired; SSID/BSSID cleared; ignoring");
2725 return;
2726 }
2727
2728 wpa_msg(wpa_s, MSG_DEBUG,
2729 "SME: Comeback timeout expired; retry associating with "
2730 MACSTR "; mode=%d auth_type=%u",
2731 MAC2STR(wpa_s->current_bss->bssid),
2732 wpa_s->current_ssid->mode,
2733 wpa_s->sme.assoc_auth_type);
2734
2735 /* Authentication state was completed already; just try association
2736 * again. */
2737 sme_associate(wpa_s, wpa_s->current_ssid->mode,
2738 wpa_s->current_bss->bssid,
2739 wpa_s->sme.assoc_auth_type);
2740}
2741
2742
2743static bool sme_try_assoc_comeback(struct wpa_supplicant *wpa_s,
2744 union wpa_event_data *data)
2745{
2746 struct ieee802_11_elems elems;
2747 u32 timeout_interval;
2748 unsigned long comeback_usec;
2749 u8 type = WLAN_TIMEOUT_ASSOC_COMEBACK;
2750
2751#ifdef CONFIG_TESTING_OPTIONS
2752 if (wpa_s->test_assoc_comeback_type != -1)
2753 type = wpa_s->test_assoc_comeback_type;
2754#endif /* CONFIG_TESTING_OPTIONS */
2755
2756 if (ieee802_11_parse_elems(data->assoc_reject.resp_ies,
2757 data->assoc_reject.resp_ies_len,
2758 &elems, 0) == ParseFailed) {
2759 wpa_msg(wpa_s, MSG_INFO,
2760 "SME: Temporary assoc reject: failed to parse (Re)Association Response frame elements");
2761 return false;
2762 }
2763
2764 if (!elems.timeout_int) {
2765 wpa_msg(wpa_s, MSG_INFO,
2766 "SME: Temporary assoc reject: missing timeout interval IE");
2767 return false;
2768 }
2769
2770 if (elems.timeout_int[0] != type) {
2771 wpa_msg(wpa_s, MSG_INFO,
2772 "SME: Temporary assoc reject: missing association comeback time");
2773 return false;
2774 }
2775
2776 timeout_interval = WPA_GET_LE32(&elems.timeout_int[1]);
2777 if (timeout_interval > 60000) {
2778 /* This is unprotected information and there is no point in
2779 * getting stuck waiting for very long duration based on it */
2780 wpa_msg(wpa_s, MSG_DEBUG,
2781 "SME: Ignore overly long association comeback interval: %u TUs",
2782 timeout_interval);
2783 return false;
2784 }
2785 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association comeback interval: %u TUs",
2786 timeout_interval);
2787
2788 comeback_usec = timeout_interval * 1024;
2789 eloop_register_timeout(comeback_usec / 1000000, comeback_usec % 1000000,
2790 sme_assoc_comeback_timer, wpa_s, NULL);
2791 return true;
2792}
2793
2794
2795void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
2796 union wpa_event_data *data,
2797 const u8 **link_bssids)
2798{
2799 const u8 *bssid;
2800
2801 if (wpa_s->valid_links)
2802 bssid = wpa_s->ap_mld_addr;
2803 else
2804 bssid = wpa_s->pending_bssid;
2805
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
2807 "status code %d", MAC2STR(wpa_s->pending_bssid),
2808 data->assoc_reject.status_code);
2809
2810 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002811 eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
2812
2813 /* Authentication phase has been completed at this point. Check whether
2814 * the AP rejected association temporarily due to still holding a
2815 * security associationis with us (MFP). If so, we must wait for the
2816 * AP's association comeback timeout period before associating again. */
2817 if (data->assoc_reject.status_code ==
2818 WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
2819 wpa_msg(wpa_s, MSG_DEBUG,
2820 "SME: Temporary association reject from BSS " MACSTR,
2821 MAC2STR(bssid));
2822 if (sme_try_assoc_comeback(wpa_s, data)) {
2823 /* Break out early; comeback error is not a failure. */
2824 return;
2825 }
2826 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002827
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002828#ifdef CONFIG_SAE
2829 if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
2830 wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
2831 wpa_dbg(wpa_s, MSG_DEBUG,
2832 "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
2833 wpa_sm_aborted_cached(wpa_s->wpa);
2834 wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
2835 if (wpa_s->current_bss) {
2836 struct wpa_bss *bss = wpa_s->current_bss;
2837 struct wpa_ssid *ssid = wpa_s->current_ssid;
2838
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002839 wpa_drv_deauthenticate(wpa_s, bssid,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002840 WLAN_REASON_DEAUTH_LEAVING);
2841 wpas_connect_work_done(wpa_s);
2842 wpa_supplicant_mark_disassoc(wpa_s);
2843 wpa_supplicant_connect(wpa_s, bss, ssid);
2844 return;
2845 }
2846 }
2847#endif /* CONFIG_SAE */
2848
Sunil Ravi77d572f2023-01-17 23:58:31 +00002849#ifdef CONFIG_DPP
2850 if (wpa_s->current_ssid &&
2851 wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
2852 !data->assoc_reject.timed_out &&
2853 data->assoc_reject.status_code == WLAN_STATUS_INVALID_PMKID) {
2854 struct rsn_pmksa_cache_entry *pmksa;
2855
2856 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2857 if (pmksa) {
2858 wpa_dbg(wpa_s, MSG_DEBUG,
2859 "DPP: Drop PMKSA cache entry for the BSS due to invalid PMKID report");
2860 wpa_sm_pmksa_cache_remove(wpa_s->wpa, pmksa);
2861 }
2862 wpa_sm_aborted_cached(wpa_s->wpa);
2863 if (wpa_s->current_bss) {
2864 struct wpa_bss *bss = wpa_s->current_bss;
2865 struct wpa_ssid *ssid = wpa_s->current_ssid;
2866
2867 wpa_dbg(wpa_s, MSG_DEBUG,
2868 "DPP: Try network introduction again");
2869 wpas_connect_work_done(wpa_s);
2870 wpa_supplicant_mark_disassoc(wpa_s);
2871 wpa_supplicant_connect(wpa_s, bss, ssid);
2872 return;
2873 }
2874 }
2875#endif /* CONFIG_DPP */
2876
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002877 /*
2878 * For now, unconditionally terminate the previous authentication. In
2879 * theory, this should not be needed, but mac80211 gets quite confused
2880 * if the authentication is left pending.. Some roaming cases might
2881 * benefit from using the previous authentication, so this could be
2882 * optimized in the future.
2883 */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002884 sme_deauth(wpa_s, link_bssids);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885}
2886
2887
2888void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
2889 union wpa_event_data *data)
2890{
2891 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002892 wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002893 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002894}
2895
2896
2897void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
2898 union wpa_event_data *data)
2899{
2900 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002901 wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002902 wpa_supplicant_mark_disassoc(wpa_s);
2903}
2904
2905
2906void sme_event_disassoc(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002907 struct disassoc_info *info)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908{
2909 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002910 if (wpa_s->sme.prev_bssid_set) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002911 /*
2912 * cfg80211/mac80211 can get into somewhat confused state if
2913 * the AP only disassociates us and leaves us in authenticated
2914 * state. For now, force the state to be cleared to avoid
2915 * confusing errors if we try to associate with the AP again.
2916 */
2917 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
2918 "driver state");
2919 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
2920 WLAN_REASON_DEAUTH_LEAVING);
2921 }
2922}
2923
2924
2925static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
2926{
2927 struct wpa_supplicant *wpa_s = eloop_ctx;
2928 if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
2929 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002930 sme_deauth(wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002931 }
2932}
2933
2934
2935static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
2936{
2937 struct wpa_supplicant *wpa_s = eloop_ctx;
2938 if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2939 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002940 sme_deauth(wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002941 }
2942}
2943
2944
2945void sme_state_changed(struct wpa_supplicant *wpa_s)
2946{
2947 /* Make sure timers are cleaned up appropriately. */
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002948 if (wpa_s->wpa_state != WPA_ASSOCIATING) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002950 eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
2951 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002952 if (wpa_s->wpa_state != WPA_AUTHENTICATING)
2953 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2954}
2955
2956
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002957void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
2958{
2959 wpa_s->sme.prev_bssid_set = 0;
2960#ifdef CONFIG_SAE
2961 wpabuf_free(wpa_s->sme.sae_token);
2962 wpa_s->sme.sae_token = NULL;
2963 sae_clear_data(&wpa_s->sme.sae);
2964#endif /* CONFIG_SAE */
2965#ifdef CONFIG_IEEE80211R
Roshan Pius3a1667e2018-07-03 15:17:14 -07002966 if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002967 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
2968#endif /* CONFIG_IEEE80211R */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002969 sme_stop_sa_query(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002970}
2971
2972
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002973void sme_deinit(struct wpa_supplicant *wpa_s)
2974{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002975 sme_clear_on_disassoc(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002976#ifdef CONFIG_SAE
2977 os_free(wpa_s->sme.sae_rejected_groups);
2978 wpa_s->sme.sae_rejected_groups = NULL;
2979#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980
2981 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2982 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002983 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
Sunil Ravib0ac25f2024-07-12 01:42:03 +00002984 eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002985}
2986
2987
2988static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
2989 const u8 *chan_list, u8 num_channels,
2990 u8 num_intol)
2991{
2992 struct ieee80211_2040_bss_coex_ie *bc_ie;
2993 struct ieee80211_2040_intol_chan_report *ic_report;
2994 struct wpabuf *buf;
2995
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002996 wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
2997 " (num_channels=%u num_intol=%u)",
2998 MAC2STR(wpa_s->bssid), num_channels, num_intol);
2999 wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
3000 chan_list, num_channels);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003001
3002 buf = wpabuf_alloc(2 + /* action.category + action_code */
3003 sizeof(struct ieee80211_2040_bss_coex_ie) +
3004 sizeof(struct ieee80211_2040_intol_chan_report) +
3005 num_channels);
3006 if (buf == NULL)
3007 return;
3008
3009 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
3010 wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
3011
3012 bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
3013 bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
3014 bc_ie->length = 1;
3015 if (num_intol)
3016 bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
3017
3018 if (num_channels > 0) {
3019 ic_report = wpabuf_put(buf, sizeof(*ic_report));
3020 ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
3021 ic_report->length = num_channels + 1;
3022 ic_report->op_class = 0;
3023 os_memcpy(wpabuf_put(buf, num_channels), chan_list,
3024 num_channels);
3025 }
3026
3027 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3028 wpa_s->own_addr, wpa_s->bssid,
3029 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
3030 wpa_msg(wpa_s, MSG_INFO,
3031 "SME: Failed to send 20/40 BSS Coexistence frame");
3032 }
3033
3034 wpabuf_free(buf);
3035}
3036
3037
Hai Shaloma20dcd72022-02-04 13:43:00 -08003038int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003039{
Hai Shaloma20dcd72022-02-04 13:43:00 -08003040 struct wpa_bss *bss;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003041 const u8 *ie;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003042 u16 ht_cap;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003043 u8 chan_list[P2P_MAX_CHANNELS], channel;
3044 u8 num_channels = 0, num_intol = 0, i;
3045
3046 if (!wpa_s->sme.sched_obss_scan)
3047 return 0;
3048
3049 wpa_s->sme.sched_obss_scan = 0;
3050 if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
3051 return 1;
3052
3053 /*
3054 * Check whether AP uses regulatory triplet or channel triplet in
3055 * country info. Right now the operating class of the BSS channel
3056 * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
3057 * based on the assumption that operating class triplet is not used in
3058 * beacon frame. If the First Channel Number/Operating Extension
3059 * Identifier octet has a positive integer value of 201 or greater,
3060 * then its operating class triplet.
3061 *
3062 * TODO: If Supported Operating Classes element is present in beacon
3063 * frame, have to lookup operating class in Annex E and fill them in
3064 * 2040 coex frame.
3065 */
3066 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
3067 if (ie && (ie[1] >= 6) && (ie[5] >= 201))
3068 return 1;
3069
3070 os_memset(chan_list, 0, sizeof(chan_list));
3071
Hai Shaloma20dcd72022-02-04 13:43:00 -08003072 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08003073 /* Skip other band bss */
Hai Shaloma20dcd72022-02-04 13:43:00 -08003074 enum hostapd_hw_mode mode;
Dmitry Shmidt4b060592013-04-29 16:42:49 -07003075 mode = ieee80211_freq_to_chan(bss->freq, &channel);
3076 if (mode != HOSTAPD_MODE_IEEE80211G &&
3077 mode != HOSTAPD_MODE_IEEE80211B)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003078 continue;
3079
Hai Shaloma20dcd72022-02-04 13:43:00 -08003080 ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
3081 ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
3082 wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
3083 " freq=%u chan=%u ht_cap=0x%x",
3084 MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
3085
3086 if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
3087 if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07003088 num_intol++;
3089
Dmitry Shmidt04949592012-07-19 12:16:46 -07003090 /* Check whether the channel is already considered */
3091 for (i = 0; i < num_channels; i++) {
3092 if (channel == chan_list[i])
3093 break;
3094 }
3095 if (i != num_channels)
3096 continue;
3097
Dmitry Shmidt04949592012-07-19 12:16:46 -07003098 chan_list[num_channels++] = channel;
3099 }
3100 }
3101
3102 sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
3103 return 1;
3104}
3105
3106
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003107static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
3108 struct wpa_driver_scan_params *params)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003109{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003110 /* Include only affected channels */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003111 struct hostapd_hw_modes *mode;
3112 int count, i;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003113 int start, end;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003114
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003115 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08003116 HOSTAPD_MODE_IEEE80211G, false);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003117 if (mode == NULL) {
3118 /* No channels supported in this band - use empty list */
3119 params->freqs = os_zalloc(sizeof(int));
3120 return;
3121 }
3122
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003123 if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
3124 wpa_s->current_bss) {
3125 const u8 *ie;
3126
3127 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
3128 if (ie && ie[1] >= 2) {
3129 u8 o;
3130
3131 o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
3132 if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
3133 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
3134 else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
3135 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
3136 }
3137 }
3138
3139 start = wpa_s->assoc_freq - 10;
3140 end = wpa_s->assoc_freq + 10;
3141 switch (wpa_s->sme.ht_sec_chan) {
3142 case HT_SEC_CHAN_UNKNOWN:
3143 /* HT40+ possible on channels 1..9 */
3144 if (wpa_s->assoc_freq <= 2452)
3145 start -= 20;
3146 /* HT40- possible on channels 5-13 */
3147 if (wpa_s->assoc_freq >= 2432)
3148 end += 20;
3149 break;
3150 case HT_SEC_CHAN_ABOVE:
3151 end += 20;
3152 break;
3153 case HT_SEC_CHAN_BELOW:
3154 start -= 20;
3155 break;
3156 }
3157 wpa_printf(MSG_DEBUG,
3158 "OBSS: assoc_freq %d possible affected range %d-%d",
3159 wpa_s->assoc_freq, start, end);
3160
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003161 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
Dmitry Shmidt04949592012-07-19 12:16:46 -07003162 if (params->freqs == NULL)
3163 return;
3164 for (count = 0, i = 0; i < mode->num_channels; i++) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003165 int freq;
3166
Dmitry Shmidt04949592012-07-19 12:16:46 -07003167 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
3168 continue;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003169 freq = mode->channels[i].freq;
3170 if (freq - 10 >= end || freq + 10 <= start)
3171 continue; /* not affected */
3172 params->freqs[count++] = freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003173 }
3174}
3175
3176
3177static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
3178{
3179 struct wpa_supplicant *wpa_s = eloop_ctx;
3180 struct wpa_driver_scan_params params;
3181
3182 if (!wpa_s->current_bss) {
3183 wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
3184 return;
3185 }
3186
3187 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003188 wpa_obss_scan_freqs_list(wpa_s, &params);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003189 params.low_priority = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003190 wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
3191
Sunil Ravi2a14cf12023-11-21 00:54:38 +00003192 if (wpa_supplicant_trigger_scan(wpa_s, &params, true, false))
Dmitry Shmidt04949592012-07-19 12:16:46 -07003193 wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
3194 else
3195 wpa_s->sme.sched_obss_scan = 1;
3196 os_free(params.freqs);
3197
3198 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3199 sme_obss_scan_timeout, wpa_s, NULL);
3200}
3201
3202
3203void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
3204{
3205 const u8 *ie;
3206 struct wpa_bss *bss = wpa_s->current_bss;
3207 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003208 struct hostapd_hw_modes *hw_mode = NULL;
3209 int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003210
3211 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
3212 wpa_s->sme.sched_obss_scan = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003213 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003214 if (!enable)
3215 return;
3216
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003217 /*
3218 * Schedule OBSS scan if driver is using station SME in wpa_supplicant
3219 * or it expects OBSS scan to be performed by wpa_supplicant.
3220 */
3221 if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
3222 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
Hai Shalom81f62d82019-07-22 12:10:00 -07003223 ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003224 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003225
Hai Shaloma20dcd72022-02-04 13:43:00 -08003226#ifdef CONFIG_HT_OVERRIDES
3227 /* No need for OBSS scan if HT40 is explicitly disabled */
3228 if (ssid->disable_ht40)
3229 return;
3230#endif /* CONFIG_HT_OVERRIDES */
3231
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003232 if (!wpa_s->hw.modes)
3233 return;
3234
3235 /* only HT caps in 11g mode are relevant */
3236 for (i = 0; i < wpa_s->hw.num_modes; i++) {
3237 hw_mode = &wpa_s->hw.modes[i];
3238 if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
3239 break;
3240 }
3241
3242 /* Driver does not support HT40 for 11g or doesn't have 11g. */
3243 if (i == wpa_s->hw.num_modes || !hw_mode ||
3244 !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3245 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003246
3247 if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
3248 return; /* Not associated on 2.4 GHz band */
3249
3250 /* Check whether AP supports HT40 */
3251 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
3252 if (!ie || ie[1] < 2 ||
3253 !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3254 return; /* AP does not support HT40 */
3255
3256 ie = wpa_bss_get_ie(wpa_s->current_bss,
3257 WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
3258 if (!ie || ie[1] < 14)
3259 return; /* AP does not request OBSS scans */
3260
3261 wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
3262 if (wpa_s->sme.obss_scan_int < 10) {
3263 wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
3264 "replaced with the minimum 10 sec",
3265 wpa_s->sme.obss_scan_int);
3266 wpa_s->sme.obss_scan_int = 10;
3267 }
3268 wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
3269 wpa_s->sme.obss_scan_int);
3270 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3271 sme_obss_scan_timeout, wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003272}
3273
3274
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003275static const unsigned int sa_query_max_timeout = 1000;
3276static const unsigned int sa_query_retry_timeout = 201;
Hai Shalom74f70d42019-02-11 14:42:39 -08003277static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003278
3279static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
3280{
3281 u32 tu;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003282 struct os_reltime now, passed;
3283 os_get_reltime(&now);
3284 os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003285 tu = (passed.sec * 1000000 + passed.usec) / 1024;
3286 if (sa_query_max_timeout < tu) {
3287 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
3288 sme_stop_sa_query(wpa_s);
3289 wpa_supplicant_deauthenticate(
3290 wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
3291 return 1;
3292 }
3293
3294 return 0;
3295}
3296
3297
3298static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
3299 const u8 *trans_id)
3300{
Hai Shalom74f70d42019-02-11 14:42:39 -08003301 u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3302 u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3303
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003304 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
3305 MACSTR, MAC2STR(wpa_s->bssid));
3306 wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
3307 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
3308 req[0] = WLAN_ACTION_SA_QUERY;
3309 req[1] = WLAN_SA_QUERY_REQUEST;
3310 os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08003311
3312#ifdef CONFIG_OCV
3313 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3314 struct wpa_channel_info ci;
3315
3316 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3317 wpa_printf(MSG_WARNING,
3318 "Failed to get channel info for OCI element in SA Query Request frame");
3319 return;
3320 }
3321
Hai Shalom899fcc72020-10-19 14:38:18 -07003322#ifdef CONFIG_TESTING_OPTIONS
3323 if (wpa_s->oci_freq_override_saquery_req) {
3324 wpa_printf(MSG_INFO,
3325 "TEST: Override SA Query Request OCI frequency %d -> %d MHz",
3326 ci.frequency,
3327 wpa_s->oci_freq_override_saquery_req);
3328 ci.frequency = wpa_s->oci_freq_override_saquery_req;
3329 }
3330#endif /* CONFIG_TESTING_OPTIONS */
3331
Hai Shalom74f70d42019-02-11 14:42:39 -08003332 if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
3333 return;
3334
3335 req_len += OCV_OCI_EXTENDED_LEN;
3336 }
3337#endif /* CONFIG_OCV */
3338
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003339 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3340 wpa_s->own_addr, wpa_s->bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08003341 req, req_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
3343 "Request");
3344}
3345
3346
3347static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
3348{
3349 struct wpa_supplicant *wpa_s = eloop_ctx;
3350 unsigned int timeout, sec, usec;
3351 u8 *trans_id, *nbuf;
3352
3353 if (wpa_s->sme.sa_query_count > 0 &&
3354 sme_check_sa_query_timeout(wpa_s))
3355 return;
3356
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003357 nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
3358 wpa_s->sme.sa_query_count + 1,
3359 WLAN_SA_QUERY_TR_ID_LEN);
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003360 if (nbuf == NULL) {
3361 sme_stop_sa_query(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003362 return;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003363 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003364 if (wpa_s->sme.sa_query_count == 0) {
3365 /* Starting a new SA Query procedure */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003366 os_get_reltime(&wpa_s->sme.sa_query_start);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003367 }
3368 trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
3369 wpa_s->sme.sa_query_trans_id = nbuf;
3370 wpa_s->sme.sa_query_count++;
3371
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003372 if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
3373 wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003374 sme_stop_sa_query(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003375 return;
3376 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003377
3378 timeout = sa_query_retry_timeout;
3379 sec = ((timeout / 1000) * 1024) / 1000;
3380 usec = (timeout % 1000) * 1024;
3381 eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
3382
3383 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
3384 wpa_s->sme.sa_query_count);
3385
3386 sme_send_sa_query_req(wpa_s, trans_id);
3387}
3388
3389
3390static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
3391{
3392 sme_sa_query_timer(wpa_s, NULL);
3393}
3394
3395
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003396static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003397{
Hai Shalom5f92bc92019-04-18 11:54:11 -07003398 if (wpa_s->sme.sa_query_trans_id)
3399 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003400 eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
3401 os_free(wpa_s->sme.sa_query_trans_id);
3402 wpa_s->sme.sa_query_trans_id = NULL;
3403 wpa_s->sme.sa_query_count = 0;
3404}
3405
3406
3407void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
3408 const u8 *da, u16 reason_code)
3409{
3410 struct wpa_ssid *ssid;
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003411 struct os_reltime now;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003412
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003413 if (wpa_s->wpa_state != WPA_COMPLETED)
3414 return;
3415 ssid = wpa_s->current_ssid;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003416 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003417 return;
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003418 if (!ether_addr_equal(sa, wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003419 return;
3420 if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
3421 reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
3422 return;
3423 if (wpa_s->sme.sa_query_count > 0)
3424 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07003425#ifdef CONFIG_TESTING_OPTIONS
3426 if (wpa_s->disable_sa_query)
3427 return;
3428#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003429
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003430 os_get_reltime(&now);
3431 if (wpa_s->sme.last_unprot_disconnect.sec &&
3432 !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
3433 return; /* limit SA Query procedure frequency */
3434 wpa_s->sme.last_unprot_disconnect = now;
3435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003436 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
3437 "possible AP/STA state mismatch - trigger SA Query");
3438 sme_start_sa_query(wpa_s);
3439}
3440
3441
Hai Shalom74f70d42019-02-11 14:42:39 -08003442void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
3443{
3444 unsigned int usec;
3445 u32 _rand;
3446
3447 if (wpa_s->wpa_state != WPA_COMPLETED ||
3448 !wpa_sm_ocv_enabled(wpa_s->wpa))
3449 return;
3450
3451 wpa_dbg(wpa_s, MSG_DEBUG,
3452 "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
3453 sme_stop_sa_query(wpa_s);
3454
3455 if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
3456 _rand = os_random();
3457 usec = _rand % (sa_query_ch_switch_max_delay + 1);
3458 eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
3459}
3460
3461
3462static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
3463 const u8 *sa, const u8 *data,
3464 size_t len)
3465{
3466 u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3467 u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3468
3469 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
3470 MACSTR, MAC2STR(wpa_s->bssid));
3471
3472 resp[0] = WLAN_ACTION_SA_QUERY;
3473 resp[1] = WLAN_SA_QUERY_RESPONSE;
3474 os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
3475
3476#ifdef CONFIG_OCV
3477 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3478 struct wpa_channel_info ci;
3479
3480 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3481 wpa_printf(MSG_WARNING,
3482 "Failed to get channel info for OCI element in SA Query Response frame");
3483 return;
3484 }
3485
Hai Shalom899fcc72020-10-19 14:38:18 -07003486#ifdef CONFIG_TESTING_OPTIONS
3487 if (wpa_s->oci_freq_override_saquery_resp) {
3488 wpa_printf(MSG_INFO,
3489 "TEST: Override SA Query Response OCI frequency %d -> %d MHz",
3490 ci.frequency,
3491 wpa_s->oci_freq_override_saquery_resp);
3492 ci.frequency = wpa_s->oci_freq_override_saquery_resp;
3493 }
3494#endif /* CONFIG_TESTING_OPTIONS */
3495
Hai Shalom74f70d42019-02-11 14:42:39 -08003496 if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
3497 return;
3498
3499 resp_len += OCV_OCI_EXTENDED_LEN;
3500 }
3501#endif /* CONFIG_OCV */
3502
3503 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3504 wpa_s->own_addr, wpa_s->bssid,
3505 resp, resp_len, 0) < 0)
3506 wpa_msg(wpa_s, MSG_INFO,
3507 "SME: Failed to send SA Query Response");
3508}
3509
3510
3511static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
3512 const u8 *sa, const u8 *data,
3513 size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003514{
3515 int i;
3516
Hai Shalom74f70d42019-02-11 14:42:39 -08003517 if (!wpa_s->sme.sa_query_trans_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003518 return;
Hai Shalom74f70d42019-02-11 14:42:39 -08003519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003520 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
3521 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3522
Sunil Ravib0ac25f2024-07-12 01:42:03 +00003523 if (!ether_addr_equal(sa, wpa_s->bssid))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003524 return;
3525
3526 for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
3527 if (os_memcmp(wpa_s->sme.sa_query_trans_id +
3528 i * WLAN_SA_QUERY_TR_ID_LEN,
3529 data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
3530 break;
3531 }
3532
3533 if (i >= wpa_s->sme.sa_query_count) {
3534 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
3535 "transaction identifier found");
3536 return;
3537 }
3538
3539 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
3540 "from " MACSTR, MAC2STR(sa));
3541 sme_stop_sa_query(wpa_s);
3542}
3543
Hai Shalom74f70d42019-02-11 14:42:39 -08003544
Hai Shaloma20dcd72022-02-04 13:43:00 -08003545void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
Hai Shalom74f70d42019-02-11 14:42:39 -08003546 const u8 *data, size_t len)
3547{
3548 if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
3549 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003550 if (is_multicast_ether_addr(da)) {
3551 wpa_printf(MSG_DEBUG,
3552 "IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
3553 MAC2STR(da), MAC2STR(sa));
3554 return;
3555 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003556
3557 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
3558 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3559
3560#ifdef CONFIG_OCV
3561 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3562 struct ieee802_11_elems elems;
3563 struct wpa_channel_info ci;
3564
3565 if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
3566 len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
3567 &elems, 1) == ParseFailed) {
3568 wpa_printf(MSG_DEBUG,
3569 "SA Query: Failed to parse elements");
3570 return;
3571 }
3572
3573 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3574 wpa_printf(MSG_WARNING,
3575 "Failed to get channel info to validate received OCI in SA Query Action frame");
3576 return;
3577 }
3578
3579 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
3580 channel_width_to_int(ci.chanwidth),
Hai Shalom899fcc72020-10-19 14:38:18 -07003581 ci.seg1_idx) != OCI_SUCCESS) {
3582 wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR
3583 " frame=saquery%s error=%s",
3584 MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ?
3585 "req" : "resp", ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003586 return;
3587 }
3588 }
3589#endif /* CONFIG_OCV */
3590
3591 if (data[0] == WLAN_SA_QUERY_REQUEST)
3592 sme_process_sa_query_request(wpa_s, sa, data, len);
3593 else if (data[0] == WLAN_SA_QUERY_RESPONSE)
3594 sme_process_sa_query_response(wpa_s, sa, data, len);
3595}