blob: ea4023c8c89f161a25bb0ef21cfcd95c1b1c1e95 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * wpa_supplicant - SME
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003 * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "utils/eloop.h"
Sunil Ravi77d572f2023-01-17 23:58:31 +000013#include "utils/ext_password.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#include "common/ieee802_11_defs.h"
15#include "common/ieee802_11_common.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080016#include "common/ocv.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070017#include "eapol_supp/eapol_supp_sm.h"
18#include "common/wpa_common.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080019#include "common/sae.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070020#include "common/dpp.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "rsn_supp/wpa.h"
22#include "rsn_supp/pmksa_cache.h"
23#include "config.h"
24#include "wpa_supplicant_i.h"
25#include "driver_i.h"
26#include "wpas_glue.h"
27#include "wps_supplicant.h"
28#include "p2p_supplicant.h"
29#include "notify.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "bss.h"
31#include "scan.h"
32#include "sme.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070033#include "hs20_supplicant.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034
35#define SME_AUTH_TIMEOUT 5
36#define SME_ASSOC_TIMEOUT 5
37
38static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
39static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt04949592012-07-19 12:16:46 -070040static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042
43
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080044#ifdef CONFIG_SAE
45
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080046static int index_within_array(const int *array, int idx)
47{
48 int i;
49 for (i = 0; i < idx; i++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -080050 if (array[i] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080051 return 0;
52 }
53 return 1;
54}
55
56
Sunil Ravi77d572f2023-01-17 23:58:31 +000057static int sme_set_sae_group(struct wpa_supplicant *wpa_s, bool external)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080058{
59 int *groups = wpa_s->conf->sae_groups;
Hai Shalom021b0b52019-04-10 11:17:58 -070060 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080061
Dmitry Shmidtcce06662013-11-04 18:44:24 -080062 if (!groups || groups[0] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080063 groups = default_groups;
64
65 /* Configuration may have changed, so validate current index */
66 if (!index_within_array(groups, wpa_s->sme.sae_group_index))
67 return -1;
68
69 for (;;) {
70 int group = groups[wpa_s->sme.sae_group_index];
Dmitry Shmidt41712582015-06-29 11:02:15 -070071 if (group <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080072 break;
73 if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
74 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
75 wpa_s->sme.sae.group);
Sunil Ravi77d572f2023-01-17 23:58:31 +000076 wpa_s->sme.sae.akmp = external ?
77 wpa_s->sme.ext_auth_key_mgmt : wpa_s->key_mgmt;
Hai Shalom74f70d42019-02-11 14:42:39 -080078 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080079 }
80 wpa_s->sme.sae_group_index++;
81 }
82
83 return -1;
84}
85
86
87static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
88 struct wpa_ssid *ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +000089 const u8 *bssid,
90 const u8 *mld_addr,
91 int external,
Hai Shalom899fcc72020-10-19 14:38:18 -070092 int reuse, int *ret_use_pt,
93 bool *ret_use_pk)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080094{
95 struct wpabuf *buf;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080096 size_t len;
Sunil Ravi77d572f2023-01-17 23:58:31 +000097 char *password = NULL;
Hai Shalomc3565922019-10-28 11:58:20 -070098 struct wpa_bss *bss;
99 int use_pt = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700100 bool use_pk = false;
101 u8 rsnxe_capa = 0;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000102 int key_mgmt = external ? wpa_s->sme.ext_auth_key_mgmt :
103 wpa_s->key_mgmt;
104 const u8 *addr = mld_addr ? mld_addr : bssid;
Hai Shalomc3565922019-10-28 11:58:20 -0700105
106 if (ret_use_pt)
107 *ret_use_pt = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700108 if (ret_use_pk)
109 *ret_use_pk = false;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800110
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700111#ifdef CONFIG_TESTING_OPTIONS
112 if (wpa_s->sae_commit_override) {
113 wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
114 buf = wpabuf_alloc(4 + wpabuf_len(wpa_s->sae_commit_override));
115 if (!buf)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000116 goto fail;
Hai Shalom021b0b52019-04-10 11:17:58 -0700117 if (!external) {
118 wpabuf_put_le16(buf, 1); /* Transaction seq# */
119 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
120 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700121 wpabuf_put_buf(buf, wpa_s->sae_commit_override);
122 return buf;
123 }
124#endif /* CONFIG_TESTING_OPTIONS */
125
Sunil Ravi77d572f2023-01-17 23:58:31 +0000126 if (ssid->sae_password) {
127 password = os_strdup(ssid->sae_password);
128 if (!password) {
129 wpa_dbg(wpa_s, MSG_INFO,
130 "SAE: Failed to allocate password");
131 goto fail;
132 }
133 }
134 if (!password && ssid->passphrase) {
135 password = os_strdup(ssid->passphrase);
136 if (!password) {
137 wpa_dbg(wpa_s, MSG_INFO,
138 "SAE: Failed to allocate password");
139 goto fail;
140 }
141 }
142 if (!password && ssid->ext_psk) {
143 struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
144 ssid->ext_psk);
145
146 if (!pw) {
147 wpa_msg(wpa_s, MSG_INFO,
148 "SAE: No password found from external storage");
149 goto fail;
150 }
151
152 password = os_malloc(wpabuf_len(pw) + 1);
153 if (!password) {
154 wpa_dbg(wpa_s, MSG_INFO,
155 "SAE: Failed to allocate password");
156 goto fail;
157 }
158 os_memcpy(password, wpabuf_head(pw), wpabuf_len(pw));
159 password[wpabuf_len(pw)] = '\0';
160 ext_password_free(pw);
161 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700162 if (!password) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800163 wpa_printf(MSG_DEBUG, "SAE: No password available");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000164 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800165 }
166
Hai Shalom021b0b52019-04-10 11:17:58 -0700167 if (reuse && wpa_s->sme.sae.tmp &&
Sunil Ravi77d572f2023-01-17 23:58:31 +0000168 os_memcmp(addr, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700169 wpa_printf(MSG_DEBUG,
170 "SAE: Reuse previously generated PWE on a retry with the same AP");
Hai Shalom899fcc72020-10-19 14:38:18 -0700171 use_pt = wpa_s->sme.sae.h2e;
172 use_pk = wpa_s->sme.sae.pk;
Hai Shalom021b0b52019-04-10 11:17:58 -0700173 goto reuse_data;
174 }
Sunil Ravi77d572f2023-01-17 23:58:31 +0000175 if (sme_set_sae_group(wpa_s, external) < 0) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800176 wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000177 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800178 }
179
Hai Shalom899fcc72020-10-19 14:38:18 -0700180 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800181 if (!bss) {
182 wpa_printf(MSG_DEBUG,
183 "SAE: BSS not available, update scan result to get BSS");
184 wpa_supplicant_update_scan_results(wpa_s);
185 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
186 }
Hai Shalom899fcc72020-10-19 14:38:18 -0700187 if (bss) {
188 const u8 *rsnxe;
189
190 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
191 if (rsnxe && rsnxe[1] >= 1)
192 rsnxe_capa = rsnxe[2];
193 }
194
Sunil Ravi77d572f2023-01-17 23:58:31 +0000195 if (ssid->sae_password_id &&
196 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Hai Shalomfdcde762020-04-02 11:19:20 -0700197 use_pt = 1;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000198 if (wpa_key_mgmt_sae_ext_key(key_mgmt) &&
199 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
Sunil Ravi89eba102022-09-13 21:04:37 -0700200 use_pt = 1;
Sunil Ravi036cec52023-03-29 11:35:17 -0700201 if (bss && is_6ghz_freq(bss->freq) &&
202 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
203 use_pt = 1;
Hai Shalom899fcc72020-10-19 14:38:18 -0700204#ifdef CONFIG_SAE_PK
205 if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
206 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
207 ((ssid->sae_password &&
208 sae_pk_valid_password(ssid->sae_password)) ||
209 (!ssid->sae_password && ssid->passphrase &&
210 sae_pk_valid_password(ssid->passphrase)))) {
211 use_pt = 1;
212 use_pk = true;
213 }
214
215 if (ssid->sae_pk == SAE_PK_MODE_ONLY && !use_pk) {
216 wpa_printf(MSG_DEBUG,
217 "SAE: Cannot use PK with the selected AP");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000218 goto fail;
Hai Shalom899fcc72020-10-19 14:38:18 -0700219 }
220#endif /* CONFIG_SAE_PK */
Hai Shalomfdcde762020-04-02 11:19:20 -0700221
Sunil Ravi77d572f2023-01-17 23:58:31 +0000222 if (use_pt || wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
223 wpa_s->conf->sae_pwe == SAE_PWE_BOTH) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700224 use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
Hai Shalomc3565922019-10-28 11:58:20 -0700225
Sunil Ravi77d572f2023-01-17 23:58:31 +0000226 if ((wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
227 ssid->sae_password_id ||
228 wpa_key_mgmt_sae_ext_key(key_mgmt)) &&
229 wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
Hai Shalomfdcde762020-04-02 11:19:20 -0700230 !use_pt) {
Hai Shalomc3565922019-10-28 11:58:20 -0700231 wpa_printf(MSG_DEBUG,
232 "SAE: Cannot use H2E with the selected AP");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000233 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -0700234 }
235 }
236
Sunil Ravi036cec52023-03-29 11:35:17 -0700237 if (use_pt && !ssid->pt)
238 wpa_s_setup_sae_pt(wpa_s->conf, ssid, true);
Hai Shalomc3565922019-10-28 11:58:20 -0700239 if (use_pt &&
240 sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000241 wpa_s->own_addr, addr,
Hai Shalom899fcc72020-10-19 14:38:18 -0700242 wpa_s->sme.sae_rejected_groups, NULL) < 0)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000243 goto fail;
Hai Shalomc3565922019-10-28 11:58:20 -0700244 if (!use_pt &&
245 sae_prepare_commit(wpa_s->own_addr, bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700246 (u8 *) password, os_strlen(password),
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800247 &wpa_s->sme.sae) < 0) {
248 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
Sunil Ravi77d572f2023-01-17 23:58:31 +0000249 goto fail;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800250 }
Hai Shalom899fcc72020-10-19 14:38:18 -0700251 if (wpa_s->sme.sae.tmp) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000252 os_memcpy(wpa_s->sme.sae.tmp->bssid, addr, ETH_ALEN);
Hai Shalom899fcc72020-10-19 14:38:18 -0700253 if (use_pt && use_pk)
254 wpa_s->sme.sae.pk = 1;
255#ifdef CONFIG_SAE_PK
256 os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr,
257 ETH_ALEN);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000258 os_memcpy(wpa_s->sme.sae.tmp->peer_addr, addr, ETH_ALEN);
Hai Shalom899fcc72020-10-19 14:38:18 -0700259 sae_pk_set_password(&wpa_s->sme.sae, password);
260#endif /* CONFIG_SAE_PK */
261 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800262
Hai Shalom021b0b52019-04-10 11:17:58 -0700263reuse_data:
Hai Shalomfdcde762020-04-02 11:19:20 -0700264 len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700265 if (ssid->sae_password_id)
266 len += 4 + os_strlen(ssid->sae_password_id);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800267 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800268 if (buf == NULL)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000269 goto fail;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700270 if (!external) {
271 wpabuf_put_le16(buf, 1); /* Transaction seq# */
Hai Shalom899fcc72020-10-19 14:38:18 -0700272 if (use_pk)
273 wpabuf_put_le16(buf, WLAN_STATUS_SAE_PK);
274 else if (use_pt)
275 wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
276 else
277 wpabuf_put_le16(buf,WLAN_STATUS_SUCCESS);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700278 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700279 if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
280 ssid->sae_password_id) < 0) {
281 wpabuf_free(buf);
Sunil Ravi77d572f2023-01-17 23:58:31 +0000282 goto fail;
Hai Shalomfdcde762020-04-02 11:19:20 -0700283 }
Hai Shalomc3565922019-10-28 11:58:20 -0700284 if (ret_use_pt)
285 *ret_use_pt = use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -0700286 if (ret_use_pk)
287 *ret_use_pk = use_pk;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800288
Sunil Ravi77d572f2023-01-17 23:58:31 +0000289 str_clear_free(password);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800290 return buf;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000291
292fail:
293 str_clear_free(password);
294 return NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800295}
296
297
Roshan Pius3a1667e2018-07-03 15:17:14 -0700298static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s,
299 int external)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800300{
301 struct wpabuf *buf;
302
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800303 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800304 if (buf == NULL)
305 return NULL;
306
Roshan Pius3a1667e2018-07-03 15:17:14 -0700307 if (!external) {
308 wpabuf_put_le16(buf, 2); /* Transaction seq# */
309 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
310 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800311 sae_write_confirm(&wpa_s->sme.sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800312
313 return buf;
314}
315
316#endif /* CONFIG_SAE */
317
318
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800319/**
320 * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt
321 * @wpa_s: Pointer to wpa_supplicant data
322 * @bss: Pointer to the bss which is the target of authentication attempt
323 */
324static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
325 struct wpa_bss *bss)
326{
327 const u8 rrm_ie_len = 5;
328 u8 *pos;
329 const u8 *rrm_ie;
330
331 wpa_s->rrm.rrm_used = 0;
332
333 wpa_printf(MSG_DEBUG,
334 "RRM: Determining whether RRM can be used - device support: 0x%x",
335 wpa_s->drv_rrm_flags);
336
337 rrm_ie = wpa_bss_get_ie(bss, WLAN_EID_RRM_ENABLED_CAPABILITIES);
338 if (!rrm_ie || !(bss->caps & IEEE80211_CAP_RRM)) {
339 wpa_printf(MSG_DEBUG, "RRM: No RRM in network");
340 return;
341 }
342
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700343 if (!((wpa_s->drv_rrm_flags &
344 WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
345 (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
346 !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800347 wpa_printf(MSG_DEBUG,
348 "RRM: Insufficient RRM support in driver - do not use RRM");
349 return;
350 }
351
352 if (sizeof(wpa_s->sme.assoc_req_ie) <
353 wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) {
354 wpa_printf(MSG_INFO,
355 "RRM: Unable to use RRM, no room for RRM IE");
356 return;
357 }
358
359 wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to Association Request");
360 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
361 os_memset(pos, 0, 2 + rrm_ie_len);
362 *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
363 *pos++ = rrm_ie_len;
364
Hai Shalom60840252021-02-19 19:02:11 -0800365 /* Set supported capabilities flags */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800366 if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
367 *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
368
Dmitry Shmidt29333592017-01-09 12:27:11 -0800369 *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
370 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
371 WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
372
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700373 if (wpa_s->lci)
374 pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
375
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800376 wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
377 wpa_s->rrm.rrm_used = 1;
378}
379
380
Sunil Ravi77d572f2023-01-17 23:58:31 +0000381static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
382{
383 struct wpabuf *mlbuf;
384 const u8 *rnr_ie, *pos;
385 u8 ml_ie_len, rnr_ie_len;
386 const struct ieee80211_eht_ml *eht_ml;
387 const struct eht_ml_basic_common_info *ml_basic_common_info;
388 u8 i;
389 const u16 control =
390 host_to_le16(MULTI_LINK_CONTROL_TYPE_BASIC |
391 BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
392 BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
393 BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA);
394 bool ret = false;
395
396 if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO))
397 return false;
398
399 mlbuf = wpa_bss_defrag_mle(bss, MULTI_LINK_CONTROL_TYPE_BASIC);
400 if (!mlbuf) {
401 wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No ML element");
402 return false;
403 }
404
405 ml_ie_len = wpabuf_len(mlbuf);
406
407 /* control + common info len + MLD address + MLD link information */
408 if (ml_ie_len < 2 + 1 + ETH_ALEN + 1)
409 goto out;
410
411 eht_ml = wpabuf_head(mlbuf);
412 if ((eht_ml->ml_control & control) != control) {
413 wpa_printf(MSG_DEBUG, "MLD: Unexpected ML element control=0x%x",
414 eht_ml->ml_control);
415 goto out;
416 }
417
418 ml_basic_common_info =
419 (const struct eht_ml_basic_common_info *) eht_ml->variable;
420
421 /* common info length should be valid (self, mld_addr, link_id) */
422 if (ml_basic_common_info->len < 1 + ETH_ALEN + 1)
423 goto out;
424
425 /* get the MLD address and MLD link ID */
426 os_memcpy(wpa_s->ap_mld_addr, ml_basic_common_info->mld_addr,
427 ETH_ALEN);
428 wpa_s->mlo_assoc_link_id = ml_basic_common_info->variable[0] &
429 EHT_ML_LINK_ID_MSK;
430
431 os_memcpy(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid, bss->bssid,
432 ETH_ALEN);
433 wpa_s->links[wpa_s->mlo_assoc_link_id].freq = bss->freq;
434
435 wpa_printf(MSG_DEBUG, "MLD: address=" MACSTR ", link ID=%u",
436 MAC2STR(wpa_s->ap_mld_addr), wpa_s->mlo_assoc_link_id);
437
438 wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
439
440 rnr_ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
441 if (!rnr_ie) {
442 wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RNR element");
443 ret = true;
444 goto out;
445 }
446
447 rnr_ie_len = rnr_ie[1];
448 pos = rnr_ie + 2;
449
450 while (rnr_ie_len > sizeof(struct ieee80211_neighbor_ap_info)) {
451 const struct ieee80211_neighbor_ap_info *ap_info =
452 (const struct ieee80211_neighbor_ap_info *) pos;
453 const u8 *data = ap_info->data;
454 size_t len = sizeof(struct ieee80211_neighbor_ap_info) +
455 ap_info->tbtt_info_len;
456
457 wpa_printf(MSG_DEBUG, "MLD: op_class=%u, channel=%u",
458 ap_info->op_class, ap_info->channel);
459
460 if (len > rnr_ie_len)
461 break;
462
463 if (ap_info->tbtt_info_len < 16) {
464 rnr_ie_len -= len;
465 pos += len;
466 continue;
467 }
468
469 data += 13;
470
471 wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
472 *data, *(data + 1) & 0xF);
473
474 if (*data) {
475 wpa_printf(MSG_DEBUG,
476 "MLD: Reported link not part of MLD");
477 } else {
478 struct wpa_bss *neigh_bss =
479 wpa_bss_get_bssid(wpa_s, ap_info->data + 1);
480 u8 link_id = *(data + 1) & 0xF;
481
482 if (neigh_bss) {
483 if (wpa_scan_res_match(wpa_s, 0, neigh_bss,
484 wpa_s->current_ssid,
485 1, 0)) {
486 wpa_s->valid_links |= BIT(link_id);
487 os_memcpy(wpa_s->links[link_id].bssid,
488 ap_info->data + 1, ETH_ALEN);
489 wpa_s->links[link_id].freq =
490 neigh_bss->freq;
491 } else {
492 wpa_printf(MSG_DEBUG,
493 "MLD: Neighbor doesn't match current SSID - skip link");
494 }
495 } else {
496 wpa_printf(MSG_DEBUG,
497 "MLD: Neighbor not found in scan");
498 }
499 }
500
501 rnr_ie_len -= len;
502 pos += len;
503 }
504
505 wpa_printf(MSG_DEBUG, "MLD: valid_links=0x%x", wpa_s->valid_links);
506
507 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
508 if (!(wpa_s->valid_links & BIT(i)))
509 continue;
510
511 wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
512 i, MAC2STR(wpa_s->links[i].bssid));
513 }
514
515 ret = true;
516out:
517 wpabuf_free(mlbuf);
518 return ret;
519}
520
521
522static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
523 union wpa_event_data *data,
524 int ie_offset)
525{
526 struct ieee802_11_elems elems;
527 const u8 *mld_addr;
528
529 if (!wpa_s->valid_links)
530 return;
531
532 if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
533 data->auth.ies_len - ie_offset,
534 &elems, 0) != ParseOK) {
535 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
536 goto out;
537 }
538
539 if (!elems.basic_mle || !elems.basic_mle_len) {
540 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
541 goto out;
542 }
543
544 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
545 if (!mld_addr)
546 goto out;
547
548 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
549
550 if (os_memcmp(wpa_s->ap_mld_addr, mld_addr, ETH_ALEN) != 0) {
551 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
552 MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
553 goto out;
554 }
555
556 return;
557out:
558 wpa_printf(MSG_DEBUG, "MLD: Authentication - clearing MLD state");
559 wpas_reset_mlo_info(wpa_s);
560}
561
562
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800563static void sme_send_authentication(struct wpa_supplicant *wpa_s,
564 struct wpa_bss *bss, struct wpa_ssid *ssid,
565 int start)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700566{
567 struct wpa_driver_auth_params params;
568 struct wpa_ssid *old_ssid;
569#ifdef CONFIG_IEEE80211R
570 const u8 *ie;
571#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700572#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573 const u8 *md = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700574#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Hai Shalomfdcde762020-04-02 11:19:20 -0700575 int bssid_changed;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800576 struct wpabuf *resp = NULL;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700577 u8 ext_capab[18];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800578 int ext_capab_len;
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800579 int skip_auth;
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800580 u8 *wpa_ie;
581 size_t wpa_ie_len;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700582#ifdef CONFIG_MBO
583 const u8 *mbo_ie;
584#endif /* CONFIG_MBO */
Hai Shalomfdcde762020-04-02 11:19:20 -0700585 int omit_rsnxe = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700586
587 if (bss == NULL) {
588 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
589 "the network");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800590 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700591 return;
592 }
593
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800594 skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
595 wpa_s->reassoc_same_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700596 wpa_s->current_bss = bss;
597
598 os_memset(&params, 0, sizeof(params));
599 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
Sunil Ravi77d572f2023-01-17 23:58:31 +0000607 if (wpas_ml_element(wpa_s, bss)) {
608 wpa_printf(MSG_DEBUG, "MLD: In authentication");
609 params.mld = true;
610 params.mld_link_id = wpa_s->mlo_assoc_link_id;
611 params.ap_mld_addr = wpa_s->ap_mld_addr;
612 }
613
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700614 if (wpa_s->sme.ssid_len != params.ssid_len ||
615 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
616 wpa_s->sme.prev_bssid_set = 0;
617
618 wpa_s->sme.freq = params.freq;
619 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
620 wpa_s->sme.ssid_len = params.ssid_len;
621
622 params.auth_alg = WPA_AUTH_ALG_OPEN;
623#ifdef IEEE8021X_EAPOL
624 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
625 if (ssid->leap) {
626 if (ssid->non_leap == 0)
627 params.auth_alg = WPA_AUTH_ALG_LEAP;
628 else
629 params.auth_alg |= WPA_AUTH_ALG_LEAP;
630 }
631 }
632#endif /* IEEE8021X_EAPOL */
633 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
634 params.auth_alg);
635 if (ssid->auth_alg) {
636 params.auth_alg = ssid->auth_alg;
637 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
638 "0x%x", params.auth_alg);
639 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800640#ifdef CONFIG_SAE
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800641 wpa_s->sme.sae_pmksa_caching = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800642 if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
643 const u8 *rsn;
644 struct wpa_ie_data ied;
645
646 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800647 if (!rsn) {
648 wpa_dbg(wpa_s, MSG_DEBUG,
649 "SAE enabled, but target BSS does not advertise RSN");
Hai Shalom021b0b52019-04-10 11:17:58 -0700650#ifdef CONFIG_DPP
651 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
652 (ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
653 (ied.key_mgmt & WPA_KEY_MGMT_DPP)) {
654 wpa_dbg(wpa_s, MSG_DEBUG, "Prefer DPP over SAE when both are enabled");
655#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800656 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
657 wpa_key_mgmt_sae(ied.key_mgmt)) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000658 if (wpas_is_sae_avoided(wpa_s, ssid, &ied)) {
659 wpa_dbg(wpa_s, MSG_DEBUG,
660 "SAE enabled, but disallowing SAE auth_alg without PMF");
661 } else {
662 wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
663 params.auth_alg = WPA_AUTH_ALG_SAE;
664 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800665 } else {
666 wpa_dbg(wpa_s, MSG_DEBUG,
667 "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800668 }
669 }
670#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700671
Hai Shalomfdcde762020-04-02 11:19:20 -0700672#ifdef CONFIG_WEP
673 {
674 int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700675
Hai Shalomfdcde762020-04-02 11:19:20 -0700676 for (i = 0; i < NUM_WEP_KEYS; i++) {
677 if (ssid->wep_key_len[i])
678 params.wep_key[i] = ssid->wep_key[i];
679 params.wep_key_len[i] = ssid->wep_key_len[i];
680 }
681 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
682 }
683#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684
685 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
686 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800687 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700688 int try_opportunistic;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700689 const u8 *cache_id = NULL;
690
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800691 try_opportunistic = (ssid->proactive_key_caching < 0 ?
692 wpa_s->conf->okc :
693 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700694 (ssid->proto & WPA_PROTO_RSN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700695#ifdef CONFIG_FILS
696 if (wpa_key_mgmt_fils(ssid->key_mgmt))
697 cache_id = wpa_bss_get_fils_cache_id(bss);
698#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000699 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
700 params.mld ? params.ap_mld_addr :
701 bss->bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702 wpa_s->current_ssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700703 try_opportunistic, cache_id,
704 0) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800705 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700706 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
707 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
708 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000709 &wpa_s->sme.assoc_req_ie_len,
710 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700711 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
712 "key management and encryption suites");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800713 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700714 return;
715 }
Hai Shalom74f70d42019-02-11 14:42:39 -0800716#ifdef CONFIG_HS20
717 } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
718 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
719 /* No PMKSA caching, but otherwise similar to RSN/WPA */
720 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
721 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
722 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000723 &wpa_s->sme.assoc_req_ie_len,
724 false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800725 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
726 "key management and encryption suites");
727 wpas_connect_work_done(wpa_s);
728 return;
729 }
730#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700731 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
732 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
733 /*
734 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
735 * use non-WPA since the scan results did not indicate that the
736 * AP is using WPA or WPA2.
737 */
738 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
739 wpa_s->sme.assoc_req_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800740 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
742 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
743 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000744 &wpa_s->sme.assoc_req_ie_len,
745 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
747 "key management and encryption suites (no "
748 "scan results)");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800749 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700750 return;
751 }
752#ifdef CONFIG_WPS
753 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
754 struct wpabuf *wps_ie;
755 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
756 if (wps_ie && wpabuf_len(wps_ie) <=
757 sizeof(wpa_s->sme.assoc_req_ie)) {
758 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
759 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
760 wpa_s->sme.assoc_req_ie_len);
761 } else
762 wpa_s->sme.assoc_req_ie_len = 0;
763 wpabuf_free(wps_ie);
764 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
765#endif /* CONFIG_WPS */
766 } else {
767 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
768 wpa_s->sme.assoc_req_ie_len = 0;
769 }
770
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800771 /* In case the WPA vendor IE is used, it should be placed after all the
772 * non-vendor IEs, as the lower layer expects the IEs to be ordered as
773 * defined in the standard. Store the WPA IE so it can later be
774 * inserted at the correct location.
775 */
776 wpa_ie = NULL;
777 wpa_ie_len = 0;
778 if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
779 wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
780 wpa_s->sme.assoc_req_ie_len);
781 if (wpa_ie) {
782 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
783
784 wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
785 wpa_s->sme.assoc_req_ie_len = 0;
786 } else {
787 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
788 wpas_connect_work_done(wpa_s);
789 return;
790 }
791 }
792
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700793#ifdef CONFIG_IEEE80211R
794 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
795 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
796 md = ie + 2;
797 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
Hai Shalom021b0b52019-04-10 11:17:58 -0700798 if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
799 !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
800 md = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700801 if (md) {
802 /* Prepare for the next transition */
803 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
804 }
805
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700806 if (md) {
807 wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
808 md[0], md[1]);
809
Hai Shalomfdcde762020-04-02 11:19:20 -0700810 omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700811 if (wpa_s->sme.assoc_req_ie_len + 5 <
812 sizeof(wpa_s->sme.assoc_req_ie)) {
813 struct rsn_mdie *mdie;
814 u8 *pos = wpa_s->sme.assoc_req_ie +
815 wpa_s->sme.assoc_req_ie_len;
816 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
817 *pos++ = sizeof(*mdie);
818 mdie = (struct rsn_mdie *) pos;
819 os_memcpy(mdie->mobility_domain, md,
820 MOBILITY_DOMAIN_ID_LEN);
821 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
822 wpa_s->sme.assoc_req_ie_len += 5;
823 }
824
Hai Shalom74f70d42019-02-11 14:42:39 -0800825 if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700826 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
Sunil Ravi77d572f2023-01-17 23:58:31 +0000827 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700828 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
829 "over-the-air");
830 params.auth_alg = WPA_AUTH_ALG_FT;
831 params.ie = wpa_s->sme.ft_ies;
832 params.ie_len = wpa_s->sme.ft_ies_len;
833 }
834 }
835#endif /* CONFIG_IEEE80211R */
836
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800837 wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800838 if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700839 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
840 struct wpa_ie_data _ie;
841 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
842 _ie.capabilities &
843 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
844 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
845 "MFP: require MFP");
846 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
847 }
848 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700849
850#ifdef CONFIG_P2P
851 if (wpa_s->global->p2p) {
852 u8 *pos;
853 size_t len;
854 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700855 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
856 len = sizeof(wpa_s->sme.assoc_req_ie) -
857 wpa_s->sme.assoc_req_ie_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800858 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
859 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700860 if (res >= 0)
861 wpa_s->sme.assoc_req_ie_len += res;
862 }
863#endif /* CONFIG_P2P */
864
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800865#ifdef CONFIG_FST
866 if (wpa_s->fst_ies) {
867 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
868
869 if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <=
870 sizeof(wpa_s->sme.assoc_req_ie)) {
871 os_memcpy(wpa_s->sme.assoc_req_ie +
872 wpa_s->sme.assoc_req_ie_len,
873 wpabuf_head(wpa_s->fst_ies),
874 fst_ies_len);
875 wpa_s->sme.assoc_req_ie_len += fst_ies_len;
876 }
877 }
878#endif /* CONFIG_FST */
879
880 sme_auth_handle_rrm(wpa_s, bss);
881
Dmitry Shmidt29333592017-01-09 12:27:11 -0800882 wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
Hai Shalomfdcde762020-04-02 11:19:20 -0700883 wpa_s, ssid, bss,
Dmitry Shmidt29333592017-01-09 12:27:11 -0800884 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
885 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800886
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700887 if (params.p2p)
888 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
889 else
890 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
891
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800892 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
893 sizeof(ext_capab));
894 if (ext_capab_len > 0) {
895 u8 *pos = wpa_s->sme.assoc_req_ie;
896 if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
897 pos += 2 + pos[1];
898 os_memmove(pos + ext_capab_len, pos,
899 wpa_s->sme.assoc_req_ie_len -
900 (pos - wpa_s->sme.assoc_req_ie));
901 wpa_s->sme.assoc_req_ie_len += ext_capab_len;
902 os_memcpy(pos, ext_capab, ext_capab_len);
903 }
904
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800905#ifdef CONFIG_TESTING_OPTIONS
906 if (wpa_s->rsnxe_override_assoc &&
907 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
908 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
909 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
910 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
911 wpabuf_head(wpa_s->rsnxe_override_assoc),
912 wpabuf_len(wpa_s->rsnxe_override_assoc));
913 wpa_s->sme.assoc_req_ie_len +=
914 wpabuf_len(wpa_s->rsnxe_override_assoc);
915 } else
916#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -0700917 if (wpa_s->rsnxe_len > 0 &&
918 wpa_s->rsnxe_len <=
Hai Shalomfdcde762020-04-02 11:19:20 -0700919 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len &&
920 !omit_rsnxe) {
Hai Shalomc3565922019-10-28 11:58:20 -0700921 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
922 wpa_s->rsnxe, wpa_s->rsnxe_len);
923 wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
924 }
925
Dmitry Shmidt04949592012-07-19 12:16:46 -0700926#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -0800927 if (is_hs20_network(wpa_s, ssid, bss)
928#ifndef ANDROID /* Android does not use the native HS 2.0 config */
929 && is_hs20_config(wpa_s)
930#endif /* ANDROID */
931 ) {
Dmitry Shmidt04949592012-07-19 12:16:46 -0700932 struct wpabuf *hs20;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800933
Roshan Pius3a1667e2018-07-03 15:17:14 -0700934 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700935 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800936 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700937 size_t len;
938
Hai Shalom74f70d42019-02-11 14:42:39 -0800939 wpas_hs20_add_indication(hs20, pps_mo_id,
940 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -0700941 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700942 len = sizeof(wpa_s->sme.assoc_req_ie) -
943 wpa_s->sme.assoc_req_ie_len;
944 if (wpabuf_len(hs20) <= len) {
945 os_memcpy(wpa_s->sme.assoc_req_ie +
946 wpa_s->sme.assoc_req_ie_len,
947 wpabuf_head(hs20), wpabuf_len(hs20));
948 wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
949 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700950 wpabuf_free(hs20);
951 }
952 }
953#endif /* CONFIG_HS20 */
954
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800955 if (wpa_ie) {
956 size_t len;
957
958 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
959
960 len = sizeof(wpa_s->sme.assoc_req_ie) -
961 wpa_s->sme.assoc_req_ie_len;
962
963 if (len > wpa_ie_len) {
964 os_memcpy(wpa_s->sme.assoc_req_ie +
965 wpa_s->sme.assoc_req_ie_len,
966 wpa_ie, wpa_ie_len);
967 wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
968 } else {
969 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
970 }
971
972 os_free(wpa_ie);
973 }
974
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800975 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
976 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
977 size_t len;
978
979 len = sizeof(wpa_s->sme.assoc_req_ie) -
980 wpa_s->sme.assoc_req_ie_len;
981 if (wpabuf_len(buf) <= len) {
982 os_memcpy(wpa_s->sme.assoc_req_ie +
983 wpa_s->sme.assoc_req_ie_len,
984 wpabuf_head(buf), wpabuf_len(buf));
985 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
986 }
987 }
988
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800989#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -0700990 mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -0700991 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800992 int len;
993
994 len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
995 wpa_s->sme.assoc_req_ie_len,
996 sizeof(wpa_s->sme.assoc_req_ie) -
Hai Shalomce48b4a2018-09-05 11:41:35 -0700997 wpa_s->sme.assoc_req_ie_len,
998 !!mbo_attr_from_mbo_ie(mbo_ie,
999 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001000 if (len >= 0)
1001 wpa_s->sme.assoc_req_ie_len += len;
1002 }
1003#endif /* CONFIG_MBO */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001004
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001005#ifdef CONFIG_SAE
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001006 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001007 pmksa_cache_set_current(wpa_s->wpa, NULL,
1008 params.mld ? params.ap_mld_addr :
1009 bss->bssid,
1010 ssid, 0,
Hai Shalom021b0b52019-04-10 11:17:58 -07001011 NULL,
Sunil Ravi89eba102022-09-13 21:04:37 -07001012 wpa_key_mgmt_sae(wpa_s->key_mgmt) ?
1013 wpa_s->key_mgmt :
1014 (int) WPA_KEY_MGMT_SAE) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001015 wpa_dbg(wpa_s, MSG_DEBUG,
1016 "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001017 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001018 params.auth_alg = WPA_AUTH_ALG_OPEN;
1019 wpa_s->sme.sae_pmksa_caching = 1;
1020 }
1021
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001022 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001023 if (start)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001024 resp = sme_auth_build_sae_commit(wpa_s, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001025 bss->bssid,
1026 params.mld ?
1027 params.ap_mld_addr :
1028 NULL, 0,
Hai Shalom899fcc72020-10-19 14:38:18 -07001029 start == 2, NULL,
1030 NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001031 else
Roshan Pius3a1667e2018-07-03 15:17:14 -07001032 resp = sme_auth_build_sae_confirm(wpa_s, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001033 if (resp == NULL) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001034 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001035 return;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001036 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001037 params.auth_data = wpabuf_head(resp);
1038 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001039 wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001040 }
1041#endif /* CONFIG_SAE */
1042
Hai Shalomfdcde762020-04-02 11:19:20 -07001043 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1044 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1045 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1046 if (bssid_changed)
1047 wpas_notify_bssid_changed(wpa_s);
1048
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001049 old_ssid = wpa_s->current_ssid;
1050 wpa_s->current_ssid = ssid;
1051 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1052 wpa_supplicant_initiate_eapol(wpa_s);
1053
1054#ifdef CONFIG_FILS
1055 /* TODO: FILS operations can in some cases be done between different
1056 * network_ctx (i.e., same credentials can be used with multiple
1057 * networks). */
1058 if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
1059 wpa_key_mgmt_fils(ssid->key_mgmt)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001060 const u8 *indic;
1061 u16 fils_info;
Hai Shalomce48b4a2018-09-05 11:41:35 -07001062 const u8 *realm, *username, *rrk;
1063 size_t realm_len, username_len, rrk_len;
1064 u16 next_seq_num;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001065
1066 /*
1067 * Check FILS Indication element (FILS Information field) bits
1068 * indicating supported authentication algorithms against local
1069 * configuration (ssid->fils_dh_group). Try to use FILS
1070 * authentication only if the AP supports the combination in the
1071 * network profile. */
1072 indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
1073 if (!indic || indic[1] < 2) {
1074 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1075 " does not include FILS Indication element - cannot use FILS authentication with it",
1076 MAC2STR(bss->bssid));
1077 goto no_fils;
1078 }
1079
1080 fils_info = WPA_GET_LE16(indic + 2);
1081 if (ssid->fils_dh_group == 0 && !(fils_info & BIT(9))) {
1082 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1083 " does not support FILS SK without PFS - cannot use FILS authentication with it",
1084 MAC2STR(bss->bssid));
1085 goto no_fils;
1086 }
1087 if (ssid->fils_dh_group != 0 && !(fils_info & BIT(10))) {
1088 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1089 " does not support FILS SK with PFS - cannot use FILS authentication with it",
1090 MAC2STR(bss->bssid));
1091 goto no_fils;
1092 }
1093
Hai Shalomce48b4a2018-09-05 11:41:35 -07001094 if (wpa_s->last_con_fail_realm &&
1095 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
1096 &username, &username_len,
1097 &realm, &realm_len, &next_seq_num,
1098 &rrk, &rrk_len) == 0 &&
1099 realm && realm_len == wpa_s->last_con_fail_realm_len &&
1100 os_memcmp(realm, wpa_s->last_con_fail_realm,
1101 realm_len) == 0) {
1102 wpa_printf(MSG_DEBUG,
1103 "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
1104 goto no_fils;
1105 }
1106
Sunil Ravi77d572f2023-01-17 23:58:31 +00001107 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
1108 params.mld ? params.ap_mld_addr :
1109 bss->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001110 ssid, 0,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001111 wpa_bss_get_fils_cache_id(bss),
1112 0) == 0)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001113 wpa_printf(MSG_DEBUG,
1114 "SME: Try to use FILS with PMKSA caching");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001115 resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001116 if (resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001117 int auth_alg;
1118
1119 if (ssid->fils_dh_group)
1120 wpa_printf(MSG_DEBUG,
1121 "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
1122 ssid->fils_dh_group);
1123 else
1124 wpa_printf(MSG_DEBUG,
1125 "SME: Try to use FILS SK authentication without PFS");
1126 auth_alg = ssid->fils_dh_group ?
1127 WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
1128 params.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001129 params.auth_data = wpabuf_head(resp);
1130 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001131 wpa_s->sme.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001132 }
1133 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001134no_fils:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001135#endif /* CONFIG_FILS */
1136
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001137 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001138 wpa_supplicant_cancel_scan(wpa_s);
1139
1140 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
1141 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
1142 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
1143
Hai Shalome21d4e82020-04-29 16:34:06 -07001144 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001145 wpa_clear_keys(wpa_s, bss->bssid);
1146 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001147 if (old_ssid != wpa_s->current_ssid)
1148 wpas_notify_network_changed(wpa_s);
1149
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001150#ifdef CONFIG_HS20
1151 hs20_configure_frame_filters(wpa_s);
1152#endif /* CONFIG_HS20 */
1153
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001154#ifdef CONFIG_P2P
1155 /*
1156 * If multi-channel concurrency is not supported, check for any
1157 * frequency conflict. In case of any frequency conflict, remove the
1158 * least prioritized connection.
1159 */
1160 if (wpa_s->num_multichan_concurrent < 2) {
1161 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001162 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001163 if (num > 0 && freq > 0 && freq != params.freq) {
1164 wpa_printf(MSG_DEBUG,
1165 "Conflicting frequency found (%d != %d)",
1166 freq, params.freq);
1167 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1168 params.freq,
1169 ssid) < 0) {
1170 wpas_connection_failed(wpa_s, bss->bssid);
1171 wpa_supplicant_mark_disassoc(wpa_s);
1172 wpabuf_free(resp);
1173 wpas_connect_work_done(wpa_s);
1174 return;
1175 }
1176 }
1177 }
1178#endif /* CONFIG_P2P */
1179
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001180 if (skip_auth) {
1181 wpa_msg(wpa_s, MSG_DEBUG,
1182 "SME: Skip authentication step on reassoc-to-same-BSS");
1183 wpabuf_free(resp);
1184 sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN);
1185 return;
1186 }
1187
1188
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001189 wpa_s->sme.auth_alg = params.auth_alg;
1190 if (wpa_drv_authenticate(wpa_s, &params) < 0) {
1191 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
1192 "driver failed");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001193 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001194 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001195 wpabuf_free(resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001196 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001197 return;
1198 }
1199
1200 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
1201 NULL);
1202
1203 /*
1204 * Association will be started based on the authentication event from
1205 * the driver.
1206 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001207
1208 wpabuf_free(resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001209}
1210
1211
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001212static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
1213{
1214 struct wpa_connect_work *cwork = work->ctx;
1215 struct wpa_supplicant *wpa_s = work->wpa_s;
1216
Hai Shaloma20dcd72022-02-04 13:43:00 -08001217 wpa_s->roam_in_progress = false;
1218#ifdef CONFIG_WNM
1219 wpa_s->bss_trans_mgmt_in_progress = false;
1220#endif /* CONFIG_WNM */
1221
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001222 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001223 if (work->started)
1224 wpa_s->connect_work = NULL;
1225
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001226 wpas_connect_work_free(cwork);
1227 return;
1228 }
1229
1230 wpa_s->connect_work = work;
1231
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001232 if (cwork->bss_removed ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001233 !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
1234 wpas_network_disabled(wpa_s, cwork->ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001235 wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
1236 wpas_connect_work_done(wpa_s);
1237 return;
1238 }
1239
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001240 /* Starting new connection, so clear the possibly used WPA IE from the
1241 * previous association. */
1242 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07001243 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
1244 wpa_s->rsnxe_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001245
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001246 sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001247 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001248}
1249
1250
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001251void sme_authenticate(struct wpa_supplicant *wpa_s,
1252 struct wpa_bss *bss, struct wpa_ssid *ssid)
1253{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001254 struct wpa_connect_work *cwork;
1255
1256 if (bss == NULL || ssid == NULL)
1257 return;
1258 if (wpa_s->connect_work) {
1259 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
1260 return;
1261 }
1262
Hai Shaloma20dcd72022-02-04 13:43:00 -08001263 if (wpa_s->roam_in_progress) {
1264 wpa_dbg(wpa_s, MSG_DEBUG,
1265 "SME: Reject sme_authenticate() in favor of explicit roam request");
1266 return;
1267 }
1268#ifdef CONFIG_WNM
1269 if (wpa_s->bss_trans_mgmt_in_progress) {
1270 wpa_dbg(wpa_s, MSG_DEBUG,
1271 "SME: Reject sme_authenticate() in favor of BSS transition management request");
1272 return;
1273 }
1274#endif /* CONFIG_WNM */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001275 if (radio_work_pending(wpa_s, "sme-connect")) {
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001276 /*
1277 * The previous sme-connect work might no longer be valid due to
1278 * the fact that the BSS list was updated. In addition, it makes
1279 * sense to adhere to the 'newer' decision.
1280 */
1281 wpa_dbg(wpa_s, MSG_DEBUG,
1282 "SME: Remove previous pending sme-connect");
1283 radio_remove_works(wpa_s, "sme-connect", 0);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001284 }
1285
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001286 wpas_abort_ongoing_scan(wpa_s);
1287
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001288 cwork = os_zalloc(sizeof(*cwork));
1289 if (cwork == NULL)
1290 return;
1291 cwork->bss = bss;
1292 cwork->ssid = ssid;
1293 cwork->sme = 1;
1294
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001295#ifdef CONFIG_SAE
1296 wpa_s->sme.sae.state = SAE_NOTHING;
1297 wpa_s->sme.sae.send_confirm = 0;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001298 wpa_s->sme.sae_group_index = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001299#endif /* CONFIG_SAE */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001300
1301 if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
1302 sme_auth_start_cb, cwork) < 0)
1303 wpas_connect_work_free(cwork);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001304}
1305
1306
1307#ifdef CONFIG_SAE
1308
Sunil Ravi036cec52023-03-29 11:35:17 -07001309#define WPA_AUTH_FRAME_ML_IE_LEN (6 + ETH_ALEN)
1310
1311static void wpa_auth_ml_ie(struct wpabuf *buf, const u8 *mld_addr)
1312{
1313
1314 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1315 wpabuf_put_u8(buf, 4 + ETH_ALEN);
1316 wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK);
1317
1318 /* Basic Multi-Link element Control field */
1319 wpabuf_put_u8(buf, 0x0);
1320 wpabuf_put_u8(buf, 0x0);
1321
1322 /* Common Info */
1323 wpabuf_put_u8(buf, 0x7); /* length = Length field + MLD MAC address */
1324 wpabuf_put_data(buf, mld_addr, ETH_ALEN);
1325}
1326
1327
Roshan Pius3a1667e2018-07-03 15:17:14 -07001328static int sme_external_auth_build_buf(struct wpabuf *buf,
1329 struct wpabuf *params,
1330 const u8 *sa, const u8 *da,
Hai Shalomc3565922019-10-28 11:58:20 -07001331 u16 auth_transaction, u16 seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001332 u16 status_code, const u8 *mld_addr)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001333{
1334 struct ieee80211_mgmt *resp;
1335
1336 resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
1337 u.auth.variable));
1338
1339 resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
1340 (WLAN_FC_STYPE_AUTH << 4));
1341 os_memcpy(resp->da, da, ETH_ALEN);
1342 os_memcpy(resp->sa, sa, ETH_ALEN);
1343 os_memcpy(resp->bssid, da, ETH_ALEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08001344 resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
1345 resp->seq_ctrl = host_to_le16(seq_num << 4);
1346 resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
Hai Shalomc3565922019-10-28 11:58:20 -07001347 resp->u.auth.status_code = host_to_le16(status_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001348 if (params)
1349 wpabuf_put_buf(buf, params);
1350
Sunil Ravi036cec52023-03-29 11:35:17 -07001351 if (mld_addr)
1352 wpa_auth_ml_ie(buf, mld_addr);
1353
Roshan Pius3a1667e2018-07-03 15:17:14 -07001354 return 0;
1355}
1356
1357
Hai Shalom81f62d82019-07-22 12:10:00 -07001358static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
1359 const u8 *bssid,
1360 struct wpa_ssid *ssid)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001361{
1362 struct wpabuf *resp, *buf;
Hai Shalomc3565922019-10-28 11:58:20 -07001363 int use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -07001364 bool use_pk;
1365 u16 status;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001366
Sunil Ravi036cec52023-03-29 11:35:17 -07001367 resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid,
1368 wpa_s->sme.ext_ml_auth ?
1369 wpa_s->sme.ext_auth_ap_mld_addr : NULL,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001370 1, 0, &use_pt, &use_pk);
Hai Shalom81f62d82019-07-22 12:10:00 -07001371 if (!resp) {
1372 wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
1373 return -1;
1374 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001375
1376 wpa_s->sme.sae.state = SAE_COMMITTED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001377 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp) +
1378 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1379 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001380 if (!buf) {
1381 wpabuf_free(resp);
Hai Shalom81f62d82019-07-22 12:10:00 -07001382 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001383 }
1384
1385 wpa_s->sme.seq_num++;
Hai Shalom899fcc72020-10-19 14:38:18 -07001386 if (use_pk)
1387 status = WLAN_STATUS_SAE_PK;
1388 else if (use_pt)
1389 status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
1390 else
1391 status = WLAN_STATUS_SUCCESS;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001392 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Sunil Ravi036cec52023-03-29 11:35:17 -07001393 wpa_s->sme.ext_ml_auth ?
1394 wpa_s->sme.ext_auth_ap_mld_addr : bssid, 1,
1395 wpa_s->sme.seq_num, status,
1396 wpa_s->sme.ext_ml_auth ?
1397 wpa_s->own_addr : NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07001398 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001399 wpabuf_free(resp);
1400 wpabuf_free(buf);
Hai Shalom81f62d82019-07-22 12:10:00 -07001401
1402 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001403}
1404
1405
1406static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
1407 u16 status)
1408{
1409 struct external_auth params;
1410
Sunil Ravi89eba102022-09-13 21:04:37 -07001411 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001412 os_memset(&params, 0, sizeof(params));
1413 params.status = status;
Hai Shalom66904732019-05-29 11:54:04 -07001414 params.ssid = wpa_s->sme.ext_auth_ssid;
1415 params.ssid_len = wpa_s->sme.ext_auth_ssid_len;
1416 params.bssid = wpa_s->sme.ext_auth_bssid;
Hai Shalomc3565922019-10-28 11:58:20 -07001417 if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
1418 params.pmkid = wpa_s->sme.sae.pmkid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001419 wpa_drv_send_external_auth_status(wpa_s, &params);
1420}
1421
1422
Hai Shalom81f62d82019-07-22 12:10:00 -07001423static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
1424 union wpa_event_data *data)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001425{
1426 struct wpa_ssid *ssid;
1427 size_t ssid_str_len = data->external_auth.ssid_len;
Hai Shalom5f92bc92019-04-18 11:54:11 -07001428 const u8 *ssid_str = data->external_auth.ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001429
Sunil Ravi89eba102022-09-13 21:04:37 -07001430 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001431 /* Get the SSID conf from the ssid string obtained */
1432 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1433 if (!wpas_network_disabled(wpa_s, ssid) &&
1434 ssid_str_len == ssid->ssid_len &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001435 os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001436 wpa_key_mgmt_sae(ssid->key_mgmt)) {
1437 /* Make sure PT is derived */
Sunil Ravi036cec52023-03-29 11:35:17 -07001438 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Sunil Ravi89eba102022-09-13 21:04:37 -07001439 wpa_s->sme.ext_auth_wpa_ssid = ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001440 break;
Sunil Ravi89eba102022-09-13 21:04:37 -07001441 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001442 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001443 if (!ssid ||
1444 sme_external_auth_send_sae_commit(wpa_s, data->external_auth.bssid,
1445 ssid) < 0)
1446 return -1;
1447
1448 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001449}
1450
1451
1452static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
1453 const u8 *da)
1454{
1455 struct wpabuf *resp, *buf;
1456
1457 resp = sme_auth_build_sae_confirm(wpa_s, 1);
1458 if (!resp) {
1459 wpa_printf(MSG_DEBUG, "SAE: Confirm message buf alloc failure");
1460 return;
1461 }
1462
1463 wpa_s->sme.sae.state = SAE_CONFIRMED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001464 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp) +
1465 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1466 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001467 if (!buf) {
1468 wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure");
1469 wpabuf_free(resp);
1470 return;
1471 }
1472 wpa_s->sme.seq_num++;
1473 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Hai Shalomc3565922019-10-28 11:58:20 -07001474 da, 2, wpa_s->sme.seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001475 WLAN_STATUS_SUCCESS,
1476 wpa_s->sme.ext_ml_auth ?
1477 wpa_s->own_addr : NULL);
1478
Hai Shalomfdcde762020-04-02 11:19:20 -07001479 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001480 wpabuf_free(resp);
1481 wpabuf_free(buf);
1482}
1483
1484
Sunil Ravi77d572f2023-01-17 23:58:31 +00001485static bool is_sae_key_mgmt_suite(struct wpa_supplicant *wpa_s, u32 suite)
1486{
1487 /* suite is supposed to be the selector value in host byte order with
1488 * the OUI in three most significant octets. However, the initial
1489 * implementation swapped that byte order and did not work with drivers
1490 * that followed the expected byte order. Keep a workaround here to
1491 * match that initial implementation so that already deployed use cases
1492 * remain functional. */
1493 if (RSN_SELECTOR_GET(&suite) == RSN_AUTH_KEY_MGMT_SAE) {
1494 /* Old drivers which follow initial implementation send SAE AKM
1495 * for both SAE and FT-SAE connections. In that case, determine
1496 * the actual AKM from wpa_s->key_mgmt. */
1497 wpa_s->sme.ext_auth_key_mgmt = wpa_s->key_mgmt;
1498 return true;
1499 }
1500
1501 if (suite == RSN_AUTH_KEY_MGMT_SAE)
1502 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE;
1503 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE)
1504 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE;
1505 else if (suite == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
1506 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1507 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
1508 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1509 else
1510 return false;
1511
1512 return true;
1513}
1514
1515
Roshan Pius3a1667e2018-07-03 15:17:14 -07001516void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
1517 union wpa_event_data *data)
1518{
Sunil Ravi77d572f2023-01-17 23:58:31 +00001519 if (!is_sae_key_mgmt_suite(wpa_s, data->external_auth.key_mgmt_suite))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001520 return;
1521
1522 if (data->external_auth.action == EXT_AUTH_START) {
Hai Shalom66904732019-05-29 11:54:04 -07001523 if (!data->external_auth.bssid || !data->external_auth.ssid)
1524 return;
1525 os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid,
1526 ETH_ALEN);
1527 os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid,
1528 data->external_auth.ssid_len);
1529 wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len;
Sunil Ravi036cec52023-03-29 11:35:17 -07001530 if (data->external_auth.mld_addr) {
1531 wpa_s->sme.ext_ml_auth = true;
1532 os_memcpy(wpa_s->sme.ext_auth_ap_mld_addr,
1533 data->external_auth.mld_addr, ETH_ALEN);
1534 } else {
1535 wpa_s->sme.ext_ml_auth = false;
1536 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001537 wpa_s->sme.seq_num = 0;
1538 wpa_s->sme.sae.state = SAE_NOTHING;
1539 wpa_s->sme.sae.send_confirm = 0;
1540 wpa_s->sme.sae_group_index = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001541 if (sme_handle_external_auth_start(wpa_s, data) < 0)
1542 sme_send_external_auth_status(wpa_s,
1543 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001544 } else if (data->external_auth.action == EXT_AUTH_ABORT) {
1545 /* Report failure to driver for the wrong trigger */
1546 sme_send_external_auth_status(wpa_s,
1547 WLAN_STATUS_UNSPECIFIED_FAILURE);
1548 }
1549}
1550
1551
Hai Shalomc3565922019-10-28 11:58:20 -07001552static int sme_sae_is_group_enabled(struct wpa_supplicant *wpa_s, int group)
1553{
1554 int *groups = wpa_s->conf->sae_groups;
1555 int default_groups[] = { 19, 20, 21, 0 };
1556 int i;
1557
1558 if (!groups)
1559 groups = default_groups;
1560
1561 for (i = 0; groups[i] > 0; i++) {
1562 if (groups[i] == group)
1563 return 1;
1564 }
1565
1566 return 0;
1567}
1568
1569
1570static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
1571 const struct wpabuf *groups)
1572{
1573 size_t i, count;
1574 const u8 *pos;
1575
1576 if (!groups)
1577 return 0;
1578
1579 pos = wpabuf_head(groups);
1580 count = wpabuf_len(groups) / 2;
1581 for (i = 0; i < count; i++) {
1582 int enabled;
1583 u16 group;
1584
1585 group = WPA_GET_LE16(pos);
1586 pos += 2;
1587 enabled = sme_sae_is_group_enabled(wpa_s, group);
1588 wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
1589 group, enabled ? "enabled" : "disabled");
1590 if (enabled)
1591 return 1;
1592 }
1593
1594 return 0;
1595}
1596
1597
Sunil Ravi036cec52023-03-29 11:35:17 -07001598static int sme_external_ml_auth(struct wpa_supplicant *wpa_s,
1599 const u8 *data, size_t len, int ie_offset)
1600{
1601 struct ieee802_11_elems elems;
1602 const u8 *mld_addr;
1603
1604 if (ieee802_11_parse_elems(data + ie_offset, len - ie_offset,
1605 &elems, 0) != ParseOK) {
1606 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
1607 return -1;
1608 }
1609
1610 if (!elems.basic_mle || !elems.basic_mle_len) {
1611 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
1612 return -1;
1613 }
1614
1615 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
1616 if (!mld_addr) {
1617 wpa_printf(MSG_DEBUG, "MLD: No MLD address in ML element");
1618 return -1;
1619 }
1620
1621 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
1622
1623 if (os_memcmp(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr, ETH_ALEN) !=
1624 0) {
1625 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
1626 MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
1627 return -1;
1628 }
1629
1630 return 0;
1631}
1632
1633
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001634static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001635 u16 status_code, const u8 *data, size_t len,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001636 int external, const u8 *sa, int *ie_offset)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001637{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001638 int *groups;
1639
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001640 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
1641 "status code %u", auth_transaction, status_code);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001642
1643 if (auth_transaction == 1 &&
1644 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1645 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001646 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1647 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001648 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001649 u16 group;
Hai Shalomfdcde762020-04-02 11:19:20 -07001650 const u8 *token_pos;
1651 size_t token_len;
1652 int h2e = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001653
1654 groups = wpa_s->conf->sae_groups;
1655 if (!groups || groups[0] <= 0)
1656 groups = default_groups;
1657
Hai Shalomfdcde762020-04-02 11:19:20 -07001658 wpa_hexdump(MSG_DEBUG, "SME: SAE anti-clogging token request",
1659 data, len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001660 if (len < sizeof(le16)) {
1661 wpa_dbg(wpa_s, MSG_DEBUG,
1662 "SME: Too short SAE anti-clogging token request");
1663 return -1;
1664 }
1665 group = WPA_GET_LE16(data);
1666 wpa_dbg(wpa_s, MSG_DEBUG,
1667 "SME: SAE anti-clogging token requested (group %u)",
1668 group);
1669 if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
1670 WLAN_STATUS_SUCCESS) {
1671 wpa_dbg(wpa_s, MSG_ERROR,
1672 "SME: SAE group %u of anti-clogging request is invalid",
1673 group);
1674 return -1;
1675 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001676 wpabuf_free(wpa_s->sme.sae_token);
Hai Shalomfdcde762020-04-02 11:19:20 -07001677 token_pos = data + sizeof(le16);
1678 token_len = len - sizeof(le16);
Hai Shalom899fcc72020-10-19 14:38:18 -07001679 h2e = wpa_s->sme.sae.h2e;
Hai Shalomfdcde762020-04-02 11:19:20 -07001680 if (h2e) {
Sunil8cd6f4d2022-06-28 18:40:46 +00001681 u8 id, elen, extid;
1682
Hai Shalomfdcde762020-04-02 11:19:20 -07001683 if (token_len < 3) {
1684 wpa_dbg(wpa_s, MSG_DEBUG,
1685 "SME: Too short SAE anti-clogging token container");
1686 return -1;
1687 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001688 id = *token_pos++;
1689 elen = *token_pos++;
1690 extid = *token_pos++;
1691 if (id != WLAN_EID_EXTENSION ||
1692 elen == 0 || elen > token_len - 2 ||
1693 extid != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001694 wpa_dbg(wpa_s, MSG_DEBUG,
1695 "SME: Invalid SAE anti-clogging token container header");
1696 return -1;
1697 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001698 token_len = elen - 1;
Hai Shalomfdcde762020-04-02 11:19:20 -07001699 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00001700
Sunil Ravi036cec52023-03-29 11:35:17 -07001701 *ie_offset = token_pos + token_len - data;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001702
Hai Shalomfdcde762020-04-02 11:19:20 -07001703 wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001704 if (!wpa_s->sme.sae_token) {
1705 wpa_dbg(wpa_s, MSG_ERROR,
1706 "SME: Failed to allocate SAE token");
1707 return -1;
1708 }
1709
Hai Shalomfdcde762020-04-02 11:19:20 -07001710 wpa_hexdump_buf(MSG_DEBUG, "SME: Requested anti-clogging token",
1711 wpa_s->sme.sae_token);
Sunil Ravi036cec52023-03-29 11:35:17 -07001712 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001713 sme_send_authentication(wpa_s, wpa_s->current_bss,
Hai Shalom021b0b52019-04-10 11:17:58 -07001714 wpa_s->current_ssid, 2);
Sunil Ravi036cec52023-03-29 11:35:17 -07001715 } else {
1716 if (wpa_s->sme.ext_ml_auth &&
1717 sme_external_ml_auth(wpa_s, data, len, *ie_offset))
1718 return -1;
1719
Roshan Pius3a1667e2018-07-03 15:17:14 -07001720 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001721 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001722 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001723 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001724 return 0;
1725 }
1726
1727 if (auth_transaction == 1 &&
1728 status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1729 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001730 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1731 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001732 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
Hai Shalomc3565922019-10-28 11:58:20 -07001733 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1734 wpa_s->sme.sae.group);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001735 wpa_s->sme.sae_group_index++;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001736 if (sme_set_sae_group(wpa_s, external) < 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001737 return -1; /* no other groups enabled */
1738 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
Sunil Ravi036cec52023-03-29 11:35:17 -07001739 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001740 sme_send_authentication(wpa_s, wpa_s->current_bss,
1741 wpa_s->current_ssid, 1);
Sunil Ravi036cec52023-03-29 11:35:17 -07001742 } else {
1743 if (wpa_s->sme.ext_ml_auth &&
1744 sme_external_ml_auth(wpa_s, data, len, *ie_offset))
1745 return -1;
1746
Roshan Pius3a1667e2018-07-03 15:17:14 -07001747 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001748 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001749 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001750 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001751 return 0;
1752 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001753
Roshan Pius3a1667e2018-07-03 15:17:14 -07001754 if (auth_transaction == 1 &&
1755 status_code == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1756 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1757
1758 wpa_msg(wpa_s, MSG_INFO,
1759 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR,
1760 MAC2STR(bssid));
1761 return -1;
1762 }
1763
Hai Shalomc3565922019-10-28 11:58:20 -07001764 if (status_code != WLAN_STATUS_SUCCESS &&
Hai Shalom899fcc72020-10-19 14:38:18 -07001765 status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08001766 status_code != WLAN_STATUS_SAE_PK) {
1767 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1768
1769 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
1770 " auth_type=%u auth_transaction=%u status_code=%u",
1771 MAC2STR(bssid), WLAN_AUTH_SAE,
1772 auth_transaction, status_code);
Sunil Ravia04bd252022-05-02 22:54:18 -07001773 return -2;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001774 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001775
1776 if (auth_transaction == 1) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07001777 u16 res;
1778
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001779 groups = wpa_s->conf->sae_groups;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001780
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001781 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
Sunil Ravi89eba102022-09-13 21:04:37 -07001782 if ((external && !wpa_s->sme.ext_auth_wpa_ssid) ||
1783 (!external &&
1784 (!wpa_s->current_bss || !wpa_s->current_ssid)))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001785 return -1;
Hai Shalomc3565922019-10-28 11:58:20 -07001786 if (wpa_s->sme.sae.state != SAE_COMMITTED) {
1787 wpa_printf(MSG_DEBUG,
1788 "SAE: Ignore commit message while waiting for confirm");
1789 return 0;
1790 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001791 if (wpa_s->sme.sae.h2e && status_code == WLAN_STATUS_SUCCESS) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001792 wpa_printf(MSG_DEBUG,
1793 "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
1794 return -1;
1795 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001796 if ((!wpa_s->sme.sae.h2e || wpa_s->sme.sae.pk) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001797 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
1798 wpa_printf(MSG_DEBUG,
1799 "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
1800 return -1;
1801 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001802 if (!wpa_s->sme.sae.pk &&
1803 status_code == WLAN_STATUS_SAE_PK) {
1804 wpa_printf(MSG_DEBUG,
1805 "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected");
1806 return -1;
1807 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001808
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001809 if (groups && groups[0] <= 0)
1810 groups = NULL;
Dmitry Shmidt41712582015-06-29 11:02:15 -07001811 res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
Hai Shalomc3565922019-10-28 11:58:20 -07001812 groups, status_code ==
Hai Shalom899fcc72020-10-19 14:38:18 -07001813 WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001814 status_code == WLAN_STATUS_SAE_PK,
1815 ie_offset);
Dmitry Shmidt41712582015-06-29 11:02:15 -07001816 if (res == SAE_SILENTLY_DISCARD) {
1817 wpa_printf(MSG_DEBUG,
1818 "SAE: Drop commit message due to reflection attack");
1819 return 0;
1820 }
1821 if (res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001822 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001823
Hai Shalomc3565922019-10-28 11:58:20 -07001824 if (wpa_s->sme.sae.tmp &&
1825 sme_check_sae_rejected_groups(
1826 wpa_s,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001827 wpa_s->sme.sae.tmp->peer_rejected_groups))
Hai Shalomc3565922019-10-28 11:58:20 -07001828 return -1;
1829
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001830 if (sae_process_commit(&wpa_s->sme.sae) < 0) {
1831 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
1832 "commit");
1833 return -1;
1834 }
1835
1836 wpabuf_free(wpa_s->sme.sae_token);
1837 wpa_s->sme.sae_token = NULL;
Sunil Ravi036cec52023-03-29 11:35:17 -07001838 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001839 sme_send_authentication(wpa_s, wpa_s->current_bss,
1840 wpa_s->current_ssid, 0);
Sunil Ravi036cec52023-03-29 11:35:17 -07001841 } else {
1842 if (wpa_s->sme.ext_ml_auth &&
1843 sme_external_ml_auth(wpa_s, data, len, *ie_offset))
1844 return -1;
1845
Roshan Pius3a1667e2018-07-03 15:17:14 -07001846 sme_external_auth_send_sae_confirm(wpa_s, sa);
Sunil Ravi036cec52023-03-29 11:35:17 -07001847 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001848 return 0;
1849 } else if (auth_transaction == 2) {
Hai Shalomc3565922019-10-28 11:58:20 -07001850 if (status_code != WLAN_STATUS_SUCCESS)
1851 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001852 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001853 if (wpa_s->sme.sae.state != SAE_CONFIRMED)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001854 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001855 if (sae_check_confirm(&wpa_s->sme.sae, data, len,
1856 ie_offset) < 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001857 return -1;
Sunil Ravi036cec52023-03-29 11:35:17 -07001858 if (external && wpa_s->sme.ext_ml_auth &&
1859 sme_external_ml_auth(wpa_s, data, len, *ie_offset))
1860 return -1;
1861
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001862 wpa_s->sme.sae.state = SAE_ACCEPTED;
1863 sae_clear_temp_data(&wpa_s->sme.sae);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001864
1865 if (external) {
1866 /* Report success to driver */
1867 sme_send_external_auth_status(wpa_s,
1868 WLAN_STATUS_SUCCESS);
1869 }
1870
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001871 return 1;
1872 }
1873
1874 return -1;
1875}
Roshan Pius3a1667e2018-07-03 15:17:14 -07001876
1877
Hai Shalomc3565922019-10-28 11:58:20 -07001878static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
1879{
1880 wpa_printf(MSG_DEBUG,
1881 "SME: SAE completed - setting PMK for 4-way handshake");
Sunil Ravi89eba102022-09-13 21:04:37 -07001882 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 -07001883 wpa_s->sme.sae.pmkid, bssid);
1884 if (wpa_s->conf->sae_pmkid_in_assoc) {
1885 /* Update the own RSNE contents now that we have set the PMK
1886 * and added a PMKSA cache entry based on the successfully
1887 * completed SAE exchange. In practice, this will add the PMKID
1888 * into RSNE. */
1889 if (wpa_s->sme.assoc_req_ie_len + 2 + PMKID_LEN >
1890 sizeof(wpa_s->sme.assoc_req_ie)) {
1891 wpa_msg(wpa_s, MSG_WARNING,
1892 "RSN: Not enough room for inserting own PMKID into RSNE");
1893 return -1;
1894 }
1895 if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
1896 &wpa_s->sme.assoc_req_ie_len,
1897 wpa_s->sme.sae.pmkid) < 0)
1898 return -1;
1899 wpa_hexdump(MSG_DEBUG,
1900 "SME: Updated Association Request IEs",
1901 wpa_s->sme.assoc_req_ie,
1902 wpa_s->sme.assoc_req_ie_len);
1903 }
1904
1905 return 0;
1906}
1907
1908
Roshan Pius3a1667e2018-07-03 15:17:14 -07001909void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
1910 const u8 *auth_frame, size_t len)
1911{
1912 const struct ieee80211_mgmt *header;
1913 size_t auth_length;
1914
1915 header = (const struct ieee80211_mgmt *) auth_frame;
1916 auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);
1917
1918 if (len < auth_length) {
1919 /* Notify failure to the driver */
1920 sme_send_external_auth_status(wpa_s,
1921 WLAN_STATUS_UNSPECIFIED_FAILURE);
1922 return;
1923 }
1924
Hai Shalom74f70d42019-02-11 14:42:39 -08001925 if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001926 int res;
Sunil Ravi036cec52023-03-29 11:35:17 -07001927 int ie_offset = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001928
Hai Shalom74f70d42019-02-11 14:42:39 -08001929 res = sme_sae_auth(
1930 wpa_s, le_to_host16(header->u.auth.auth_transaction),
1931 le_to_host16(header->u.auth.status_code),
1932 header->u.auth.variable,
Sunil Ravi036cec52023-03-29 11:35:17 -07001933 len - auth_length, 1, header->sa, &ie_offset);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001934 if (res < 0) {
1935 /* Notify failure to the driver */
1936 sme_send_external_auth_status(
Sunil Ravia04bd252022-05-02 22:54:18 -07001937 wpa_s,
1938 res == -2 ?
1939 le_to_host16(header->u.auth.status_code) :
1940 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001941 return;
1942 }
1943 if (res != 1)
1944 return;
1945
Sunil Ravi036cec52023-03-29 11:35:17 -07001946 if (sme_sae_set_pmk(wpa_s,
1947 wpa_s->sme.ext_ml_auth ?
1948 wpa_s->sme.ext_auth_ap_mld_addr :
1949 wpa_s->sme.ext_auth_bssid) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07001950 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001951 }
1952}
1953
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001954#endif /* CONFIG_SAE */
1955
1956
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001957void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
1958{
1959 struct wpa_ssid *ssid = wpa_s->current_ssid;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001960 int ie_offset = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001961
1962 if (ssid == NULL) {
1963 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1964 "when network is not selected");
1965 return;
1966 }
1967
1968 if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
1969 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1970 "when not in authenticating state");
1971 return;
1972 }
1973
Sunil Ravi77d572f2023-01-17 23:58:31 +00001974 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0 &&
1975 !(wpa_s->valid_links &&
1976 os_memcmp(wpa_s->ap_mld_addr, data->auth.peer, ETH_ALEN) == 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001977 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
1978 "unexpected peer " MACSTR,
1979 MAC2STR(data->auth.peer));
1980 return;
1981 }
1982
1983 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001984 " auth_type=%d auth_transaction=%d status_code=%d",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001985 MAC2STR(data->auth.peer), data->auth.auth_type,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001986 data->auth.auth_transaction, data->auth.status_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001987 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
1988 data->auth.ies, data->auth.ies_len);
1989
1990 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
1991
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001992#ifdef CONFIG_SAE
1993 if (data->auth.auth_type == WLAN_AUTH_SAE) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00001994 const u8 *addr = wpa_s->pending_bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001995 int res;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001996
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001997 res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
1998 data->auth.status_code, data->auth.ies,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001999 data->auth.ies_len, 0, data->auth.peer,
2000 &ie_offset);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002001 if (res < 0) {
2002 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2003 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2004
2005 }
2006 if (res != 1)
2007 return;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002008
Sunil Ravi77d572f2023-01-17 23:58:31 +00002009 if (wpa_s->valid_links)
2010 addr = wpa_s->ap_mld_addr;
2011
2012 if (sme_sae_set_pmk(wpa_s, addr) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002013 return;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002014 }
2015#endif /* CONFIG_SAE */
2016
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002017 if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002018 char *ie_txt = NULL;
2019
2020 if (data->auth.ies && data->auth.ies_len) {
2021 size_t buflen = 2 * data->auth.ies_len + 1;
2022 ie_txt = os_malloc(buflen);
2023 if (ie_txt) {
2024 wpa_snprintf_hex(ie_txt, buflen, data->auth.ies,
2025 data->auth.ies_len);
2026 }
2027 }
2028 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002029 " auth_type=%u auth_transaction=%u status_code=%u%s%s",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002030 MAC2STR(data->auth.peer), data->auth.auth_type,
2031 data->auth.auth_transaction, data->auth.status_code,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002032 ie_txt ? " ie=" : "",
2033 ie_txt ? ie_txt : "");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002034 os_free(ie_txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002035
Hai Shalomce48b4a2018-09-05 11:41:35 -07002036#ifdef CONFIG_FILS
2037 if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
2038 wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS)
2039 fils_connection_failure(wpa_s);
2040#endif /* CONFIG_FILS */
2041
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042 if (data->auth.status_code !=
2043 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
2044 wpa_s->sme.auth_alg == data->auth.auth_type ||
2045 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
2046 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002047 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002048 return;
2049 }
2050
Dmitry Shmidt97672262014-02-03 13:02:54 -08002051 wpas_connect_work_done(wpa_s);
2052
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002053 switch (data->auth.auth_type) {
2054 case WLAN_AUTH_OPEN:
2055 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
2056
2057 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
2058 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2059 wpa_s->current_ssid);
2060 return;
2061
2062 case WLAN_AUTH_SHARED_KEY:
2063 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
2064
2065 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
2066 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2067 wpa_s->current_ssid);
2068 return;
2069
2070 default:
2071 return;
2072 }
2073 }
2074
2075#ifdef CONFIG_IEEE80211R
2076 if (data->auth.auth_type == WLAN_AUTH_FT) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002077 const u8 *ric_ies = NULL;
2078 size_t ric_ies_len = 0;
2079
2080 if (wpa_s->ric_ies) {
2081 ric_ies = wpabuf_head(wpa_s->ric_ies);
2082 ric_ies_len = wpabuf_len(wpa_s->ric_ies);
2083 }
Dmitry Shmidt41712582015-06-29 11:02:15 -07002084 if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
2085 data->auth.ies_len, 0,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002086 data->auth.peer,
2087 ric_ies, ric_ies_len) < 0) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07002088 wpa_dbg(wpa_s, MSG_DEBUG,
2089 "SME: FT Authentication response processing failed");
2090 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2091 MACSTR
2092 " reason=%d locally_generated=1",
2093 MAC2STR(wpa_s->pending_bssid),
2094 WLAN_REASON_DEAUTH_LEAVING);
2095 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2096 wpa_supplicant_mark_disassoc(wpa_s);
2097 return;
2098 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002099 }
2100#endif /* CONFIG_IEEE80211R */
2101
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002102#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002103 if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
2104 data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
2105 u16 expect_auth_type;
2106
2107 expect_auth_type = wpa_s->sme.auth_alg ==
2108 WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
2109 WLAN_AUTH_FILS_SK;
2110 if (data->auth.auth_type != expect_auth_type) {
2111 wpa_dbg(wpa_s, MSG_DEBUG,
2112 "SME: FILS Authentication response used different auth alg (%u; expected %u)",
2113 data->auth.auth_type, expect_auth_type);
2114 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2115 MACSTR
2116 " reason=%d locally_generated=1",
2117 MAC2STR(wpa_s->pending_bssid),
2118 WLAN_REASON_DEAUTH_LEAVING);
2119 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2120 wpa_supplicant_mark_disassoc(wpa_s);
2121 return;
2122 }
2123
2124 if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
2125 data->auth.ies, data->auth.ies_len) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002126 wpa_dbg(wpa_s, MSG_DEBUG,
2127 "SME: FILS Authentication response processing failed");
2128 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2129 MACSTR
2130 " reason=%d locally_generated=1",
2131 MAC2STR(wpa_s->pending_bssid),
2132 WLAN_REASON_DEAUTH_LEAVING);
2133 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2134 wpa_supplicant_mark_disassoc(wpa_s);
2135 return;
2136 }
2137 }
2138#endif /* CONFIG_FILS */
2139
Sunil Ravi77d572f2023-01-17 23:58:31 +00002140 /* TODO: Support additional auth_type values as well */
2141 if (data->auth.auth_type == WLAN_AUTH_OPEN ||
2142 data->auth.auth_type == WLAN_AUTH_SAE)
2143 wpas_sme_ml_auth(wpa_s, data, ie_offset);
2144
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002145 sme_associate(wpa_s, ssid->mode, data->auth.peer,
2146 data->auth.auth_type);
2147}
2148
2149
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002150#ifdef CONFIG_IEEE80211R
2151static void remove_ie(u8 *buf, size_t *len, u8 eid)
2152{
2153 u8 *pos, *next, *end;
2154
2155 pos = (u8 *) get_ie(buf, *len, eid);
2156 if (pos) {
2157 next = pos + 2 + pos[1];
2158 end = buf + *len;
2159 *len -= 2 + pos[1];
2160 os_memmove(pos, next, end - next);
2161 }
2162}
2163#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002164
2165
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002166void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
2167 const u8 *bssid, u16 auth_type)
2168{
2169 struct wpa_driver_associate_params params;
2170 struct ieee802_11_elems elems;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002171 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002172#ifdef CONFIG_FILS
2173 u8 nonces[2 * FILS_NONCE_LEN];
2174#endif /* CONFIG_FILS */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002175#ifdef CONFIG_HT_OVERRIDES
2176 struct ieee80211_ht_capabilities htcaps;
2177 struct ieee80211_ht_capabilities htcaps_mask;
2178#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002179#ifdef CONFIG_VHT_OVERRIDES
2180 struct ieee80211_vht_capabilities vhtcaps;
2181 struct ieee80211_vht_capabilities vhtcaps_mask;
2182#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002183
2184 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002185
2186#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002187 if (auth_type == WLAN_AUTH_FILS_SK ||
2188 auth_type == WLAN_AUTH_FILS_SK_PFS) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002189 struct wpabuf *buf;
2190 const u8 *snonce, *anonce;
Paul Stewart092955c2017-02-06 09:13:09 -08002191 const unsigned int max_hlp = 20;
2192 struct wpabuf *hlp[max_hlp];
2193 unsigned int i, num_hlp = 0;
2194 struct fils_hlp_req *req;
2195
2196 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2197 list) {
2198 hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
2199 wpabuf_len(req->pkt));
2200 if (!hlp[num_hlp])
2201 break;
2202 wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
2203 wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
2204 ETH_ALEN);
2205 wpabuf_put_data(hlp[num_hlp],
2206 "\xaa\xaa\x03\x00\x00\x00", 6);
2207 wpabuf_put_buf(hlp[num_hlp], req->pkt);
2208 num_hlp++;
2209 if (num_hlp >= max_hlp)
2210 break;
2211 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002212
2213 buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
2214 &params.fils_kek_len, &snonce,
Paul Stewart092955c2017-02-06 09:13:09 -08002215 &anonce,
2216 (const struct wpabuf **) hlp,
2217 num_hlp);
2218 for (i = 0; i < num_hlp; i++)
2219 wpabuf_free(hlp[i]);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002220 if (!buf)
2221 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002222 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req before FILS elements",
2223 wpa_s->sme.assoc_req_ie,
2224 wpa_s->sme.assoc_req_ie_len);
2225#ifdef CONFIG_IEEE80211R
2226 if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
2227 /* Remove RSNE and MDE to allow them to be overridden
2228 * with FILS+FT specific values from
2229 * fils_build_assoc_req(). */
2230 remove_ie(wpa_s->sme.assoc_req_ie,
2231 &wpa_s->sme.assoc_req_ie_len,
2232 WLAN_EID_RSN);
2233 wpa_hexdump(MSG_DEBUG,
2234 "FILS: assoc_req after RSNE removal",
2235 wpa_s->sme.assoc_req_ie,
2236 wpa_s->sme.assoc_req_ie_len);
2237 remove_ie(wpa_s->sme.assoc_req_ie,
2238 &wpa_s->sme.assoc_req_ie_len,
2239 WLAN_EID_MOBILITY_DOMAIN);
2240 wpa_hexdump(MSG_DEBUG,
2241 "FILS: assoc_req after MDE removal",
2242 wpa_s->sme.assoc_req_ie,
2243 wpa_s->sme.assoc_req_ie_len);
2244 }
2245#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002246 /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
2247 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
2248 sizeof(wpa_s->sme.assoc_req_ie)) {
2249 wpa_printf(MSG_ERROR,
2250 "FILS: Not enough buffer room for own AssocReq elements");
2251 wpabuf_free(buf);
2252 return;
2253 }
2254 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2255 wpabuf_head(buf), wpabuf_len(buf));
2256 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
2257 wpabuf_free(buf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002258 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req after FILS elements",
2259 wpa_s->sme.assoc_req_ie,
2260 wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002261
2262 os_memcpy(nonces, snonce, FILS_NONCE_LEN);
2263 os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
2264 params.fils_nonces = nonces;
2265 params.fils_nonces_len = sizeof(nonces);
2266 }
2267#endif /* CONFIG_FILS */
2268
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002269#ifdef CONFIG_OWE
2270#ifdef CONFIG_TESTING_OPTIONS
2271 if (get_ie_ext(wpa_s->sme.assoc_req_ie, wpa_s->sme.assoc_req_ie_len,
2272 WLAN_EID_EXT_OWE_DH_PARAM)) {
2273 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2274 } else
2275#endif /* CONFIG_TESTING_OPTIONS */
2276 if (auth_type == WLAN_AUTH_OPEN &&
2277 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2278 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002279 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002280
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002281 if (ssid && ssid->owe_group) {
2282 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08002283 } else if (wpa_s->assoc_status_code ==
2284 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002285 if (wpa_s->last_owe_group == 19)
2286 group = 20;
2287 else if (wpa_s->last_owe_group == 20)
2288 group = 21;
2289 else
2290 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002291 } else {
2292 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002293 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002294
Roshan Pius3a1667e2018-07-03 15:17:14 -07002295 wpa_s->last_owe_group = group;
2296 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002297 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2298 if (!owe_ie) {
2299 wpa_printf(MSG_ERROR,
2300 "OWE: Failed to build IE for Association Request frame");
2301 return;
2302 }
2303 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(owe_ie) >
2304 sizeof(wpa_s->sme.assoc_req_ie)) {
2305 wpa_printf(MSG_ERROR,
2306 "OWE: Not enough buffer room for own Association Request frame elements");
2307 wpabuf_free(owe_ie);
2308 return;
2309 }
2310 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2311 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2312 wpa_s->sme.assoc_req_ie_len += wpabuf_len(owe_ie);
2313 wpabuf_free(owe_ie);
2314 }
2315#endif /* CONFIG_OWE */
2316
Hai Shalom021b0b52019-04-10 11:17:58 -07002317#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002318 if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid &&
2319 ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 &&
2320 !ssid->dpp_pfs_fallback) {
2321 struct rsn_pmksa_cache_entry *pmksa;
2322
2323 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2324 if (!pmksa || !pmksa->dpp_pfs)
2325 goto pfs_fail;
Hai Shalom021b0b52019-04-10 11:17:58 -07002326
2327 dpp_pfs_free(wpa_s->dpp_pfs);
2328 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
2329 ssid->dpp_netaccesskey_len);
2330 if (!wpa_s->dpp_pfs) {
2331 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
2332 /* Try to continue without PFS */
2333 goto pfs_fail;
2334 }
2335 if (wpa_s->sme.assoc_req_ie_len +
2336 wpabuf_len(wpa_s->dpp_pfs->ie) >
2337 sizeof(wpa_s->sme.assoc_req_ie)) {
2338 wpa_printf(MSG_ERROR,
2339 "DPP: Not enough buffer room for own Association Request frame elements");
2340 dpp_pfs_free(wpa_s->dpp_pfs);
2341 wpa_s->dpp_pfs = NULL;
2342 goto pfs_fail;
2343 }
2344 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2345 wpabuf_head(wpa_s->dpp_pfs->ie),
2346 wpabuf_len(wpa_s->dpp_pfs->ie));
2347 wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
2348 }
2349pfs_fail:
2350#endif /* CONFIG_DPP2 */
2351
Hai Shalom899fcc72020-10-19 14:38:18 -07002352 wpa_s->mscs_setup_done = false;
Hai Shalom60840252021-02-19 19:02:11 -08002353 if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
2354 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002355 struct wpabuf *mscs_ie;
2356 size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len;
2357
Hai Shalom899fcc72020-10-19 14:38:18 -07002358 buf_len = 3 + /* MSCS descriptor IE header */
2359 1 + /* Request type */
2360 2 + /* User priority control */
2361 4 + /* Stream timeout */
2362 3 + /* TCLAS Mask IE header */
2363 wpa_s->robust_av.frame_classifier_len;
2364 mscs_ie = wpabuf_alloc(buf_len);
2365 if (!mscs_ie) {
2366 wpa_printf(MSG_INFO,
2367 "MSCS: Failed to allocate MSCS IE");
2368 goto mscs_fail;
2369 }
2370
2371 wpa_ie_len = &wpa_s->sme.assoc_req_ie_len;
2372 max_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
2373 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
2374 if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) {
2375 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
2376 mscs_ie_len = wpabuf_len(mscs_ie);
2377 os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len,
2378 wpabuf_head(mscs_ie), mscs_ie_len);
2379 *wpa_ie_len += mscs_ie_len;
2380 }
2381
2382 wpabuf_free(mscs_ie);
2383 }
2384mscs_fail:
2385
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002386 if (ssid && ssid->multi_ap_backhaul_sta) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002387 size_t multi_ap_ie_len;
2388
2389 multi_ap_ie_len = add_multi_ap_ie(
2390 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2391 sizeof(wpa_s->sme.assoc_req_ie) -
2392 wpa_s->sme.assoc_req_ie_len,
2393 MULTI_AP_BACKHAUL_STA);
2394 if (multi_ap_ie_len == 0) {
2395 wpa_printf(MSG_ERROR,
2396 "Multi-AP: Failed to build Multi-AP IE");
2397 return;
2398 }
2399 wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
2400 }
2401
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402 params.bssid = bssid;
2403 params.ssid = wpa_s->sme.ssid;
2404 params.ssid_len = wpa_s->sme.ssid_len;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002405 params.freq.freq = wpa_s->sme.freq;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002406 params.bg_scan_period = ssid ? ssid->bg_scan_period : -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
2408 wpa_s->sme.assoc_req_ie : NULL;
2409 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08002410 wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
2411 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002412 params.pairwise_suite = wpa_s->pairwise_cipher;
2413 params.group_suite = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002414 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
Dmitry Shmidt15907092014-03-25 10:42:57 -07002415 params.key_mgmt_suite = wpa_s->key_mgmt;
2416 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002417#ifdef CONFIG_HT_OVERRIDES
2418 os_memset(&htcaps, 0, sizeof(htcaps));
2419 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2420 params.htcaps = (u8 *) &htcaps;
2421 params.htcaps_mask = (u8 *) &htcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002422 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002423#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002424#ifdef CONFIG_VHT_OVERRIDES
2425 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2426 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2427 params.vhtcaps = &vhtcaps;
2428 params.vhtcaps_mask = &vhtcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002429 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002430#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07002431#ifdef CONFIG_HE_OVERRIDES
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002432 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
Hai Shalomfdcde762020-04-02 11:19:20 -07002433#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00002434 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002435#ifdef CONFIG_IEEE80211R
Hai Shalom74f70d42019-02-11 14:42:39 -08002436 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
2437 get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
2438 WLAN_EID_RIC_DATA)) {
2439 /* There seems to be a pretty inconvenient bug in the Linux
2440 * kernel IE splitting functionality when RIC is used. For now,
2441 * skip correct behavior in IE construction here (i.e., drop the
2442 * additional non-FT-specific IEs) to avoid kernel issues. This
2443 * is fine since RIC is used only for testing purposes in the
2444 * current implementation. */
2445 wpa_printf(MSG_INFO,
2446 "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002447 params.wpa_ie = wpa_s->sme.ft_ies;
2448 params.wpa_ie_len = wpa_s->sme.ft_ies_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08002449 } else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
2450 const u8 *rm_en, *pos, *end;
2451 size_t rm_en_len = 0;
2452 u8 *rm_en_dup = NULL, *wpos;
2453
2454 /* Remove RSNE, MDE, FTE to allow them to be overridden with
2455 * FT specific values */
2456 remove_ie(wpa_s->sme.assoc_req_ie,
2457 &wpa_s->sme.assoc_req_ie_len,
2458 WLAN_EID_RSN);
2459 remove_ie(wpa_s->sme.assoc_req_ie,
2460 &wpa_s->sme.assoc_req_ie_len,
2461 WLAN_EID_MOBILITY_DOMAIN);
2462 remove_ie(wpa_s->sme.assoc_req_ie,
2463 &wpa_s->sme.assoc_req_ie_len,
2464 WLAN_EID_FAST_BSS_TRANSITION);
2465 rm_en = get_ie(wpa_s->sme.assoc_req_ie,
2466 wpa_s->sme.assoc_req_ie_len,
2467 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2468 if (rm_en) {
2469 /* Need to remove RM Enabled Capabilities element as
2470 * well temporarily, so that it can be placed between
2471 * RSNE and MDE. */
2472 rm_en_len = 2 + rm_en[1];
2473 rm_en_dup = os_memdup(rm_en, rm_en_len);
2474 remove_ie(wpa_s->sme.assoc_req_ie,
2475 &wpa_s->sme.assoc_req_ie_len,
2476 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2477 }
2478 wpa_hexdump(MSG_DEBUG,
2479 "SME: Association Request IEs after FT IE removal",
2480 wpa_s->sme.assoc_req_ie,
2481 wpa_s->sme.assoc_req_ie_len);
2482 if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
2483 rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
2484 wpa_printf(MSG_ERROR,
2485 "SME: Not enough buffer room for FT IEs in Association Request frame");
2486 os_free(rm_en_dup);
2487 return;
2488 }
2489
2490 os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
2491 rm_en_len,
2492 wpa_s->sme.assoc_req_ie,
2493 wpa_s->sme.assoc_req_ie_len);
2494 pos = wpa_s->sme.ft_ies;
2495 end = pos + wpa_s->sme.ft_ies_len;
2496 wpos = wpa_s->sme.assoc_req_ie;
2497 if (*pos == WLAN_EID_RSN) {
2498 os_memcpy(wpos, pos, 2 + pos[1]);
2499 wpos += 2 + pos[1];
2500 pos += 2 + pos[1];
2501 }
2502 if (rm_en_dup) {
2503 os_memcpy(wpos, rm_en_dup, rm_en_len);
2504 wpos += rm_en_len;
2505 os_free(rm_en_dup);
2506 }
2507 os_memcpy(wpos, pos, end - pos);
2508 wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
2509 rm_en_len;
2510 params.wpa_ie = wpa_s->sme.assoc_req_ie;
2511 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
2512 wpa_hexdump(MSG_DEBUG,
2513 "SME: Association Request IEs after FT override",
2514 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 }
2516#endif /* CONFIG_IEEE80211R */
2517 params.mode = mode;
2518 params.mgmt_frame_protection = wpa_s->sme.mfp;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002519 params.rrm_used = wpa_s->rrm.rrm_used;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 if (wpa_s->sme.prev_bssid_set)
2521 params.prev_bssid = wpa_s->sme.prev_bssid;
2522
2523 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2524 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
2525 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002526 params.freq.freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527
2528 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2529
2530 if (params.wpa_ie == NULL ||
2531 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
2532 < 0) {
2533 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
2534 os_memset(&elems, 0, sizeof(elems));
2535 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002536 if (elems.rsn_ie) {
2537 params.wpa_proto = WPA_PROTO_RSN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
2539 elems.rsn_ie_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002540 } else if (elems.wpa_ie) {
2541 params.wpa_proto = WPA_PROTO_WPA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
2543 elems.wpa_ie_len + 2);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002544 } else if (elems.osen) {
2545 params.wpa_proto = WPA_PROTO_OSEN;
2546 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
2547 elems.osen_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002548 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002549 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07002550 if (elems.rsnxe)
2551 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, elems.rsnxe - 2,
2552 elems.rsnxe_len + 2);
2553 else
2554 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002555 if (ssid && ssid->p2p_group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002556 params.p2p = 1;
2557
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002558 if (wpa_s->p2pdev->set_sta_uapsd)
2559 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560 else
2561 params.uapsd = -1;
2562
Sunil Ravi77d572f2023-01-17 23:58:31 +00002563 if (wpa_s->valid_links) {
2564 unsigned int i;
2565
2566 wpa_printf(MSG_DEBUG,
2567 "MLD: In association. assoc_link_id=%u, valid_links=0x%x",
2568 wpa_s->mlo_assoc_link_id, wpa_s->valid_links);
2569
2570 params.mld_params.mld_addr = wpa_s->ap_mld_addr;
2571 params.mld_params.valid_links = wpa_s->valid_links;
2572 params.mld_params.assoc_link_id = wpa_s->mlo_assoc_link_id;
2573 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
2574 if (!(wpa_s->valid_links & BIT(i)))
2575 continue;
2576
2577 params.mld_params.mld_links[i].bssid =
2578 wpa_s->links[i].bssid;
2579 params.mld_params.mld_links[i].freq =
2580 wpa_s->links[i].freq;
2581
2582 wpa_printf(MSG_DEBUG, "MLD: id=%u, freq=%d, " MACSTR,
2583 i, wpa_s->links[i].freq,
2584 MAC2STR(wpa_s->links[i].bssid));
2585 }
2586 }
2587
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002588 if (wpa_drv_associate(wpa_s, &params) < 0) {
2589 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
2590 "driver failed");
2591 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002592 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002593 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2594 return;
2595 }
2596
2597 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
2598 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002599
2600#ifdef CONFIG_TESTING_OPTIONS
2601 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
2602 wpa_s->last_assoc_req_wpa_ie = NULL;
2603 if (params.wpa_ie)
2604 wpa_s->last_assoc_req_wpa_ie =
2605 wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len);
2606#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607}
2608
2609
2610int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
2611 const u8 *ies, size_t ies_len)
2612{
2613 if (md == NULL || ies == NULL) {
2614 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
2615 os_free(wpa_s->sme.ft_ies);
2616 wpa_s->sme.ft_ies = NULL;
2617 wpa_s->sme.ft_ies_len = 0;
2618 wpa_s->sme.ft_used = 0;
2619 return 0;
2620 }
2621
2622 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
2623 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
2624 os_free(wpa_s->sme.ft_ies);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002625 wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626 if (wpa_s->sme.ft_ies == NULL)
2627 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628 wpa_s->sme.ft_ies_len = ies_len;
2629 return 0;
2630}
2631
2632
2633static void sme_deauth(struct wpa_supplicant *wpa_s)
2634{
2635 int bssid_changed;
2636
2637 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2638
2639 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
2640 WLAN_REASON_DEAUTH_LEAVING) < 0) {
2641 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
2642 "failed");
2643 }
2644 wpa_s->sme.prev_bssid_set = 0;
2645
2646 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2647 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2648 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2649 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2650 if (bssid_changed)
2651 wpas_notify_bssid_changed(wpa_s);
2652}
2653
2654
2655void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
2656 union wpa_event_data *data)
2657{
2658 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
2659 "status code %d", MAC2STR(wpa_s->pending_bssid),
2660 data->assoc_reject.status_code);
2661
2662 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2663
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002664#ifdef CONFIG_SAE
2665 if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
2666 wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
2667 wpa_dbg(wpa_s, MSG_DEBUG,
2668 "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
2669 wpa_sm_aborted_cached(wpa_s->wpa);
2670 wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
2671 if (wpa_s->current_bss) {
2672 struct wpa_bss *bss = wpa_s->current_bss;
2673 struct wpa_ssid *ssid = wpa_s->current_ssid;
2674
2675 wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
2676 WLAN_REASON_DEAUTH_LEAVING);
2677 wpas_connect_work_done(wpa_s);
2678 wpa_supplicant_mark_disassoc(wpa_s);
2679 wpa_supplicant_connect(wpa_s, bss, ssid);
2680 return;
2681 }
2682 }
2683#endif /* CONFIG_SAE */
2684
Sunil Ravi77d572f2023-01-17 23:58:31 +00002685#ifdef CONFIG_DPP
2686 if (wpa_s->current_ssid &&
2687 wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
2688 !data->assoc_reject.timed_out &&
2689 data->assoc_reject.status_code == WLAN_STATUS_INVALID_PMKID) {
2690 struct rsn_pmksa_cache_entry *pmksa;
2691
2692 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2693 if (pmksa) {
2694 wpa_dbg(wpa_s, MSG_DEBUG,
2695 "DPP: Drop PMKSA cache entry for the BSS due to invalid PMKID report");
2696 wpa_sm_pmksa_cache_remove(wpa_s->wpa, pmksa);
2697 }
2698 wpa_sm_aborted_cached(wpa_s->wpa);
2699 if (wpa_s->current_bss) {
2700 struct wpa_bss *bss = wpa_s->current_bss;
2701 struct wpa_ssid *ssid = wpa_s->current_ssid;
2702
2703 wpa_dbg(wpa_s, MSG_DEBUG,
2704 "DPP: Try network introduction again");
2705 wpas_connect_work_done(wpa_s);
2706 wpa_supplicant_mark_disassoc(wpa_s);
2707 wpa_supplicant_connect(wpa_s, bss, ssid);
2708 return;
2709 }
2710 }
2711#endif /* CONFIG_DPP */
2712
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 /*
2714 * For now, unconditionally terminate the previous authentication. In
2715 * theory, this should not be needed, but mac80211 gets quite confused
2716 * if the authentication is left pending.. Some roaming cases might
2717 * benefit from using the previous authentication, so this could be
2718 * optimized in the future.
2719 */
2720 sme_deauth(wpa_s);
2721}
2722
2723
2724void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
2725 union wpa_event_data *data)
2726{
2727 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
2728 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002729 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002730}
2731
2732
2733void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
2734 union wpa_event_data *data)
2735{
2736 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
2737 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2738 wpa_supplicant_mark_disassoc(wpa_s);
2739}
2740
2741
2742void sme_event_disassoc(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002743 struct disassoc_info *info)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002744{
2745 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002746 if (wpa_s->sme.prev_bssid_set) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002747 /*
2748 * cfg80211/mac80211 can get into somewhat confused state if
2749 * the AP only disassociates us and leaves us in authenticated
2750 * state. For now, force the state to be cleared to avoid
2751 * confusing errors if we try to associate with the AP again.
2752 */
2753 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
2754 "driver state");
2755 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
2756 WLAN_REASON_DEAUTH_LEAVING);
2757 }
2758}
2759
2760
2761static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
2762{
2763 struct wpa_supplicant *wpa_s = eloop_ctx;
2764 if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
2765 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
2766 sme_deauth(wpa_s);
2767 }
2768}
2769
2770
2771static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
2772{
2773 struct wpa_supplicant *wpa_s = eloop_ctx;
2774 if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2775 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
2776 sme_deauth(wpa_s);
2777 }
2778}
2779
2780
2781void sme_state_changed(struct wpa_supplicant *wpa_s)
2782{
2783 /* Make sure timers are cleaned up appropriately. */
2784 if (wpa_s->wpa_state != WPA_ASSOCIATING)
2785 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2786 if (wpa_s->wpa_state != WPA_AUTHENTICATING)
2787 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2788}
2789
2790
2791void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
2792 const u8 *prev_pending_bssid)
2793{
2794 /*
2795 * mac80211-workaround to force deauth on failed auth cmd,
2796 * requires us to remain in authenticating state to allow the
2797 * second authentication attempt to be continued properly.
2798 */
2799 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
2800 "to proceed after disconnection event");
2801 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
2802 os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
2803
2804 /*
2805 * Re-arm authentication timer in case auth fails for whatever reason.
2806 */
2807 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2808 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
2809 NULL);
2810}
2811
2812
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002813void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
2814{
2815 wpa_s->sme.prev_bssid_set = 0;
2816#ifdef CONFIG_SAE
2817 wpabuf_free(wpa_s->sme.sae_token);
2818 wpa_s->sme.sae_token = NULL;
2819 sae_clear_data(&wpa_s->sme.sae);
2820#endif /* CONFIG_SAE */
2821#ifdef CONFIG_IEEE80211R
Roshan Pius3a1667e2018-07-03 15:17:14 -07002822 if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002823 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
2824#endif /* CONFIG_IEEE80211R */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002825 sme_stop_sa_query(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002826}
2827
2828
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002829void sme_deinit(struct wpa_supplicant *wpa_s)
2830{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002831 sme_clear_on_disassoc(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002832#ifdef CONFIG_SAE
2833 os_free(wpa_s->sme.sae_rejected_groups);
2834 wpa_s->sme.sae_rejected_groups = NULL;
2835#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002836
2837 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2838 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002839 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
2840}
2841
2842
2843static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
2844 const u8 *chan_list, u8 num_channels,
2845 u8 num_intol)
2846{
2847 struct ieee80211_2040_bss_coex_ie *bc_ie;
2848 struct ieee80211_2040_intol_chan_report *ic_report;
2849 struct wpabuf *buf;
2850
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002851 wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
2852 " (num_channels=%u num_intol=%u)",
2853 MAC2STR(wpa_s->bssid), num_channels, num_intol);
2854 wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
2855 chan_list, num_channels);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002856
2857 buf = wpabuf_alloc(2 + /* action.category + action_code */
2858 sizeof(struct ieee80211_2040_bss_coex_ie) +
2859 sizeof(struct ieee80211_2040_intol_chan_report) +
2860 num_channels);
2861 if (buf == NULL)
2862 return;
2863
2864 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
2865 wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
2866
2867 bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
2868 bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
2869 bc_ie->length = 1;
2870 if (num_intol)
2871 bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
2872
2873 if (num_channels > 0) {
2874 ic_report = wpabuf_put(buf, sizeof(*ic_report));
2875 ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
2876 ic_report->length = num_channels + 1;
2877 ic_report->op_class = 0;
2878 os_memcpy(wpabuf_put(buf, num_channels), chan_list,
2879 num_channels);
2880 }
2881
2882 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
2883 wpa_s->own_addr, wpa_s->bssid,
2884 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
2885 wpa_msg(wpa_s, MSG_INFO,
2886 "SME: Failed to send 20/40 BSS Coexistence frame");
2887 }
2888
2889 wpabuf_free(buf);
2890}
2891
2892
Hai Shaloma20dcd72022-02-04 13:43:00 -08002893int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002894{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002895 struct wpa_bss *bss;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002896 const u8 *ie;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002897 u16 ht_cap;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002898 u8 chan_list[P2P_MAX_CHANNELS], channel;
2899 u8 num_channels = 0, num_intol = 0, i;
2900
2901 if (!wpa_s->sme.sched_obss_scan)
2902 return 0;
2903
2904 wpa_s->sme.sched_obss_scan = 0;
2905 if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
2906 return 1;
2907
2908 /*
2909 * Check whether AP uses regulatory triplet or channel triplet in
2910 * country info. Right now the operating class of the BSS channel
2911 * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
2912 * based on the assumption that operating class triplet is not used in
2913 * beacon frame. If the First Channel Number/Operating Extension
2914 * Identifier octet has a positive integer value of 201 or greater,
2915 * then its operating class triplet.
2916 *
2917 * TODO: If Supported Operating Classes element is present in beacon
2918 * frame, have to lookup operating class in Annex E and fill them in
2919 * 2040 coex frame.
2920 */
2921 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
2922 if (ie && (ie[1] >= 6) && (ie[5] >= 201))
2923 return 1;
2924
2925 os_memset(chan_list, 0, sizeof(chan_list));
2926
Hai Shaloma20dcd72022-02-04 13:43:00 -08002927 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002928 /* Skip other band bss */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002929 enum hostapd_hw_mode mode;
Dmitry Shmidt4b060592013-04-29 16:42:49 -07002930 mode = ieee80211_freq_to_chan(bss->freq, &channel);
2931 if (mode != HOSTAPD_MODE_IEEE80211G &&
2932 mode != HOSTAPD_MODE_IEEE80211B)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002933 continue;
2934
Hai Shaloma20dcd72022-02-04 13:43:00 -08002935 ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
2936 ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
2937 wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
2938 " freq=%u chan=%u ht_cap=0x%x",
2939 MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
2940
2941 if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
2942 if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002943 num_intol++;
2944
Dmitry Shmidt04949592012-07-19 12:16:46 -07002945 /* Check whether the channel is already considered */
2946 for (i = 0; i < num_channels; i++) {
2947 if (channel == chan_list[i])
2948 break;
2949 }
2950 if (i != num_channels)
2951 continue;
2952
Dmitry Shmidt04949592012-07-19 12:16:46 -07002953 chan_list[num_channels++] = channel;
2954 }
2955 }
2956
2957 sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
2958 return 1;
2959}
2960
2961
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002962static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
2963 struct wpa_driver_scan_params *params)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002964{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002965 /* Include only affected channels */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002966 struct hostapd_hw_modes *mode;
2967 int count, i;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002968 int start, end;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002969
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002970 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08002971 HOSTAPD_MODE_IEEE80211G, false);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002972 if (mode == NULL) {
2973 /* No channels supported in this band - use empty list */
2974 params->freqs = os_zalloc(sizeof(int));
2975 return;
2976 }
2977
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002978 if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
2979 wpa_s->current_bss) {
2980 const u8 *ie;
2981
2982 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
2983 if (ie && ie[1] >= 2) {
2984 u8 o;
2985
2986 o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
2987 if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
2988 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
2989 else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
2990 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
2991 }
2992 }
2993
2994 start = wpa_s->assoc_freq - 10;
2995 end = wpa_s->assoc_freq + 10;
2996 switch (wpa_s->sme.ht_sec_chan) {
2997 case HT_SEC_CHAN_UNKNOWN:
2998 /* HT40+ possible on channels 1..9 */
2999 if (wpa_s->assoc_freq <= 2452)
3000 start -= 20;
3001 /* HT40- possible on channels 5-13 */
3002 if (wpa_s->assoc_freq >= 2432)
3003 end += 20;
3004 break;
3005 case HT_SEC_CHAN_ABOVE:
3006 end += 20;
3007 break;
3008 case HT_SEC_CHAN_BELOW:
3009 start -= 20;
3010 break;
3011 }
3012 wpa_printf(MSG_DEBUG,
3013 "OBSS: assoc_freq %d possible affected range %d-%d",
3014 wpa_s->assoc_freq, start, end);
3015
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003016 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
Dmitry Shmidt04949592012-07-19 12:16:46 -07003017 if (params->freqs == NULL)
3018 return;
3019 for (count = 0, i = 0; i < mode->num_channels; i++) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003020 int freq;
3021
Dmitry Shmidt04949592012-07-19 12:16:46 -07003022 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
3023 continue;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003024 freq = mode->channels[i].freq;
3025 if (freq - 10 >= end || freq + 10 <= start)
3026 continue; /* not affected */
3027 params->freqs[count++] = freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003028 }
3029}
3030
3031
3032static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
3033{
3034 struct wpa_supplicant *wpa_s = eloop_ctx;
3035 struct wpa_driver_scan_params params;
3036
3037 if (!wpa_s->current_bss) {
3038 wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
3039 return;
3040 }
3041
3042 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003043 wpa_obss_scan_freqs_list(wpa_s, &params);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003044 params.low_priority = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003045 wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
3046
3047 if (wpa_supplicant_trigger_scan(wpa_s, &params))
3048 wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
3049 else
3050 wpa_s->sme.sched_obss_scan = 1;
3051 os_free(params.freqs);
3052
3053 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3054 sme_obss_scan_timeout, wpa_s, NULL);
3055}
3056
3057
3058void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
3059{
3060 const u8 *ie;
3061 struct wpa_bss *bss = wpa_s->current_bss;
3062 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003063 struct hostapd_hw_modes *hw_mode = NULL;
3064 int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003065
3066 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
3067 wpa_s->sme.sched_obss_scan = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003068 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003069 if (!enable)
3070 return;
3071
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003072 /*
3073 * Schedule OBSS scan if driver is using station SME in wpa_supplicant
3074 * or it expects OBSS scan to be performed by wpa_supplicant.
3075 */
3076 if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
3077 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
Hai Shalom81f62d82019-07-22 12:10:00 -07003078 ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003079 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003080
Hai Shaloma20dcd72022-02-04 13:43:00 -08003081#ifdef CONFIG_HT_OVERRIDES
3082 /* No need for OBSS scan if HT40 is explicitly disabled */
3083 if (ssid->disable_ht40)
3084 return;
3085#endif /* CONFIG_HT_OVERRIDES */
3086
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003087 if (!wpa_s->hw.modes)
3088 return;
3089
3090 /* only HT caps in 11g mode are relevant */
3091 for (i = 0; i < wpa_s->hw.num_modes; i++) {
3092 hw_mode = &wpa_s->hw.modes[i];
3093 if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
3094 break;
3095 }
3096
3097 /* Driver does not support HT40 for 11g or doesn't have 11g. */
3098 if (i == wpa_s->hw.num_modes || !hw_mode ||
3099 !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3100 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003101
3102 if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
3103 return; /* Not associated on 2.4 GHz band */
3104
3105 /* Check whether AP supports HT40 */
3106 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
3107 if (!ie || ie[1] < 2 ||
3108 !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3109 return; /* AP does not support HT40 */
3110
3111 ie = wpa_bss_get_ie(wpa_s->current_bss,
3112 WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
3113 if (!ie || ie[1] < 14)
3114 return; /* AP does not request OBSS scans */
3115
3116 wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
3117 if (wpa_s->sme.obss_scan_int < 10) {
3118 wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
3119 "replaced with the minimum 10 sec",
3120 wpa_s->sme.obss_scan_int);
3121 wpa_s->sme.obss_scan_int = 10;
3122 }
3123 wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
3124 wpa_s->sme.obss_scan_int);
3125 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3126 sme_obss_scan_timeout, wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003127}
3128
3129
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003130static const unsigned int sa_query_max_timeout = 1000;
3131static const unsigned int sa_query_retry_timeout = 201;
Hai Shalom74f70d42019-02-11 14:42:39 -08003132static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003133
3134static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
3135{
3136 u32 tu;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003137 struct os_reltime now, passed;
3138 os_get_reltime(&now);
3139 os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003140 tu = (passed.sec * 1000000 + passed.usec) / 1024;
3141 if (sa_query_max_timeout < tu) {
3142 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
3143 sme_stop_sa_query(wpa_s);
3144 wpa_supplicant_deauthenticate(
3145 wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
3146 return 1;
3147 }
3148
3149 return 0;
3150}
3151
3152
3153static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
3154 const u8 *trans_id)
3155{
Hai Shalom74f70d42019-02-11 14:42:39 -08003156 u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3157 u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3158
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003159 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
3160 MACSTR, MAC2STR(wpa_s->bssid));
3161 wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
3162 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
3163 req[0] = WLAN_ACTION_SA_QUERY;
3164 req[1] = WLAN_SA_QUERY_REQUEST;
3165 os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08003166
3167#ifdef CONFIG_OCV
3168 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3169 struct wpa_channel_info ci;
3170
3171 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3172 wpa_printf(MSG_WARNING,
3173 "Failed to get channel info for OCI element in SA Query Request frame");
3174 return;
3175 }
3176
Hai Shalom899fcc72020-10-19 14:38:18 -07003177#ifdef CONFIG_TESTING_OPTIONS
3178 if (wpa_s->oci_freq_override_saquery_req) {
3179 wpa_printf(MSG_INFO,
3180 "TEST: Override SA Query Request OCI frequency %d -> %d MHz",
3181 ci.frequency,
3182 wpa_s->oci_freq_override_saquery_req);
3183 ci.frequency = wpa_s->oci_freq_override_saquery_req;
3184 }
3185#endif /* CONFIG_TESTING_OPTIONS */
3186
Hai Shalom74f70d42019-02-11 14:42:39 -08003187 if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
3188 return;
3189
3190 req_len += OCV_OCI_EXTENDED_LEN;
3191 }
3192#endif /* CONFIG_OCV */
3193
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003194 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3195 wpa_s->own_addr, wpa_s->bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08003196 req, req_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003197 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
3198 "Request");
3199}
3200
3201
3202static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
3203{
3204 struct wpa_supplicant *wpa_s = eloop_ctx;
3205 unsigned int timeout, sec, usec;
3206 u8 *trans_id, *nbuf;
3207
3208 if (wpa_s->sme.sa_query_count > 0 &&
3209 sme_check_sa_query_timeout(wpa_s))
3210 return;
3211
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003212 nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
3213 wpa_s->sme.sa_query_count + 1,
3214 WLAN_SA_QUERY_TR_ID_LEN);
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003215 if (nbuf == NULL) {
3216 sme_stop_sa_query(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003217 return;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003218 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003219 if (wpa_s->sme.sa_query_count == 0) {
3220 /* Starting a new SA Query procedure */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003221 os_get_reltime(&wpa_s->sme.sa_query_start);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003222 }
3223 trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
3224 wpa_s->sme.sa_query_trans_id = nbuf;
3225 wpa_s->sme.sa_query_count++;
3226
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003227 if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
3228 wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003229 sme_stop_sa_query(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003230 return;
3231 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003232
3233 timeout = sa_query_retry_timeout;
3234 sec = ((timeout / 1000) * 1024) / 1000;
3235 usec = (timeout % 1000) * 1024;
3236 eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
3237
3238 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
3239 wpa_s->sme.sa_query_count);
3240
3241 sme_send_sa_query_req(wpa_s, trans_id);
3242}
3243
3244
3245static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
3246{
3247 sme_sa_query_timer(wpa_s, NULL);
3248}
3249
3250
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003251static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003252{
Hai Shalom5f92bc92019-04-18 11:54:11 -07003253 if (wpa_s->sme.sa_query_trans_id)
3254 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003255 eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
3256 os_free(wpa_s->sme.sa_query_trans_id);
3257 wpa_s->sme.sa_query_trans_id = NULL;
3258 wpa_s->sme.sa_query_count = 0;
3259}
3260
3261
3262void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
3263 const u8 *da, u16 reason_code)
3264{
3265 struct wpa_ssid *ssid;
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003266 struct os_reltime now;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003267
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003268 if (wpa_s->wpa_state != WPA_COMPLETED)
3269 return;
3270 ssid = wpa_s->current_ssid;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003271 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003272 return;
3273 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
3274 return;
3275 if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
3276 reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
3277 return;
3278 if (wpa_s->sme.sa_query_count > 0)
3279 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07003280#ifdef CONFIG_TESTING_OPTIONS
3281 if (wpa_s->disable_sa_query)
3282 return;
3283#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003284
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003285 os_get_reltime(&now);
3286 if (wpa_s->sme.last_unprot_disconnect.sec &&
3287 !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
3288 return; /* limit SA Query procedure frequency */
3289 wpa_s->sme.last_unprot_disconnect = now;
3290
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003291 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
3292 "possible AP/STA state mismatch - trigger SA Query");
3293 sme_start_sa_query(wpa_s);
3294}
3295
3296
Hai Shalom74f70d42019-02-11 14:42:39 -08003297void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
3298{
3299 unsigned int usec;
3300 u32 _rand;
3301
3302 if (wpa_s->wpa_state != WPA_COMPLETED ||
3303 !wpa_sm_ocv_enabled(wpa_s->wpa))
3304 return;
3305
3306 wpa_dbg(wpa_s, MSG_DEBUG,
3307 "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
3308 sme_stop_sa_query(wpa_s);
3309
3310 if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
3311 _rand = os_random();
3312 usec = _rand % (sa_query_ch_switch_max_delay + 1);
3313 eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
3314}
3315
3316
3317static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
3318 const u8 *sa, const u8 *data,
3319 size_t len)
3320{
3321 u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3322 u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3323
3324 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
3325 MACSTR, MAC2STR(wpa_s->bssid));
3326
3327 resp[0] = WLAN_ACTION_SA_QUERY;
3328 resp[1] = WLAN_SA_QUERY_RESPONSE;
3329 os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
3330
3331#ifdef CONFIG_OCV
3332 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3333 struct wpa_channel_info ci;
3334
3335 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3336 wpa_printf(MSG_WARNING,
3337 "Failed to get channel info for OCI element in SA Query Response frame");
3338 return;
3339 }
3340
Hai Shalom899fcc72020-10-19 14:38:18 -07003341#ifdef CONFIG_TESTING_OPTIONS
3342 if (wpa_s->oci_freq_override_saquery_resp) {
3343 wpa_printf(MSG_INFO,
3344 "TEST: Override SA Query Response OCI frequency %d -> %d MHz",
3345 ci.frequency,
3346 wpa_s->oci_freq_override_saquery_resp);
3347 ci.frequency = wpa_s->oci_freq_override_saquery_resp;
3348 }
3349#endif /* CONFIG_TESTING_OPTIONS */
3350
Hai Shalom74f70d42019-02-11 14:42:39 -08003351 if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
3352 return;
3353
3354 resp_len += OCV_OCI_EXTENDED_LEN;
3355 }
3356#endif /* CONFIG_OCV */
3357
3358 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3359 wpa_s->own_addr, wpa_s->bssid,
3360 resp, resp_len, 0) < 0)
3361 wpa_msg(wpa_s, MSG_INFO,
3362 "SME: Failed to send SA Query Response");
3363}
3364
3365
3366static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
3367 const u8 *sa, const u8 *data,
3368 size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003369{
3370 int i;
3371
Hai Shalom74f70d42019-02-11 14:42:39 -08003372 if (!wpa_s->sme.sa_query_trans_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003373 return;
Hai Shalom74f70d42019-02-11 14:42:39 -08003374
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003375 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
3376 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3377
3378 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
3379 return;
3380
3381 for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
3382 if (os_memcmp(wpa_s->sme.sa_query_trans_id +
3383 i * WLAN_SA_QUERY_TR_ID_LEN,
3384 data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
3385 break;
3386 }
3387
3388 if (i >= wpa_s->sme.sa_query_count) {
3389 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
3390 "transaction identifier found");
3391 return;
3392 }
3393
3394 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
3395 "from " MACSTR, MAC2STR(sa));
3396 sme_stop_sa_query(wpa_s);
3397}
3398
Hai Shalom74f70d42019-02-11 14:42:39 -08003399
Hai Shaloma20dcd72022-02-04 13:43:00 -08003400void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
Hai Shalom74f70d42019-02-11 14:42:39 -08003401 const u8 *data, size_t len)
3402{
3403 if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
3404 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003405 if (is_multicast_ether_addr(da)) {
3406 wpa_printf(MSG_DEBUG,
3407 "IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
3408 MAC2STR(da), MAC2STR(sa));
3409 return;
3410 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003411
3412 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
3413 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3414
3415#ifdef CONFIG_OCV
3416 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3417 struct ieee802_11_elems elems;
3418 struct wpa_channel_info ci;
3419
3420 if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
3421 len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
3422 &elems, 1) == ParseFailed) {
3423 wpa_printf(MSG_DEBUG,
3424 "SA Query: Failed to parse elements");
3425 return;
3426 }
3427
3428 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3429 wpa_printf(MSG_WARNING,
3430 "Failed to get channel info to validate received OCI in SA Query Action frame");
3431 return;
3432 }
3433
3434 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
3435 channel_width_to_int(ci.chanwidth),
Hai Shalom899fcc72020-10-19 14:38:18 -07003436 ci.seg1_idx) != OCI_SUCCESS) {
3437 wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR
3438 " frame=saquery%s error=%s",
3439 MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ?
3440 "req" : "resp", ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003441 return;
3442 }
3443 }
3444#endif /* CONFIG_OCV */
3445
3446 if (data[0] == WLAN_SA_QUERY_REQUEST)
3447 sme_process_sa_query_request(wpa_s, sa, data, len);
3448 else if (data[0] == WLAN_SA_QUERY_RESPONSE)
3449 sme_process_sa_query_response(wpa_s, sa, data, len);
3450}