blob: 8068f1efd87b5019c0d145c6cbf57e8ab9d9c385 [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 Ravi640215c2023-06-28 23:08:09 +0000381static bool wpas_ml_element(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
382 struct wpa_ssid *ssid)
Sunil Ravi77d572f2023-01-17 23:58:31 +0000383{
384 struct wpabuf *mlbuf;
Sunil Ravi640215c2023-06-28 23:08:09 +0000385 const u8 *rnr_ie, *pos, *rsn_ie;
386 struct wpa_ie_data ie;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000387 u8 ml_ie_len, rnr_ie_len;
388 const struct ieee80211_eht_ml *eht_ml;
389 const struct eht_ml_basic_common_info *ml_basic_common_info;
390 u8 i;
391 const u16 control =
392 host_to_le16(MULTI_LINK_CONTROL_TYPE_BASIC |
393 BASIC_MULTI_LINK_CTRL_PRES_LINK_ID |
394 BASIC_MULTI_LINK_CTRL_PRES_BSS_PARAM_CH_COUNT |
395 BASIC_MULTI_LINK_CTRL_PRES_MLD_CAPA);
396 bool ret = false;
397
398 if (!(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO))
399 return false;
400
401 mlbuf = wpa_bss_defrag_mle(bss, MULTI_LINK_CONTROL_TYPE_BASIC);
402 if (!mlbuf) {
403 wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No ML element");
404 return false;
405 }
406
Sunil Ravi640215c2023-06-28 23:08:09 +0000407 rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN);
408 if (!rsn_ie || wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) {
409 wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RSN element");
410 goto out;
411 }
412
413 if (!(ie.capabilities & WPA_CAPABILITY_MFPC) ||
414 wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) {
415 wpa_dbg(wpa_s, MSG_DEBUG,
416 "MLD: No management frame protection");
417 goto out;
418 }
419
420 ie.key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK |
421 WPA_KEY_MGMT_PSK_SHA256);
422 if (!(ie.key_mgmt & ssid->key_mgmt)) {
423 wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No valid key management");
424 goto out;
425 }
426
Sunil Ravi77d572f2023-01-17 23:58:31 +0000427 ml_ie_len = wpabuf_len(mlbuf);
428
429 /* control + common info len + MLD address + MLD link information */
430 if (ml_ie_len < 2 + 1 + ETH_ALEN + 1)
431 goto out;
432
433 eht_ml = wpabuf_head(mlbuf);
434 if ((eht_ml->ml_control & control) != control) {
435 wpa_printf(MSG_DEBUG, "MLD: Unexpected ML element control=0x%x",
436 eht_ml->ml_control);
437 goto out;
438 }
439
440 ml_basic_common_info =
441 (const struct eht_ml_basic_common_info *) eht_ml->variable;
442
443 /* common info length should be valid (self, mld_addr, link_id) */
444 if (ml_basic_common_info->len < 1 + ETH_ALEN + 1)
445 goto out;
446
447 /* get the MLD address and MLD link ID */
448 os_memcpy(wpa_s->ap_mld_addr, ml_basic_common_info->mld_addr,
449 ETH_ALEN);
450 wpa_s->mlo_assoc_link_id = ml_basic_common_info->variable[0] &
451 EHT_ML_LINK_ID_MSK;
452
453 os_memcpy(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid, bss->bssid,
454 ETH_ALEN);
455 wpa_s->links[wpa_s->mlo_assoc_link_id].freq = bss->freq;
456
457 wpa_printf(MSG_DEBUG, "MLD: address=" MACSTR ", link ID=%u",
458 MAC2STR(wpa_s->ap_mld_addr), wpa_s->mlo_assoc_link_id);
459
460 wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
461
462 rnr_ie = wpa_bss_get_ie(bss, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
463 if (!rnr_ie) {
464 wpa_dbg(wpa_s, MSG_DEBUG, "MLD: No RNR element");
465 ret = true;
466 goto out;
467 }
468
469 rnr_ie_len = rnr_ie[1];
470 pos = rnr_ie + 2;
471
472 while (rnr_ie_len > sizeof(struct ieee80211_neighbor_ap_info)) {
473 const struct ieee80211_neighbor_ap_info *ap_info =
474 (const struct ieee80211_neighbor_ap_info *) pos;
475 const u8 *data = ap_info->data;
476 size_t len = sizeof(struct ieee80211_neighbor_ap_info) +
477 ap_info->tbtt_info_len;
478
479 wpa_printf(MSG_DEBUG, "MLD: op_class=%u, channel=%u",
480 ap_info->op_class, ap_info->channel);
481
482 if (len > rnr_ie_len)
483 break;
484
485 if (ap_info->tbtt_info_len < 16) {
486 rnr_ie_len -= len;
487 pos += len;
488 continue;
489 }
490
491 data += 13;
492
493 wpa_printf(MSG_DEBUG, "MLD: mld ID=%u, link ID=%u",
494 *data, *(data + 1) & 0xF);
495
496 if (*data) {
497 wpa_printf(MSG_DEBUG,
498 "MLD: Reported link not part of MLD");
499 } else {
500 struct wpa_bss *neigh_bss =
501 wpa_bss_get_bssid(wpa_s, ap_info->data + 1);
502 u8 link_id = *(data + 1) & 0xF;
503
504 if (neigh_bss) {
505 if (wpa_scan_res_match(wpa_s, 0, neigh_bss,
506 wpa_s->current_ssid,
507 1, 0)) {
508 wpa_s->valid_links |= BIT(link_id);
509 os_memcpy(wpa_s->links[link_id].bssid,
510 ap_info->data + 1, ETH_ALEN);
511 wpa_s->links[link_id].freq =
512 neigh_bss->freq;
513 } else {
514 wpa_printf(MSG_DEBUG,
515 "MLD: Neighbor doesn't match current SSID - skip link");
516 }
517 } else {
518 wpa_printf(MSG_DEBUG,
519 "MLD: Neighbor not found in scan");
520 }
521 }
522
523 rnr_ie_len -= len;
524 pos += len;
525 }
526
527 wpa_printf(MSG_DEBUG, "MLD: valid_links=0x%x", wpa_s->valid_links);
528
529 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
530 if (!(wpa_s->valid_links & BIT(i)))
531 continue;
532
533 wpa_printf(MSG_DEBUG, "MLD: link=%u, bssid=" MACSTR,
534 i, MAC2STR(wpa_s->links[i].bssid));
535 }
536
537 ret = true;
538out:
539 wpabuf_free(mlbuf);
540 return ret;
541}
542
543
544static void wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
545 union wpa_event_data *data,
546 int ie_offset)
547{
548 struct ieee802_11_elems elems;
549 const u8 *mld_addr;
Sunil Ravi640215c2023-06-28 23:08:09 +0000550 u16 status_code = data->auth.status_code;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000551
552 if (!wpa_s->valid_links)
553 return;
554
555 if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
556 data->auth.ies_len - ie_offset,
Sunil Ravi640215c2023-06-28 23:08:09 +0000557 &elems, 0) == ParseFailed) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000558 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
559 goto out;
560 }
561
562 if (!elems.basic_mle || !elems.basic_mle_len) {
563 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
Sunil Ravi640215c2023-06-28 23:08:09 +0000564 if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
565 status_code == WLAN_STATUS_SUCCESS ||
566 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
567 status_code == WLAN_STATUS_SAE_PK)
568 goto out;
569 /* Accept missing Multi-Link element in failed authentication
570 * cases. */
571 return;
Sunil Ravi77d572f2023-01-17 23:58:31 +0000572 }
573
574 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
575 if (!mld_addr)
576 goto out;
577
578 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
579
580 if (os_memcmp(wpa_s->ap_mld_addr, mld_addr, ETH_ALEN) != 0) {
581 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
582 MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
583 goto out;
584 }
585
586 return;
587out:
588 wpa_printf(MSG_DEBUG, "MLD: Authentication - clearing MLD state");
589 wpas_reset_mlo_info(wpa_s);
590}
591
592
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800593static void sme_send_authentication(struct wpa_supplicant *wpa_s,
594 struct wpa_bss *bss, struct wpa_ssid *ssid,
595 int start)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700596{
597 struct wpa_driver_auth_params params;
598 struct wpa_ssid *old_ssid;
599#ifdef CONFIG_IEEE80211R
600 const u8 *ie;
601#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700602#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700603 const u8 *md = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700604#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Hai Shalomfdcde762020-04-02 11:19:20 -0700605 int bssid_changed;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800606 struct wpabuf *resp = NULL;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700607 u8 ext_capab[18];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800608 int ext_capab_len;
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800609 int skip_auth;
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800610 u8 *wpa_ie;
611 size_t wpa_ie_len;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700612#ifdef CONFIG_MBO
613 const u8 *mbo_ie;
614#endif /* CONFIG_MBO */
Hai Shalomfdcde762020-04-02 11:19:20 -0700615 int omit_rsnxe = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700616
617 if (bss == NULL) {
618 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
619 "the network");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800620 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700621 return;
622 }
623
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800624 skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
625 wpa_s->reassoc_same_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700626 wpa_s->current_bss = bss;
627
628 os_memset(&params, 0, sizeof(params));
629 wpa_s->reassociate = 0;
630
631 params.freq = bss->freq;
632 params.bssid = bss->bssid;
633 params.ssid = bss->ssid;
634 params.ssid_len = bss->ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800635 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700636
Sunil Ravi640215c2023-06-28 23:08:09 +0000637 if (wpas_ml_element(wpa_s, bss, ssid)) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000638 wpa_printf(MSG_DEBUG, "MLD: In authentication");
639 params.mld = true;
640 params.mld_link_id = wpa_s->mlo_assoc_link_id;
641 params.ap_mld_addr = wpa_s->ap_mld_addr;
642 }
643
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700644 if (wpa_s->sme.ssid_len != params.ssid_len ||
645 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
646 wpa_s->sme.prev_bssid_set = 0;
647
648 wpa_s->sme.freq = params.freq;
649 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
650 wpa_s->sme.ssid_len = params.ssid_len;
651
652 params.auth_alg = WPA_AUTH_ALG_OPEN;
653#ifdef IEEE8021X_EAPOL
654 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
655 if (ssid->leap) {
656 if (ssid->non_leap == 0)
657 params.auth_alg = WPA_AUTH_ALG_LEAP;
658 else
659 params.auth_alg |= WPA_AUTH_ALG_LEAP;
660 }
661 }
662#endif /* IEEE8021X_EAPOL */
663 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
664 params.auth_alg);
665 if (ssid->auth_alg) {
666 params.auth_alg = ssid->auth_alg;
667 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
668 "0x%x", params.auth_alg);
669 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800670#ifdef CONFIG_SAE
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800671 wpa_s->sme.sae_pmksa_caching = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800672 if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
673 const u8 *rsn;
674 struct wpa_ie_data ied;
675
676 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800677 if (!rsn) {
678 wpa_dbg(wpa_s, MSG_DEBUG,
679 "SAE enabled, but target BSS does not advertise RSN");
Hai Shalom021b0b52019-04-10 11:17:58 -0700680#ifdef CONFIG_DPP
681 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
682 (ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
683 (ied.key_mgmt & WPA_KEY_MGMT_DPP)) {
684 wpa_dbg(wpa_s, MSG_DEBUG, "Prefer DPP over SAE when both are enabled");
685#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800686 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
687 wpa_key_mgmt_sae(ied.key_mgmt)) {
Sunil Ravi77d572f2023-01-17 23:58:31 +0000688 if (wpas_is_sae_avoided(wpa_s, ssid, &ied)) {
689 wpa_dbg(wpa_s, MSG_DEBUG,
690 "SAE enabled, but disallowing SAE auth_alg without PMF");
691 } else {
692 wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
693 params.auth_alg = WPA_AUTH_ALG_SAE;
694 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800695 } else {
696 wpa_dbg(wpa_s, MSG_DEBUG,
697 "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800698 }
699 }
700#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700701
Hai Shalomfdcde762020-04-02 11:19:20 -0700702#ifdef CONFIG_WEP
703 {
704 int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705
Hai Shalomfdcde762020-04-02 11:19:20 -0700706 for (i = 0; i < NUM_WEP_KEYS; i++) {
707 if (ssid->wep_key_len[i])
708 params.wep_key[i] = ssid->wep_key[i];
709 params.wep_key_len[i] = ssid->wep_key_len[i];
710 }
711 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
712 }
713#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700714
715 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
716 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800717 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700718 int try_opportunistic;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700719 const u8 *cache_id = NULL;
720
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800721 try_opportunistic = (ssid->proactive_key_caching < 0 ?
722 wpa_s->conf->okc :
723 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700724 (ssid->proto & WPA_PROTO_RSN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700725#ifdef CONFIG_FILS
726 if (wpa_key_mgmt_fils(ssid->key_mgmt))
727 cache_id = wpa_bss_get_fils_cache_id(bss);
728#endif /* CONFIG_FILS */
Sunil Ravi77d572f2023-01-17 23:58:31 +0000729 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
730 params.mld ? params.ap_mld_addr :
731 bss->bssid,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700732 wpa_s->current_ssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700733 try_opportunistic, cache_id,
734 0) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800735 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700736 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
737 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
738 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000739 &wpa_s->sme.assoc_req_ie_len,
740 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
742 "key management and encryption suites");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800743 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744 return;
745 }
Hai Shalom74f70d42019-02-11 14:42:39 -0800746#ifdef CONFIG_HS20
747 } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
748 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
749 /* No PMKSA caching, but otherwise similar to RSN/WPA */
750 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
751 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
752 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000753 &wpa_s->sme.assoc_req_ie_len,
754 false)) {
Hai Shalom74f70d42019-02-11 14:42:39 -0800755 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
756 "key management and encryption suites");
757 wpas_connect_work_done(wpa_s);
758 return;
759 }
760#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700761 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
762 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
763 /*
764 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
765 * use non-WPA since the scan results did not indicate that the
766 * AP is using WPA or WPA2.
767 */
768 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
769 wpa_s->sme.assoc_req_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800770 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700771 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
772 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
773 wpa_s->sme.assoc_req_ie,
Sunil Ravi77d572f2023-01-17 23:58:31 +0000774 &wpa_s->sme.assoc_req_ie_len,
775 false)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700776 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
777 "key management and encryption suites (no "
778 "scan results)");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800779 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700780 return;
781 }
782#ifdef CONFIG_WPS
783 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
784 struct wpabuf *wps_ie;
785 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
786 if (wps_ie && wpabuf_len(wps_ie) <=
787 sizeof(wpa_s->sme.assoc_req_ie)) {
788 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
789 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
790 wpa_s->sme.assoc_req_ie_len);
791 } else
792 wpa_s->sme.assoc_req_ie_len = 0;
793 wpabuf_free(wps_ie);
794 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
795#endif /* CONFIG_WPS */
796 } else {
797 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
798 wpa_s->sme.assoc_req_ie_len = 0;
799 }
800
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800801 /* In case the WPA vendor IE is used, it should be placed after all the
802 * non-vendor IEs, as the lower layer expects the IEs to be ordered as
803 * defined in the standard. Store the WPA IE so it can later be
804 * inserted at the correct location.
805 */
806 wpa_ie = NULL;
807 wpa_ie_len = 0;
808 if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
809 wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
810 wpa_s->sme.assoc_req_ie_len);
811 if (wpa_ie) {
812 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
813
814 wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
815 wpa_s->sme.assoc_req_ie_len = 0;
816 } else {
817 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
818 wpas_connect_work_done(wpa_s);
819 return;
820 }
821 }
822
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700823#ifdef CONFIG_IEEE80211R
824 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
825 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
826 md = ie + 2;
827 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
Hai Shalom021b0b52019-04-10 11:17:58 -0700828 if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
829 !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
830 md = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700831 if (md) {
832 /* Prepare for the next transition */
833 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
834 }
835
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700836 if (md) {
837 wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
838 md[0], md[1]);
839
Hai Shalomfdcde762020-04-02 11:19:20 -0700840 omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700841 if (wpa_s->sme.assoc_req_ie_len + 5 <
842 sizeof(wpa_s->sme.assoc_req_ie)) {
843 struct rsn_mdie *mdie;
844 u8 *pos = wpa_s->sme.assoc_req_ie +
845 wpa_s->sme.assoc_req_ie_len;
846 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
847 *pos++ = sizeof(*mdie);
848 mdie = (struct rsn_mdie *) pos;
849 os_memcpy(mdie->mobility_domain, md,
850 MOBILITY_DOMAIN_ID_LEN);
851 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
852 wpa_s->sme.assoc_req_ie_len += 5;
853 }
854
Hai Shalom74f70d42019-02-11 14:42:39 -0800855 if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700856 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
Sunil Ravi77d572f2023-01-17 23:58:31 +0000857 wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700858 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
859 "over-the-air");
860 params.auth_alg = WPA_AUTH_ALG_FT;
861 params.ie = wpa_s->sme.ft_ies;
862 params.ie_len = wpa_s->sme.ft_ies_len;
863 }
864 }
865#endif /* CONFIG_IEEE80211R */
866
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800867 wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800868 if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700869 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
870 struct wpa_ie_data _ie;
871 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
872 _ie.capabilities &
873 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
874 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
875 "MFP: require MFP");
876 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
877 }
878 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700879
880#ifdef CONFIG_P2P
881 if (wpa_s->global->p2p) {
882 u8 *pos;
883 size_t len;
884 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700885 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
886 len = sizeof(wpa_s->sme.assoc_req_ie) -
887 wpa_s->sme.assoc_req_ie_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800888 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
889 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700890 if (res >= 0)
891 wpa_s->sme.assoc_req_ie_len += res;
892 }
893#endif /* CONFIG_P2P */
894
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800895#ifdef CONFIG_FST
896 if (wpa_s->fst_ies) {
897 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
898
899 if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <=
900 sizeof(wpa_s->sme.assoc_req_ie)) {
901 os_memcpy(wpa_s->sme.assoc_req_ie +
902 wpa_s->sme.assoc_req_ie_len,
903 wpabuf_head(wpa_s->fst_ies),
904 fst_ies_len);
905 wpa_s->sme.assoc_req_ie_len += fst_ies_len;
906 }
907 }
908#endif /* CONFIG_FST */
909
910 sme_auth_handle_rrm(wpa_s, bss);
911
Dmitry Shmidt29333592017-01-09 12:27:11 -0800912 wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
Hai Shalomfdcde762020-04-02 11:19:20 -0700913 wpa_s, ssid, bss,
Dmitry Shmidt29333592017-01-09 12:27:11 -0800914 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
915 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800916
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700917 if (params.p2p)
918 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
919 else
920 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
921
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800922 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
923 sizeof(ext_capab));
924 if (ext_capab_len > 0) {
925 u8 *pos = wpa_s->sme.assoc_req_ie;
926 if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
927 pos += 2 + pos[1];
928 os_memmove(pos + ext_capab_len, pos,
929 wpa_s->sme.assoc_req_ie_len -
930 (pos - wpa_s->sme.assoc_req_ie));
931 wpa_s->sme.assoc_req_ie_len += ext_capab_len;
932 os_memcpy(pos, ext_capab, ext_capab_len);
933 }
934
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800935#ifdef CONFIG_TESTING_OPTIONS
936 if (wpa_s->rsnxe_override_assoc &&
937 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
938 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
939 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
940 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
941 wpabuf_head(wpa_s->rsnxe_override_assoc),
942 wpabuf_len(wpa_s->rsnxe_override_assoc));
943 wpa_s->sme.assoc_req_ie_len +=
944 wpabuf_len(wpa_s->rsnxe_override_assoc);
945 } else
946#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -0700947 if (wpa_s->rsnxe_len > 0 &&
948 wpa_s->rsnxe_len <=
Hai Shalomfdcde762020-04-02 11:19:20 -0700949 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len &&
950 !omit_rsnxe) {
Hai Shalomc3565922019-10-28 11:58:20 -0700951 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
952 wpa_s->rsnxe, wpa_s->rsnxe_len);
953 wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
954 }
955
Dmitry Shmidt04949592012-07-19 12:16:46 -0700956#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -0800957 if (is_hs20_network(wpa_s, ssid, bss)
958#ifndef ANDROID /* Android does not use the native HS 2.0 config */
959 && is_hs20_config(wpa_s)
960#endif /* ANDROID */
961 ) {
Dmitry Shmidt04949592012-07-19 12:16:46 -0700962 struct wpabuf *hs20;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800963
Roshan Pius3a1667e2018-07-03 15:17:14 -0700964 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700965 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800966 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700967 size_t len;
968
Hai Shalom74f70d42019-02-11 14:42:39 -0800969 wpas_hs20_add_indication(hs20, pps_mo_id,
970 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -0700971 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700972 len = sizeof(wpa_s->sme.assoc_req_ie) -
973 wpa_s->sme.assoc_req_ie_len;
974 if (wpabuf_len(hs20) <= len) {
975 os_memcpy(wpa_s->sme.assoc_req_ie +
976 wpa_s->sme.assoc_req_ie_len,
977 wpabuf_head(hs20), wpabuf_len(hs20));
978 wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
979 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700980 wpabuf_free(hs20);
981 }
982 }
983#endif /* CONFIG_HS20 */
984
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800985 if (wpa_ie) {
986 size_t len;
987
988 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
989
990 len = sizeof(wpa_s->sme.assoc_req_ie) -
991 wpa_s->sme.assoc_req_ie_len;
992
993 if (len > wpa_ie_len) {
994 os_memcpy(wpa_s->sme.assoc_req_ie +
995 wpa_s->sme.assoc_req_ie_len,
996 wpa_ie, wpa_ie_len);
997 wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
998 } else {
999 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
1000 }
1001
1002 os_free(wpa_ie);
1003 }
1004
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001005 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
1006 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
1007 size_t len;
1008
1009 len = sizeof(wpa_s->sme.assoc_req_ie) -
1010 wpa_s->sme.assoc_req_ie_len;
1011 if (wpabuf_len(buf) <= len) {
1012 os_memcpy(wpa_s->sme.assoc_req_ie +
1013 wpa_s->sme.assoc_req_ie_len,
1014 wpabuf_head(buf), wpabuf_len(buf));
1015 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
1016 }
1017 }
1018
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001019#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -07001020 mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -07001021 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001022 int len;
1023
1024 len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
1025 wpa_s->sme.assoc_req_ie_len,
1026 sizeof(wpa_s->sme.assoc_req_ie) -
Hai Shalomce48b4a2018-09-05 11:41:35 -07001027 wpa_s->sme.assoc_req_ie_len,
1028 !!mbo_attr_from_mbo_ie(mbo_ie,
1029 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001030 if (len >= 0)
1031 wpa_s->sme.assoc_req_ie_len += len;
1032 }
1033#endif /* CONFIG_MBO */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001034
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001035#ifdef CONFIG_SAE
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001036 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
Sunil Ravi77d572f2023-01-17 23:58:31 +00001037 pmksa_cache_set_current(wpa_s->wpa, NULL,
1038 params.mld ? params.ap_mld_addr :
1039 bss->bssid,
1040 ssid, 0,
Hai Shalom021b0b52019-04-10 11:17:58 -07001041 NULL,
Sunil Ravi89eba102022-09-13 21:04:37 -07001042 wpa_key_mgmt_sae(wpa_s->key_mgmt) ?
1043 wpa_s->key_mgmt :
1044 (int) WPA_KEY_MGMT_SAE) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001045 wpa_dbg(wpa_s, MSG_DEBUG,
1046 "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001047 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001048 params.auth_alg = WPA_AUTH_ALG_OPEN;
1049 wpa_s->sme.sae_pmksa_caching = 1;
1050 }
1051
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001052 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001053 if (start)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001054 resp = sme_auth_build_sae_commit(wpa_s, ssid,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001055 bss->bssid,
1056 params.mld ?
1057 params.ap_mld_addr :
1058 NULL, 0,
Hai Shalom899fcc72020-10-19 14:38:18 -07001059 start == 2, NULL,
1060 NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001061 else
Roshan Pius3a1667e2018-07-03 15:17:14 -07001062 resp = sme_auth_build_sae_confirm(wpa_s, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001063 if (resp == NULL) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001064 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001065 return;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001066 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001067 params.auth_data = wpabuf_head(resp);
1068 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001069 wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001070 }
1071#endif /* CONFIG_SAE */
1072
Hai Shalomfdcde762020-04-02 11:19:20 -07001073 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1074 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1075 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1076 if (bssid_changed)
1077 wpas_notify_bssid_changed(wpa_s);
1078
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001079 old_ssid = wpa_s->current_ssid;
1080 wpa_s->current_ssid = ssid;
1081 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1082 wpa_supplicant_initiate_eapol(wpa_s);
1083
1084#ifdef CONFIG_FILS
1085 /* TODO: FILS operations can in some cases be done between different
1086 * network_ctx (i.e., same credentials can be used with multiple
1087 * networks). */
1088 if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
1089 wpa_key_mgmt_fils(ssid->key_mgmt)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001090 const u8 *indic;
1091 u16 fils_info;
Hai Shalomce48b4a2018-09-05 11:41:35 -07001092 const u8 *realm, *username, *rrk;
1093 size_t realm_len, username_len, rrk_len;
1094 u16 next_seq_num;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001095
1096 /*
1097 * Check FILS Indication element (FILS Information field) bits
1098 * indicating supported authentication algorithms against local
1099 * configuration (ssid->fils_dh_group). Try to use FILS
1100 * authentication only if the AP supports the combination in the
1101 * network profile. */
1102 indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
1103 if (!indic || indic[1] < 2) {
1104 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1105 " does not include FILS Indication element - cannot use FILS authentication with it",
1106 MAC2STR(bss->bssid));
1107 goto no_fils;
1108 }
1109
1110 fils_info = WPA_GET_LE16(indic + 2);
1111 if (ssid->fils_dh_group == 0 && !(fils_info & BIT(9))) {
1112 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1113 " does not support FILS SK without PFS - cannot use FILS authentication with it",
1114 MAC2STR(bss->bssid));
1115 goto no_fils;
1116 }
1117 if (ssid->fils_dh_group != 0 && !(fils_info & BIT(10))) {
1118 wpa_printf(MSG_DEBUG, "SME: " MACSTR
1119 " does not support FILS SK with PFS - cannot use FILS authentication with it",
1120 MAC2STR(bss->bssid));
1121 goto no_fils;
1122 }
1123
Hai Shalomce48b4a2018-09-05 11:41:35 -07001124 if (wpa_s->last_con_fail_realm &&
1125 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
1126 &username, &username_len,
1127 &realm, &realm_len, &next_seq_num,
1128 &rrk, &rrk_len) == 0 &&
1129 realm && realm_len == wpa_s->last_con_fail_realm_len &&
1130 os_memcmp(realm, wpa_s->last_con_fail_realm,
1131 realm_len) == 0) {
1132 wpa_printf(MSG_DEBUG,
1133 "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
1134 goto no_fils;
1135 }
1136
Sunil Ravi77d572f2023-01-17 23:58:31 +00001137 if (pmksa_cache_set_current(wpa_s->wpa, NULL,
1138 params.mld ? params.ap_mld_addr :
1139 bss->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001140 ssid, 0,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001141 wpa_bss_get_fils_cache_id(bss),
1142 0) == 0)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001143 wpa_printf(MSG_DEBUG,
1144 "SME: Try to use FILS with PMKSA caching");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001145 resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001146 if (resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001147 int auth_alg;
1148
1149 if (ssid->fils_dh_group)
1150 wpa_printf(MSG_DEBUG,
1151 "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
1152 ssid->fils_dh_group);
1153 else
1154 wpa_printf(MSG_DEBUG,
1155 "SME: Try to use FILS SK authentication without PFS");
1156 auth_alg = ssid->fils_dh_group ?
1157 WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
1158 params.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001159 params.auth_data = wpabuf_head(resp);
1160 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001161 wpa_s->sme.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001162 }
1163 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001164no_fils:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001165#endif /* CONFIG_FILS */
1166
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001167 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001168 wpa_supplicant_cancel_scan(wpa_s);
1169
1170 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
1171 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
1172 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
1173
Hai Shalome21d4e82020-04-29 16:34:06 -07001174 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001175 wpa_clear_keys(wpa_s, bss->bssid);
1176 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001177 if (old_ssid != wpa_s->current_ssid)
1178 wpas_notify_network_changed(wpa_s);
1179
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001180#ifdef CONFIG_HS20
1181 hs20_configure_frame_filters(wpa_s);
1182#endif /* CONFIG_HS20 */
1183
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001184#ifdef CONFIG_P2P
1185 /*
1186 * If multi-channel concurrency is not supported, check for any
1187 * frequency conflict. In case of any frequency conflict, remove the
1188 * least prioritized connection.
1189 */
1190 if (wpa_s->num_multichan_concurrent < 2) {
1191 int freq, num;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001192 num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -07001193 if (num > 0 && freq > 0 && freq != params.freq) {
1194 wpa_printf(MSG_DEBUG,
1195 "Conflicting frequency found (%d != %d)",
1196 freq, params.freq);
1197 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1198 params.freq,
1199 ssid) < 0) {
1200 wpas_connection_failed(wpa_s, bss->bssid);
1201 wpa_supplicant_mark_disassoc(wpa_s);
1202 wpabuf_free(resp);
1203 wpas_connect_work_done(wpa_s);
1204 return;
1205 }
1206 }
1207 }
1208#endif /* CONFIG_P2P */
1209
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001210 if (skip_auth) {
1211 wpa_msg(wpa_s, MSG_DEBUG,
1212 "SME: Skip authentication step on reassoc-to-same-BSS");
1213 wpabuf_free(resp);
1214 sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN);
1215 return;
1216 }
1217
1218
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001219 wpa_s->sme.auth_alg = params.auth_alg;
1220 if (wpa_drv_authenticate(wpa_s, &params) < 0) {
1221 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
1222 "driver failed");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001223 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001224 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001225 wpabuf_free(resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001226 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001227 return;
1228 }
1229
1230 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
1231 NULL);
1232
1233 /*
1234 * Association will be started based on the authentication event from
1235 * the driver.
1236 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001237
1238 wpabuf_free(resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001239}
1240
1241
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001242static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
1243{
1244 struct wpa_connect_work *cwork = work->ctx;
1245 struct wpa_supplicant *wpa_s = work->wpa_s;
1246
Hai Shaloma20dcd72022-02-04 13:43:00 -08001247 wpa_s->roam_in_progress = false;
1248#ifdef CONFIG_WNM
1249 wpa_s->bss_trans_mgmt_in_progress = false;
1250#endif /* CONFIG_WNM */
1251
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001252 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001253 if (work->started)
1254 wpa_s->connect_work = NULL;
1255
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001256 wpas_connect_work_free(cwork);
1257 return;
1258 }
1259
1260 wpa_s->connect_work = work;
1261
Dmitry Shmidt2e425d62014-11-10 11:18:27 -08001262 if (cwork->bss_removed ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001263 !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
1264 wpas_network_disabled(wpa_s, cwork->ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001265 wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
1266 wpas_connect_work_done(wpa_s);
1267 return;
1268 }
1269
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001270 /* Starting new connection, so clear the possibly used WPA IE from the
1271 * previous association. */
1272 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07001273 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
1274 wpa_s->rsnxe_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001275
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001276 sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001277 wpas_notify_auth_changed(wpa_s);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001278}
1279
1280
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001281void sme_authenticate(struct wpa_supplicant *wpa_s,
1282 struct wpa_bss *bss, struct wpa_ssid *ssid)
1283{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001284 struct wpa_connect_work *cwork;
1285
1286 if (bss == NULL || ssid == NULL)
1287 return;
1288 if (wpa_s->connect_work) {
1289 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
1290 return;
1291 }
1292
Hai Shaloma20dcd72022-02-04 13:43:00 -08001293 if (wpa_s->roam_in_progress) {
1294 wpa_dbg(wpa_s, MSG_DEBUG,
1295 "SME: Reject sme_authenticate() in favor of explicit roam request");
1296 return;
1297 }
1298#ifdef CONFIG_WNM
1299 if (wpa_s->bss_trans_mgmt_in_progress) {
1300 wpa_dbg(wpa_s, MSG_DEBUG,
1301 "SME: Reject sme_authenticate() in favor of BSS transition management request");
1302 return;
1303 }
1304#endif /* CONFIG_WNM */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001305 if (radio_work_pending(wpa_s, "sme-connect")) {
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001306 /*
1307 * The previous sme-connect work might no longer be valid due to
1308 * the fact that the BSS list was updated. In addition, it makes
1309 * sense to adhere to the 'newer' decision.
1310 */
1311 wpa_dbg(wpa_s, MSG_DEBUG,
1312 "SME: Remove previous pending sme-connect");
1313 radio_remove_works(wpa_s, "sme-connect", 0);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001314 }
1315
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -08001316 wpas_abort_ongoing_scan(wpa_s);
1317
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001318 cwork = os_zalloc(sizeof(*cwork));
1319 if (cwork == NULL)
1320 return;
1321 cwork->bss = bss;
1322 cwork->ssid = ssid;
1323 cwork->sme = 1;
1324
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001325#ifdef CONFIG_SAE
1326 wpa_s->sme.sae.state = SAE_NOTHING;
1327 wpa_s->sme.sae.send_confirm = 0;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001328 wpa_s->sme.sae_group_index = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001329#endif /* CONFIG_SAE */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001330
1331 if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
1332 sme_auth_start_cb, cwork) < 0)
1333 wpas_connect_work_free(cwork);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001334}
1335
1336
1337#ifdef CONFIG_SAE
1338
Sunil Ravi036cec52023-03-29 11:35:17 -07001339#define WPA_AUTH_FRAME_ML_IE_LEN (6 + ETH_ALEN)
1340
1341static void wpa_auth_ml_ie(struct wpabuf *buf, const u8 *mld_addr)
1342{
1343
1344 wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1345 wpabuf_put_u8(buf, 4 + ETH_ALEN);
1346 wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK);
1347
1348 /* Basic Multi-Link element Control field */
1349 wpabuf_put_u8(buf, 0x0);
1350 wpabuf_put_u8(buf, 0x0);
1351
1352 /* Common Info */
1353 wpabuf_put_u8(buf, 0x7); /* length = Length field + MLD MAC address */
1354 wpabuf_put_data(buf, mld_addr, ETH_ALEN);
1355}
1356
1357
Roshan Pius3a1667e2018-07-03 15:17:14 -07001358static int sme_external_auth_build_buf(struct wpabuf *buf,
1359 struct wpabuf *params,
1360 const u8 *sa, const u8 *da,
Hai Shalomc3565922019-10-28 11:58:20 -07001361 u16 auth_transaction, u16 seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001362 u16 status_code, const u8 *mld_addr)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001363{
1364 struct ieee80211_mgmt *resp;
1365
1366 resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
1367 u.auth.variable));
1368
1369 resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
1370 (WLAN_FC_STYPE_AUTH << 4));
1371 os_memcpy(resp->da, da, ETH_ALEN);
1372 os_memcpy(resp->sa, sa, ETH_ALEN);
1373 os_memcpy(resp->bssid, da, ETH_ALEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08001374 resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
1375 resp->seq_ctrl = host_to_le16(seq_num << 4);
1376 resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
Hai Shalomc3565922019-10-28 11:58:20 -07001377 resp->u.auth.status_code = host_to_le16(status_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001378 if (params)
1379 wpabuf_put_buf(buf, params);
1380
Sunil Ravi036cec52023-03-29 11:35:17 -07001381 if (mld_addr)
1382 wpa_auth_ml_ie(buf, mld_addr);
1383
Roshan Pius3a1667e2018-07-03 15:17:14 -07001384 return 0;
1385}
1386
1387
Hai Shalom81f62d82019-07-22 12:10:00 -07001388static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
1389 const u8 *bssid,
1390 struct wpa_ssid *ssid)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001391{
1392 struct wpabuf *resp, *buf;
Hai Shalomc3565922019-10-28 11:58:20 -07001393 int use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -07001394 bool use_pk;
1395 u16 status;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001396
Sunil Ravi036cec52023-03-29 11:35:17 -07001397 resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid,
1398 wpa_s->sme.ext_ml_auth ?
1399 wpa_s->sme.ext_auth_ap_mld_addr : NULL,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001400 1, 0, &use_pt, &use_pk);
Hai Shalom81f62d82019-07-22 12:10:00 -07001401 if (!resp) {
1402 wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
1403 return -1;
1404 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001405
1406 wpa_s->sme.sae.state = SAE_COMMITTED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001407 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp) +
1408 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1409 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001410 if (!buf) {
1411 wpabuf_free(resp);
Hai Shalom81f62d82019-07-22 12:10:00 -07001412 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001413 }
1414
1415 wpa_s->sme.seq_num++;
Hai Shalom899fcc72020-10-19 14:38:18 -07001416 if (use_pk)
1417 status = WLAN_STATUS_SAE_PK;
1418 else if (use_pt)
1419 status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
1420 else
1421 status = WLAN_STATUS_SUCCESS;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001422 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Sunil Ravi036cec52023-03-29 11:35:17 -07001423 wpa_s->sme.ext_ml_auth ?
1424 wpa_s->sme.ext_auth_ap_mld_addr : bssid, 1,
1425 wpa_s->sme.seq_num, status,
1426 wpa_s->sme.ext_ml_auth ?
1427 wpa_s->own_addr : NULL);
Hai Shalomfdcde762020-04-02 11:19:20 -07001428 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001429 wpabuf_free(resp);
1430 wpabuf_free(buf);
Hai Shalom81f62d82019-07-22 12:10:00 -07001431
1432 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001433}
1434
1435
1436static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
1437 u16 status)
1438{
1439 struct external_auth params;
1440
Sunil Ravi89eba102022-09-13 21:04:37 -07001441 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001442 os_memset(&params, 0, sizeof(params));
1443 params.status = status;
Hai Shalom66904732019-05-29 11:54:04 -07001444 params.ssid = wpa_s->sme.ext_auth_ssid;
1445 params.ssid_len = wpa_s->sme.ext_auth_ssid_len;
1446 params.bssid = wpa_s->sme.ext_auth_bssid;
Hai Shalomc3565922019-10-28 11:58:20 -07001447 if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
1448 params.pmkid = wpa_s->sme.sae.pmkid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001449 wpa_drv_send_external_auth_status(wpa_s, &params);
1450}
1451
1452
Hai Shalom81f62d82019-07-22 12:10:00 -07001453static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
1454 union wpa_event_data *data)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001455{
1456 struct wpa_ssid *ssid;
1457 size_t ssid_str_len = data->external_auth.ssid_len;
Hai Shalom5f92bc92019-04-18 11:54:11 -07001458 const u8 *ssid_str = data->external_auth.ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001459
Sunil Ravi89eba102022-09-13 21:04:37 -07001460 wpa_s->sme.ext_auth_wpa_ssid = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001461 /* Get the SSID conf from the ssid string obtained */
1462 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1463 if (!wpas_network_disabled(wpa_s, ssid) &&
1464 ssid_str_len == ssid->ssid_len &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001465 os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001466 wpa_key_mgmt_sae(ssid->key_mgmt)) {
1467 /* Make sure PT is derived */
Sunil Ravi036cec52023-03-29 11:35:17 -07001468 wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
Sunil Ravi89eba102022-09-13 21:04:37 -07001469 wpa_s->sme.ext_auth_wpa_ssid = ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001470 break;
Sunil Ravi89eba102022-09-13 21:04:37 -07001471 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001472 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001473 if (!ssid ||
1474 sme_external_auth_send_sae_commit(wpa_s, data->external_auth.bssid,
1475 ssid) < 0)
1476 return -1;
1477
1478 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001479}
1480
1481
1482static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
1483 const u8 *da)
1484{
1485 struct wpabuf *resp, *buf;
1486
1487 resp = sme_auth_build_sae_confirm(wpa_s, 1);
1488 if (!resp) {
1489 wpa_printf(MSG_DEBUG, "SAE: Confirm message buf alloc failure");
1490 return;
1491 }
1492
1493 wpa_s->sme.sae.state = SAE_CONFIRMED;
Sunil Ravi036cec52023-03-29 11:35:17 -07001494 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp) +
1495 (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1496 0));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001497 if (!buf) {
1498 wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure");
1499 wpabuf_free(resp);
1500 return;
1501 }
1502 wpa_s->sme.seq_num++;
1503 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Hai Shalomc3565922019-10-28 11:58:20 -07001504 da, 2, wpa_s->sme.seq_num,
Sunil Ravi036cec52023-03-29 11:35:17 -07001505 WLAN_STATUS_SUCCESS,
1506 wpa_s->sme.ext_ml_auth ?
1507 wpa_s->own_addr : NULL);
1508
Hai Shalomfdcde762020-04-02 11:19:20 -07001509 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001510 wpabuf_free(resp);
1511 wpabuf_free(buf);
1512}
1513
1514
Sunil Ravi77d572f2023-01-17 23:58:31 +00001515static bool is_sae_key_mgmt_suite(struct wpa_supplicant *wpa_s, u32 suite)
1516{
1517 /* suite is supposed to be the selector value in host byte order with
1518 * the OUI in three most significant octets. However, the initial
1519 * implementation swapped that byte order and did not work with drivers
1520 * that followed the expected byte order. Keep a workaround here to
1521 * match that initial implementation so that already deployed use cases
1522 * remain functional. */
1523 if (RSN_SELECTOR_GET(&suite) == RSN_AUTH_KEY_MGMT_SAE) {
1524 /* Old drivers which follow initial implementation send SAE AKM
1525 * for both SAE and FT-SAE connections. In that case, determine
1526 * the actual AKM from wpa_s->key_mgmt. */
1527 wpa_s->sme.ext_auth_key_mgmt = wpa_s->key_mgmt;
1528 return true;
1529 }
1530
1531 if (suite == RSN_AUTH_KEY_MGMT_SAE)
1532 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE;
1533 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE)
1534 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE;
1535 else if (suite == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
1536 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1537 else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
1538 wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1539 else
1540 return false;
1541
1542 return true;
1543}
1544
1545
Roshan Pius3a1667e2018-07-03 15:17:14 -07001546void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
1547 union wpa_event_data *data)
1548{
Sunil Ravi77d572f2023-01-17 23:58:31 +00001549 if (!is_sae_key_mgmt_suite(wpa_s, data->external_auth.key_mgmt_suite))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001550 return;
1551
1552 if (data->external_auth.action == EXT_AUTH_START) {
Hai Shalom66904732019-05-29 11:54:04 -07001553 if (!data->external_auth.bssid || !data->external_auth.ssid)
1554 return;
1555 os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid,
1556 ETH_ALEN);
1557 os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid,
1558 data->external_auth.ssid_len);
1559 wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len;
Sunil Ravi036cec52023-03-29 11:35:17 -07001560 if (data->external_auth.mld_addr) {
1561 wpa_s->sme.ext_ml_auth = true;
1562 os_memcpy(wpa_s->sme.ext_auth_ap_mld_addr,
1563 data->external_auth.mld_addr, ETH_ALEN);
1564 } else {
1565 wpa_s->sme.ext_ml_auth = false;
1566 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001567 wpa_s->sme.seq_num = 0;
1568 wpa_s->sme.sae.state = SAE_NOTHING;
1569 wpa_s->sme.sae.send_confirm = 0;
1570 wpa_s->sme.sae_group_index = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001571 if (sme_handle_external_auth_start(wpa_s, data) < 0)
1572 sme_send_external_auth_status(wpa_s,
1573 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001574 } else if (data->external_auth.action == EXT_AUTH_ABORT) {
1575 /* Report failure to driver for the wrong trigger */
1576 sme_send_external_auth_status(wpa_s,
1577 WLAN_STATUS_UNSPECIFIED_FAILURE);
1578 }
1579}
1580
1581
Hai Shalomc3565922019-10-28 11:58:20 -07001582static int sme_sae_is_group_enabled(struct wpa_supplicant *wpa_s, int group)
1583{
1584 int *groups = wpa_s->conf->sae_groups;
1585 int default_groups[] = { 19, 20, 21, 0 };
1586 int i;
1587
1588 if (!groups)
1589 groups = default_groups;
1590
1591 for (i = 0; groups[i] > 0; i++) {
1592 if (groups[i] == group)
1593 return 1;
1594 }
1595
1596 return 0;
1597}
1598
1599
1600static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
1601 const struct wpabuf *groups)
1602{
1603 size_t i, count;
1604 const u8 *pos;
1605
1606 if (!groups)
1607 return 0;
1608
1609 pos = wpabuf_head(groups);
1610 count = wpabuf_len(groups) / 2;
1611 for (i = 0; i < count; i++) {
1612 int enabled;
1613 u16 group;
1614
1615 group = WPA_GET_LE16(pos);
1616 pos += 2;
1617 enabled = sme_sae_is_group_enabled(wpa_s, group);
1618 wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
1619 group, enabled ? "enabled" : "disabled");
1620 if (enabled)
1621 return 1;
1622 }
1623
1624 return 0;
1625}
1626
1627
Sunil Ravi036cec52023-03-29 11:35:17 -07001628static int sme_external_ml_auth(struct wpa_supplicant *wpa_s,
Sunil Ravi640215c2023-06-28 23:08:09 +00001629 const u8 *data, size_t len, int ie_offset,
1630 u16 status_code)
Sunil Ravi036cec52023-03-29 11:35:17 -07001631{
1632 struct ieee802_11_elems elems;
1633 const u8 *mld_addr;
1634
1635 if (ieee802_11_parse_elems(data + ie_offset, len - ie_offset,
Sunil Ravi640215c2023-06-28 23:08:09 +00001636 &elems, 0) == ParseFailed) {
Sunil Ravi036cec52023-03-29 11:35:17 -07001637 wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
1638 return -1;
1639 }
1640
1641 if (!elems.basic_mle || !elems.basic_mle_len) {
1642 wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
Sunil Ravi640215c2023-06-28 23:08:09 +00001643 if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
1644 status_code == WLAN_STATUS_SUCCESS ||
1645 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
1646 status_code == WLAN_STATUS_SAE_PK)
1647 return -1;
1648 /* Accept missing Multi-Link element in failed authentication
1649 * cases. */
1650 return 0;
Sunil Ravi036cec52023-03-29 11:35:17 -07001651 }
1652
1653 mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
1654 if (!mld_addr) {
1655 wpa_printf(MSG_DEBUG, "MLD: No MLD address in ML element");
1656 return -1;
1657 }
1658
1659 wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
1660
1661 if (os_memcmp(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr, ETH_ALEN) !=
1662 0) {
1663 wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
Sunil Ravi640215c2023-06-28 23:08:09 +00001664 MACSTR ")",
1665 MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr));
Sunil Ravi036cec52023-03-29 11:35:17 -07001666 return -1;
1667 }
1668
1669 return 0;
1670}
1671
1672
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001673static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001674 u16 status_code, const u8 *data, size_t len,
Sunil Ravi77d572f2023-01-17 23:58:31 +00001675 int external, const u8 *sa, int *ie_offset)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001676{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001677 int *groups;
1678
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001679 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
1680 "status code %u", auth_transaction, status_code);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001681
1682 if (auth_transaction == 1 &&
1683 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1684 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001685 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1686 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001687 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001688 u16 group;
Hai Shalomfdcde762020-04-02 11:19:20 -07001689 const u8 *token_pos;
1690 size_t token_len;
1691 int h2e = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001692
1693 groups = wpa_s->conf->sae_groups;
1694 if (!groups || groups[0] <= 0)
1695 groups = default_groups;
1696
Hai Shalomfdcde762020-04-02 11:19:20 -07001697 wpa_hexdump(MSG_DEBUG, "SME: SAE anti-clogging token request",
1698 data, len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001699 if (len < sizeof(le16)) {
1700 wpa_dbg(wpa_s, MSG_DEBUG,
1701 "SME: Too short SAE anti-clogging token request");
1702 return -1;
1703 }
1704 group = WPA_GET_LE16(data);
1705 wpa_dbg(wpa_s, MSG_DEBUG,
1706 "SME: SAE anti-clogging token requested (group %u)",
1707 group);
1708 if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
1709 WLAN_STATUS_SUCCESS) {
1710 wpa_dbg(wpa_s, MSG_ERROR,
1711 "SME: SAE group %u of anti-clogging request is invalid",
1712 group);
1713 return -1;
1714 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001715 wpabuf_free(wpa_s->sme.sae_token);
Hai Shalomfdcde762020-04-02 11:19:20 -07001716 token_pos = data + sizeof(le16);
1717 token_len = len - sizeof(le16);
Hai Shalom899fcc72020-10-19 14:38:18 -07001718 h2e = wpa_s->sme.sae.h2e;
Hai Shalomfdcde762020-04-02 11:19:20 -07001719 if (h2e) {
Sunil8cd6f4d2022-06-28 18:40:46 +00001720 u8 id, elen, extid;
1721
Hai Shalomfdcde762020-04-02 11:19:20 -07001722 if (token_len < 3) {
1723 wpa_dbg(wpa_s, MSG_DEBUG,
1724 "SME: Too short SAE anti-clogging token container");
1725 return -1;
1726 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001727 id = *token_pos++;
1728 elen = *token_pos++;
1729 extid = *token_pos++;
1730 if (id != WLAN_EID_EXTENSION ||
1731 elen == 0 || elen > token_len - 2 ||
1732 extid != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001733 wpa_dbg(wpa_s, MSG_DEBUG,
1734 "SME: Invalid SAE anti-clogging token container header");
1735 return -1;
1736 }
Sunil8cd6f4d2022-06-28 18:40:46 +00001737 token_len = elen - 1;
Hai Shalomfdcde762020-04-02 11:19:20 -07001738 }
Sunil Ravi77d572f2023-01-17 23:58:31 +00001739
Sunil Ravi036cec52023-03-29 11:35:17 -07001740 *ie_offset = token_pos + token_len - data;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001741
Hai Shalomfdcde762020-04-02 11:19:20 -07001742 wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
Sunil Ravi77d572f2023-01-17 23:58:31 +00001743 if (!wpa_s->sme.sae_token) {
1744 wpa_dbg(wpa_s, MSG_ERROR,
1745 "SME: Failed to allocate SAE token");
1746 return -1;
1747 }
1748
Hai Shalomfdcde762020-04-02 11:19:20 -07001749 wpa_hexdump_buf(MSG_DEBUG, "SME: Requested anti-clogging token",
1750 wpa_s->sme.sae_token);
Sunil Ravi036cec52023-03-29 11:35:17 -07001751 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001752 sme_send_authentication(wpa_s, wpa_s->current_bss,
Hai Shalom021b0b52019-04-10 11:17:58 -07001753 wpa_s->current_ssid, 2);
Sunil Ravi036cec52023-03-29 11:35:17 -07001754 } else {
1755 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001756 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1757 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001758 return -1;
1759
Roshan Pius3a1667e2018-07-03 15:17:14 -07001760 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001761 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001762 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001763 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001764 return 0;
1765 }
1766
1767 if (auth_transaction == 1 &&
1768 status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1769 wpa_s->sme.sae.state == SAE_COMMITTED &&
Sunil Ravi89eba102022-09-13 21:04:37 -07001770 ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1771 (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001772 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
Hai Shalomc3565922019-10-28 11:58:20 -07001773 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1774 wpa_s->sme.sae.group);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001775 wpa_s->sme.sae_group_index++;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001776 if (sme_set_sae_group(wpa_s, external) < 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001777 return -1; /* no other groups enabled */
1778 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
Sunil Ravi036cec52023-03-29 11:35:17 -07001779 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001780 sme_send_authentication(wpa_s, wpa_s->current_bss,
1781 wpa_s->current_ssid, 1);
Sunil Ravi036cec52023-03-29 11:35:17 -07001782 } else {
1783 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001784 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1785 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001786 return -1;
1787
Roshan Pius3a1667e2018-07-03 15:17:14 -07001788 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001789 wpa_s, wpa_s->sme.ext_auth_bssid,
Sunil Ravi89eba102022-09-13 21:04:37 -07001790 wpa_s->sme.ext_auth_wpa_ssid);
Sunil Ravi036cec52023-03-29 11:35:17 -07001791 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001792 return 0;
1793 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001794
Roshan Pius3a1667e2018-07-03 15:17:14 -07001795 if (auth_transaction == 1 &&
1796 status_code == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1797 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1798
1799 wpa_msg(wpa_s, MSG_INFO,
1800 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR,
1801 MAC2STR(bssid));
1802 return -1;
1803 }
1804
Hai Shalomc3565922019-10-28 11:58:20 -07001805 if (status_code != WLAN_STATUS_SUCCESS &&
Hai Shalom899fcc72020-10-19 14:38:18 -07001806 status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
Hai Shaloma20dcd72022-02-04 13:43:00 -08001807 status_code != WLAN_STATUS_SAE_PK) {
1808 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1809
1810 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
1811 " auth_type=%u auth_transaction=%u status_code=%u",
1812 MAC2STR(bssid), WLAN_AUTH_SAE,
1813 auth_transaction, status_code);
Sunil Ravia04bd252022-05-02 22:54:18 -07001814 return -2;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001815 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001816
1817 if (auth_transaction == 1) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07001818 u16 res;
1819
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001820 groups = wpa_s->conf->sae_groups;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001821
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001822 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
Sunil Ravi89eba102022-09-13 21:04:37 -07001823 if ((external && !wpa_s->sme.ext_auth_wpa_ssid) ||
1824 (!external &&
1825 (!wpa_s->current_bss || !wpa_s->current_ssid)))
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001826 return -1;
Hai Shalomc3565922019-10-28 11:58:20 -07001827 if (wpa_s->sme.sae.state != SAE_COMMITTED) {
1828 wpa_printf(MSG_DEBUG,
1829 "SAE: Ignore commit message while waiting for confirm");
1830 return 0;
1831 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001832 if (wpa_s->sme.sae.h2e && status_code == WLAN_STATUS_SUCCESS) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001833 wpa_printf(MSG_DEBUG,
1834 "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
1835 return -1;
1836 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001837 if ((!wpa_s->sme.sae.h2e || wpa_s->sme.sae.pk) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001838 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
1839 wpa_printf(MSG_DEBUG,
1840 "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
1841 return -1;
1842 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001843 if (!wpa_s->sme.sae.pk &&
1844 status_code == WLAN_STATUS_SAE_PK) {
1845 wpa_printf(MSG_DEBUG,
1846 "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected");
1847 return -1;
1848 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001849
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001850 if (groups && groups[0] <= 0)
1851 groups = NULL;
Dmitry Shmidt41712582015-06-29 11:02:15 -07001852 res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
Hai Shalomc3565922019-10-28 11:58:20 -07001853 groups, status_code ==
Hai Shalom899fcc72020-10-19 14:38:18 -07001854 WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
Sunil Ravi77d572f2023-01-17 23:58:31 +00001855 status_code == WLAN_STATUS_SAE_PK,
1856 ie_offset);
Dmitry Shmidt41712582015-06-29 11:02:15 -07001857 if (res == SAE_SILENTLY_DISCARD) {
1858 wpa_printf(MSG_DEBUG,
1859 "SAE: Drop commit message due to reflection attack");
1860 return 0;
1861 }
1862 if (res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001863 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001864
Hai Shalomc3565922019-10-28 11:58:20 -07001865 if (wpa_s->sme.sae.tmp &&
1866 sme_check_sae_rejected_groups(
1867 wpa_s,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001868 wpa_s->sme.sae.tmp->peer_rejected_groups))
Hai Shalomc3565922019-10-28 11:58:20 -07001869 return -1;
1870
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001871 if (sae_process_commit(&wpa_s->sme.sae) < 0) {
1872 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
1873 "commit");
1874 return -1;
1875 }
1876
1877 wpabuf_free(wpa_s->sme.sae_token);
1878 wpa_s->sme.sae_token = NULL;
Sunil Ravi036cec52023-03-29 11:35:17 -07001879 if (!external) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001880 sme_send_authentication(wpa_s, wpa_s->current_bss,
1881 wpa_s->current_ssid, 0);
Sunil Ravi036cec52023-03-29 11:35:17 -07001882 } else {
1883 if (wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001884 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1885 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001886 return -1;
1887
Roshan Pius3a1667e2018-07-03 15:17:14 -07001888 sme_external_auth_send_sae_confirm(wpa_s, sa);
Sunil Ravi036cec52023-03-29 11:35:17 -07001889 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001890 return 0;
1891 } else if (auth_transaction == 2) {
Hai Shalomc3565922019-10-28 11:58:20 -07001892 if (status_code != WLAN_STATUS_SUCCESS)
1893 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001894 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001895 if (wpa_s->sme.sae.state != SAE_CONFIRMED)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001896 return -1;
Sunil Ravi77d572f2023-01-17 23:58:31 +00001897 if (sae_check_confirm(&wpa_s->sme.sae, data, len,
1898 ie_offset) < 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001899 return -1;
Sunil Ravi036cec52023-03-29 11:35:17 -07001900 if (external && wpa_s->sme.ext_ml_auth &&
Sunil Ravi640215c2023-06-28 23:08:09 +00001901 sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1902 status_code))
Sunil Ravi036cec52023-03-29 11:35:17 -07001903 return -1;
1904
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001905 wpa_s->sme.sae.state = SAE_ACCEPTED;
1906 sae_clear_temp_data(&wpa_s->sme.sae);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001907
1908 if (external) {
1909 /* Report success to driver */
1910 sme_send_external_auth_status(wpa_s,
1911 WLAN_STATUS_SUCCESS);
1912 }
1913
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001914 return 1;
1915 }
1916
1917 return -1;
1918}
Roshan Pius3a1667e2018-07-03 15:17:14 -07001919
1920
Hai Shalomc3565922019-10-28 11:58:20 -07001921static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
1922{
1923 wpa_printf(MSG_DEBUG,
1924 "SME: SAE completed - setting PMK for 4-way handshake");
Sunil Ravi89eba102022-09-13 21:04:37 -07001925 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 -07001926 wpa_s->sme.sae.pmkid, bssid);
1927 if (wpa_s->conf->sae_pmkid_in_assoc) {
1928 /* Update the own RSNE contents now that we have set the PMK
1929 * and added a PMKSA cache entry based on the successfully
1930 * completed SAE exchange. In practice, this will add the PMKID
1931 * into RSNE. */
1932 if (wpa_s->sme.assoc_req_ie_len + 2 + PMKID_LEN >
1933 sizeof(wpa_s->sme.assoc_req_ie)) {
1934 wpa_msg(wpa_s, MSG_WARNING,
1935 "RSN: Not enough room for inserting own PMKID into RSNE");
1936 return -1;
1937 }
1938 if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
1939 &wpa_s->sme.assoc_req_ie_len,
1940 wpa_s->sme.sae.pmkid) < 0)
1941 return -1;
1942 wpa_hexdump(MSG_DEBUG,
1943 "SME: Updated Association Request IEs",
1944 wpa_s->sme.assoc_req_ie,
1945 wpa_s->sme.assoc_req_ie_len);
1946 }
1947
1948 return 0;
1949}
1950
1951
Roshan Pius3a1667e2018-07-03 15:17:14 -07001952void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
1953 const u8 *auth_frame, size_t len)
1954{
1955 const struct ieee80211_mgmt *header;
1956 size_t auth_length;
1957
1958 header = (const struct ieee80211_mgmt *) auth_frame;
1959 auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);
1960
1961 if (len < auth_length) {
1962 /* Notify failure to the driver */
1963 sme_send_external_auth_status(wpa_s,
1964 WLAN_STATUS_UNSPECIFIED_FAILURE);
1965 return;
1966 }
1967
Hai Shalom74f70d42019-02-11 14:42:39 -08001968 if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001969 int res;
Sunil Ravi036cec52023-03-29 11:35:17 -07001970 int ie_offset = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001971
Hai Shalom74f70d42019-02-11 14:42:39 -08001972 res = sme_sae_auth(
1973 wpa_s, le_to_host16(header->u.auth.auth_transaction),
1974 le_to_host16(header->u.auth.status_code),
1975 header->u.auth.variable,
Sunil Ravi036cec52023-03-29 11:35:17 -07001976 len - auth_length, 1, header->sa, &ie_offset);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001977 if (res < 0) {
1978 /* Notify failure to the driver */
1979 sme_send_external_auth_status(
Sunil Ravia04bd252022-05-02 22:54:18 -07001980 wpa_s,
1981 res == -2 ?
1982 le_to_host16(header->u.auth.status_code) :
1983 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001984 return;
1985 }
1986 if (res != 1)
1987 return;
1988
Sunil Ravi036cec52023-03-29 11:35:17 -07001989 if (sme_sae_set_pmk(wpa_s,
1990 wpa_s->sme.ext_ml_auth ?
1991 wpa_s->sme.ext_auth_ap_mld_addr :
1992 wpa_s->sme.ext_auth_bssid) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07001993 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001994 }
1995}
1996
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001997#endif /* CONFIG_SAE */
1998
1999
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002000void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
2001{
2002 struct wpa_ssid *ssid = wpa_s->current_ssid;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002003 int ie_offset = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002004
2005 if (ssid == NULL) {
2006 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
2007 "when network is not selected");
2008 return;
2009 }
2010
2011 if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
2012 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
2013 "when not in authenticating state");
2014 return;
2015 }
2016
Sunil Ravi77d572f2023-01-17 23:58:31 +00002017 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0 &&
2018 !(wpa_s->valid_links &&
2019 os_memcmp(wpa_s->ap_mld_addr, data->auth.peer, ETH_ALEN) == 0)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002020 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
2021 "unexpected peer " MACSTR,
2022 MAC2STR(data->auth.peer));
2023 return;
2024 }
2025
2026 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002027 " auth_type=%d auth_transaction=%d status_code=%d",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002028 MAC2STR(data->auth.peer), data->auth.auth_type,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002029 data->auth.auth_transaction, data->auth.status_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002030 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
2031 data->auth.ies, data->auth.ies_len);
2032
2033 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2034
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002035#ifdef CONFIG_SAE
2036 if (data->auth.auth_type == WLAN_AUTH_SAE) {
Sunil Ravi77d572f2023-01-17 23:58:31 +00002037 const u8 *addr = wpa_s->pending_bssid;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002038 int res;
Sunil Ravi77d572f2023-01-17 23:58:31 +00002039
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002040 res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
2041 data->auth.status_code, data->auth.ies,
Sunil Ravi77d572f2023-01-17 23:58:31 +00002042 data->auth.ies_len, 0, data->auth.peer,
2043 &ie_offset);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002044 if (res < 0) {
2045 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2046 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2047
2048 }
2049 if (res != 1)
2050 return;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002051
Sunil Ravi77d572f2023-01-17 23:58:31 +00002052 if (wpa_s->valid_links)
2053 addr = wpa_s->ap_mld_addr;
2054
2055 if (sme_sae_set_pmk(wpa_s, addr) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -07002056 return;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002057 }
2058#endif /* CONFIG_SAE */
2059
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002060 if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002061 char *ie_txt = NULL;
2062
2063 if (data->auth.ies && data->auth.ies_len) {
2064 size_t buflen = 2 * data->auth.ies_len + 1;
2065 ie_txt = os_malloc(buflen);
2066 if (ie_txt) {
2067 wpa_snprintf_hex(ie_txt, buflen, data->auth.ies,
2068 data->auth.ies_len);
2069 }
2070 }
2071 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002072 " auth_type=%u auth_transaction=%u status_code=%u%s%s",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002073 MAC2STR(data->auth.peer), data->auth.auth_type,
2074 data->auth.auth_transaction, data->auth.status_code,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002075 ie_txt ? " ie=" : "",
2076 ie_txt ? ie_txt : "");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002077 os_free(ie_txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002078
Hai Shalomce48b4a2018-09-05 11:41:35 -07002079#ifdef CONFIG_FILS
2080 if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
2081 wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS)
2082 fils_connection_failure(wpa_s);
2083#endif /* CONFIG_FILS */
2084
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002085 if (data->auth.status_code !=
2086 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
2087 wpa_s->sme.auth_alg == data->auth.auth_type ||
2088 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
2089 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002090 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002091 return;
2092 }
2093
Dmitry Shmidt97672262014-02-03 13:02:54 -08002094 wpas_connect_work_done(wpa_s);
2095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002096 switch (data->auth.auth_type) {
2097 case WLAN_AUTH_OPEN:
2098 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
2099
2100 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
2101 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2102 wpa_s->current_ssid);
2103 return;
2104
2105 case WLAN_AUTH_SHARED_KEY:
2106 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
2107
2108 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
2109 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2110 wpa_s->current_ssid);
2111 return;
2112
2113 default:
2114 return;
2115 }
2116 }
2117
2118#ifdef CONFIG_IEEE80211R
2119 if (data->auth.auth_type == WLAN_AUTH_FT) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002120 const u8 *ric_ies = NULL;
2121 size_t ric_ies_len = 0;
2122
2123 if (wpa_s->ric_ies) {
2124 ric_ies = wpabuf_head(wpa_s->ric_ies);
2125 ric_ies_len = wpabuf_len(wpa_s->ric_ies);
2126 }
Dmitry Shmidt41712582015-06-29 11:02:15 -07002127 if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
2128 data->auth.ies_len, 0,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002129 data->auth.peer,
2130 ric_ies, ric_ies_len) < 0) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07002131 wpa_dbg(wpa_s, MSG_DEBUG,
2132 "SME: FT Authentication response processing failed");
2133 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2134 MACSTR
2135 " reason=%d locally_generated=1",
2136 MAC2STR(wpa_s->pending_bssid),
2137 WLAN_REASON_DEAUTH_LEAVING);
2138 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2139 wpa_supplicant_mark_disassoc(wpa_s);
2140 return;
2141 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002142 }
2143#endif /* CONFIG_IEEE80211R */
2144
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002145#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002146 if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
2147 data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
2148 u16 expect_auth_type;
2149
2150 expect_auth_type = wpa_s->sme.auth_alg ==
2151 WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
2152 WLAN_AUTH_FILS_SK;
2153 if (data->auth.auth_type != expect_auth_type) {
2154 wpa_dbg(wpa_s, MSG_DEBUG,
2155 "SME: FILS Authentication response used different auth alg (%u; expected %u)",
2156 data->auth.auth_type, expect_auth_type);
2157 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2158 MACSTR
2159 " reason=%d locally_generated=1",
2160 MAC2STR(wpa_s->pending_bssid),
2161 WLAN_REASON_DEAUTH_LEAVING);
2162 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2163 wpa_supplicant_mark_disassoc(wpa_s);
2164 return;
2165 }
2166
2167 if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
2168 data->auth.ies, data->auth.ies_len) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002169 wpa_dbg(wpa_s, MSG_DEBUG,
2170 "SME: FILS Authentication response processing failed");
2171 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2172 MACSTR
2173 " reason=%d locally_generated=1",
2174 MAC2STR(wpa_s->pending_bssid),
2175 WLAN_REASON_DEAUTH_LEAVING);
2176 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2177 wpa_supplicant_mark_disassoc(wpa_s);
2178 return;
2179 }
2180 }
2181#endif /* CONFIG_FILS */
2182
Sunil Ravi77d572f2023-01-17 23:58:31 +00002183 /* TODO: Support additional auth_type values as well */
2184 if (data->auth.auth_type == WLAN_AUTH_OPEN ||
2185 data->auth.auth_type == WLAN_AUTH_SAE)
2186 wpas_sme_ml_auth(wpa_s, data, ie_offset);
2187
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002188 sme_associate(wpa_s, ssid->mode, data->auth.peer,
2189 data->auth.auth_type);
2190}
2191
2192
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002193#ifdef CONFIG_IEEE80211R
2194static void remove_ie(u8 *buf, size_t *len, u8 eid)
2195{
2196 u8 *pos, *next, *end;
2197
2198 pos = (u8 *) get_ie(buf, *len, eid);
2199 if (pos) {
2200 next = pos + 2 + pos[1];
2201 end = buf + *len;
2202 *len -= 2 + pos[1];
2203 os_memmove(pos, next, end - next);
2204 }
2205}
2206#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002207
2208
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002209void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
2210 const u8 *bssid, u16 auth_type)
2211{
2212 struct wpa_driver_associate_params params;
2213 struct ieee802_11_elems elems;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002214 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002215#ifdef CONFIG_FILS
2216 u8 nonces[2 * FILS_NONCE_LEN];
2217#endif /* CONFIG_FILS */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002218#ifdef CONFIG_HT_OVERRIDES
2219 struct ieee80211_ht_capabilities htcaps;
2220 struct ieee80211_ht_capabilities htcaps_mask;
2221#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002222#ifdef CONFIG_VHT_OVERRIDES
2223 struct ieee80211_vht_capabilities vhtcaps;
2224 struct ieee80211_vht_capabilities vhtcaps_mask;
2225#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002226
2227 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002228
2229#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002230 if (auth_type == WLAN_AUTH_FILS_SK ||
2231 auth_type == WLAN_AUTH_FILS_SK_PFS) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002232 struct wpabuf *buf;
2233 const u8 *snonce, *anonce;
Paul Stewart092955c2017-02-06 09:13:09 -08002234 const unsigned int max_hlp = 20;
2235 struct wpabuf *hlp[max_hlp];
2236 unsigned int i, num_hlp = 0;
2237 struct fils_hlp_req *req;
2238
2239 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2240 list) {
2241 hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
2242 wpabuf_len(req->pkt));
2243 if (!hlp[num_hlp])
2244 break;
2245 wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
2246 wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
2247 ETH_ALEN);
2248 wpabuf_put_data(hlp[num_hlp],
2249 "\xaa\xaa\x03\x00\x00\x00", 6);
2250 wpabuf_put_buf(hlp[num_hlp], req->pkt);
2251 num_hlp++;
2252 if (num_hlp >= max_hlp)
2253 break;
2254 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002255
2256 buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
2257 &params.fils_kek_len, &snonce,
Paul Stewart092955c2017-02-06 09:13:09 -08002258 &anonce,
2259 (const struct wpabuf **) hlp,
2260 num_hlp);
2261 for (i = 0; i < num_hlp; i++)
2262 wpabuf_free(hlp[i]);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002263 if (!buf)
2264 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002265 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req before FILS elements",
2266 wpa_s->sme.assoc_req_ie,
2267 wpa_s->sme.assoc_req_ie_len);
2268#ifdef CONFIG_IEEE80211R
2269 if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
2270 /* Remove RSNE and MDE to allow them to be overridden
2271 * with FILS+FT specific values from
2272 * fils_build_assoc_req(). */
2273 remove_ie(wpa_s->sme.assoc_req_ie,
2274 &wpa_s->sme.assoc_req_ie_len,
2275 WLAN_EID_RSN);
2276 wpa_hexdump(MSG_DEBUG,
2277 "FILS: assoc_req after RSNE removal",
2278 wpa_s->sme.assoc_req_ie,
2279 wpa_s->sme.assoc_req_ie_len);
2280 remove_ie(wpa_s->sme.assoc_req_ie,
2281 &wpa_s->sme.assoc_req_ie_len,
2282 WLAN_EID_MOBILITY_DOMAIN);
2283 wpa_hexdump(MSG_DEBUG,
2284 "FILS: assoc_req after MDE removal",
2285 wpa_s->sme.assoc_req_ie,
2286 wpa_s->sme.assoc_req_ie_len);
2287 }
2288#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002289 /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
2290 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
2291 sizeof(wpa_s->sme.assoc_req_ie)) {
2292 wpa_printf(MSG_ERROR,
2293 "FILS: Not enough buffer room for own AssocReq elements");
2294 wpabuf_free(buf);
2295 return;
2296 }
2297 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2298 wpabuf_head(buf), wpabuf_len(buf));
2299 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
2300 wpabuf_free(buf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002301 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req after FILS elements",
2302 wpa_s->sme.assoc_req_ie,
2303 wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002304
2305 os_memcpy(nonces, snonce, FILS_NONCE_LEN);
2306 os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
2307 params.fils_nonces = nonces;
2308 params.fils_nonces_len = sizeof(nonces);
2309 }
2310#endif /* CONFIG_FILS */
2311
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002312#ifdef CONFIG_OWE
2313#ifdef CONFIG_TESTING_OPTIONS
2314 if (get_ie_ext(wpa_s->sme.assoc_req_ie, wpa_s->sme.assoc_req_ie_len,
2315 WLAN_EID_EXT_OWE_DH_PARAM)) {
2316 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2317 } else
2318#endif /* CONFIG_TESTING_OPTIONS */
2319 if (auth_type == WLAN_AUTH_OPEN &&
2320 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2321 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002322 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002323
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002324 if (ssid && ssid->owe_group) {
2325 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08002326 } else if (wpa_s->assoc_status_code ==
2327 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002328 if (wpa_s->last_owe_group == 19)
2329 group = 20;
2330 else if (wpa_s->last_owe_group == 20)
2331 group = 21;
2332 else
2333 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002334 } else {
2335 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002336 }
Hai Shalom74f70d42019-02-11 14:42:39 -08002337
Roshan Pius3a1667e2018-07-03 15:17:14 -07002338 wpa_s->last_owe_group = group;
2339 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002340 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2341 if (!owe_ie) {
2342 wpa_printf(MSG_ERROR,
2343 "OWE: Failed to build IE for Association Request frame");
2344 return;
2345 }
2346 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(owe_ie) >
2347 sizeof(wpa_s->sme.assoc_req_ie)) {
2348 wpa_printf(MSG_ERROR,
2349 "OWE: Not enough buffer room for own Association Request frame elements");
2350 wpabuf_free(owe_ie);
2351 return;
2352 }
2353 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2354 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2355 wpa_s->sme.assoc_req_ie_len += wpabuf_len(owe_ie);
2356 wpabuf_free(owe_ie);
2357 }
2358#endif /* CONFIG_OWE */
2359
Hai Shalom021b0b52019-04-10 11:17:58 -07002360#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002361 if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid &&
2362 ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 &&
2363 !ssid->dpp_pfs_fallback) {
2364 struct rsn_pmksa_cache_entry *pmksa;
2365
2366 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2367 if (!pmksa || !pmksa->dpp_pfs)
2368 goto pfs_fail;
Hai Shalom021b0b52019-04-10 11:17:58 -07002369
2370 dpp_pfs_free(wpa_s->dpp_pfs);
2371 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
2372 ssid->dpp_netaccesskey_len);
2373 if (!wpa_s->dpp_pfs) {
2374 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
2375 /* Try to continue without PFS */
2376 goto pfs_fail;
2377 }
2378 if (wpa_s->sme.assoc_req_ie_len +
2379 wpabuf_len(wpa_s->dpp_pfs->ie) >
2380 sizeof(wpa_s->sme.assoc_req_ie)) {
2381 wpa_printf(MSG_ERROR,
2382 "DPP: Not enough buffer room for own Association Request frame elements");
2383 dpp_pfs_free(wpa_s->dpp_pfs);
2384 wpa_s->dpp_pfs = NULL;
2385 goto pfs_fail;
2386 }
2387 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2388 wpabuf_head(wpa_s->dpp_pfs->ie),
2389 wpabuf_len(wpa_s->dpp_pfs->ie));
2390 wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
2391 }
2392pfs_fail:
2393#endif /* CONFIG_DPP2 */
2394
Hai Shalom899fcc72020-10-19 14:38:18 -07002395 wpa_s->mscs_setup_done = false;
Hai Shalom60840252021-02-19 19:02:11 -08002396 if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
2397 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07002398 struct wpabuf *mscs_ie;
2399 size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len;
2400
Hai Shalom899fcc72020-10-19 14:38:18 -07002401 buf_len = 3 + /* MSCS descriptor IE header */
2402 1 + /* Request type */
2403 2 + /* User priority control */
2404 4 + /* Stream timeout */
2405 3 + /* TCLAS Mask IE header */
2406 wpa_s->robust_av.frame_classifier_len;
2407 mscs_ie = wpabuf_alloc(buf_len);
2408 if (!mscs_ie) {
2409 wpa_printf(MSG_INFO,
2410 "MSCS: Failed to allocate MSCS IE");
2411 goto mscs_fail;
2412 }
2413
2414 wpa_ie_len = &wpa_s->sme.assoc_req_ie_len;
2415 max_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
2416 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
2417 if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) {
2418 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
2419 mscs_ie_len = wpabuf_len(mscs_ie);
2420 os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len,
2421 wpabuf_head(mscs_ie), mscs_ie_len);
2422 *wpa_ie_len += mscs_ie_len;
2423 }
2424
2425 wpabuf_free(mscs_ie);
2426 }
2427mscs_fail:
2428
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002429 if (ssid && ssid->multi_ap_backhaul_sta) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002430 size_t multi_ap_ie_len;
2431
2432 multi_ap_ie_len = add_multi_ap_ie(
2433 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2434 sizeof(wpa_s->sme.assoc_req_ie) -
2435 wpa_s->sme.assoc_req_ie_len,
2436 MULTI_AP_BACKHAUL_STA);
2437 if (multi_ap_ie_len == 0) {
2438 wpa_printf(MSG_ERROR,
2439 "Multi-AP: Failed to build Multi-AP IE");
2440 return;
2441 }
2442 wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
2443 }
2444
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445 params.bssid = bssid;
2446 params.ssid = wpa_s->sme.ssid;
2447 params.ssid_len = wpa_s->sme.ssid_len;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002448 params.freq.freq = wpa_s->sme.freq;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002449 params.bg_scan_period = ssid ? ssid->bg_scan_period : -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002450 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
2451 wpa_s->sme.assoc_req_ie : NULL;
2452 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08002453 wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
2454 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002455 params.pairwise_suite = wpa_s->pairwise_cipher;
2456 params.group_suite = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002457 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
Dmitry Shmidt15907092014-03-25 10:42:57 -07002458 params.key_mgmt_suite = wpa_s->key_mgmt;
2459 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002460#ifdef CONFIG_HT_OVERRIDES
2461 os_memset(&htcaps, 0, sizeof(htcaps));
2462 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2463 params.htcaps = (u8 *) &htcaps;
2464 params.htcaps_mask = (u8 *) &htcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002465 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002466#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002467#ifdef CONFIG_VHT_OVERRIDES
2468 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2469 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2470 params.vhtcaps = &vhtcaps;
2471 params.vhtcaps_mask = &vhtcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002472 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07002473#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07002474#ifdef CONFIG_HE_OVERRIDES
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002475 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
Hai Shalomfdcde762020-04-02 11:19:20 -07002476#endif /* CONFIG_HE_OVERRIDES */
Sunil Ravi77d572f2023-01-17 23:58:31 +00002477 wpa_supplicant_apply_eht_overrides(wpa_s, ssid, &params);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478#ifdef CONFIG_IEEE80211R
Hai Shalom74f70d42019-02-11 14:42:39 -08002479 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
2480 get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
2481 WLAN_EID_RIC_DATA)) {
2482 /* There seems to be a pretty inconvenient bug in the Linux
2483 * kernel IE splitting functionality when RIC is used. For now,
2484 * skip correct behavior in IE construction here (i.e., drop the
2485 * additional non-FT-specific IEs) to avoid kernel issues. This
2486 * is fine since RIC is used only for testing purposes in the
2487 * current implementation. */
2488 wpa_printf(MSG_INFO,
2489 "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002490 params.wpa_ie = wpa_s->sme.ft_ies;
2491 params.wpa_ie_len = wpa_s->sme.ft_ies_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08002492 } else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
2493 const u8 *rm_en, *pos, *end;
2494 size_t rm_en_len = 0;
2495 u8 *rm_en_dup = NULL, *wpos;
2496
2497 /* Remove RSNE, MDE, FTE to allow them to be overridden with
2498 * FT specific values */
2499 remove_ie(wpa_s->sme.assoc_req_ie,
2500 &wpa_s->sme.assoc_req_ie_len,
2501 WLAN_EID_RSN);
2502 remove_ie(wpa_s->sme.assoc_req_ie,
2503 &wpa_s->sme.assoc_req_ie_len,
2504 WLAN_EID_MOBILITY_DOMAIN);
2505 remove_ie(wpa_s->sme.assoc_req_ie,
2506 &wpa_s->sme.assoc_req_ie_len,
2507 WLAN_EID_FAST_BSS_TRANSITION);
2508 rm_en = get_ie(wpa_s->sme.assoc_req_ie,
2509 wpa_s->sme.assoc_req_ie_len,
2510 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2511 if (rm_en) {
2512 /* Need to remove RM Enabled Capabilities element as
2513 * well temporarily, so that it can be placed between
2514 * RSNE and MDE. */
2515 rm_en_len = 2 + rm_en[1];
2516 rm_en_dup = os_memdup(rm_en, rm_en_len);
2517 remove_ie(wpa_s->sme.assoc_req_ie,
2518 &wpa_s->sme.assoc_req_ie_len,
2519 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2520 }
2521 wpa_hexdump(MSG_DEBUG,
2522 "SME: Association Request IEs after FT IE removal",
2523 wpa_s->sme.assoc_req_ie,
2524 wpa_s->sme.assoc_req_ie_len);
2525 if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
2526 rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
2527 wpa_printf(MSG_ERROR,
2528 "SME: Not enough buffer room for FT IEs in Association Request frame");
2529 os_free(rm_en_dup);
2530 return;
2531 }
2532
2533 os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
2534 rm_en_len,
2535 wpa_s->sme.assoc_req_ie,
2536 wpa_s->sme.assoc_req_ie_len);
2537 pos = wpa_s->sme.ft_ies;
2538 end = pos + wpa_s->sme.ft_ies_len;
2539 wpos = wpa_s->sme.assoc_req_ie;
2540 if (*pos == WLAN_EID_RSN) {
2541 os_memcpy(wpos, pos, 2 + pos[1]);
2542 wpos += 2 + pos[1];
2543 pos += 2 + pos[1];
2544 }
2545 if (rm_en_dup) {
2546 os_memcpy(wpos, rm_en_dup, rm_en_len);
2547 wpos += rm_en_len;
2548 os_free(rm_en_dup);
2549 }
2550 os_memcpy(wpos, pos, end - pos);
2551 wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
2552 rm_en_len;
2553 params.wpa_ie = wpa_s->sme.assoc_req_ie;
2554 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
2555 wpa_hexdump(MSG_DEBUG,
2556 "SME: Association Request IEs after FT override",
2557 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 }
2559#endif /* CONFIG_IEEE80211R */
2560 params.mode = mode;
2561 params.mgmt_frame_protection = wpa_s->sme.mfp;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002562 params.rrm_used = wpa_s->rrm.rrm_used;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002563 if (wpa_s->sme.prev_bssid_set)
2564 params.prev_bssid = wpa_s->sme.prev_bssid;
2565
2566 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2567 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
2568 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002569 params.freq.freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570
2571 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2572
2573 if (params.wpa_ie == NULL ||
2574 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
2575 < 0) {
2576 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
2577 os_memset(&elems, 0, sizeof(elems));
2578 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002579 if (elems.rsn_ie) {
2580 params.wpa_proto = WPA_PROTO_RSN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
2582 elems.rsn_ie_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002583 } else if (elems.wpa_ie) {
2584 params.wpa_proto = WPA_PROTO_WPA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002585 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
2586 elems.wpa_ie_len + 2);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002587 } else if (elems.osen) {
2588 params.wpa_proto = WPA_PROTO_OSEN;
2589 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
2590 elems.osen_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002591 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07002593 if (elems.rsnxe)
2594 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, elems.rsnxe - 2,
2595 elems.rsnxe_len + 2);
2596 else
2597 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002598 if (ssid && ssid->p2p_group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599 params.p2p = 1;
2600
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002601 if (wpa_s->p2pdev->set_sta_uapsd)
2602 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 else
2604 params.uapsd = -1;
2605
Sunil Ravi77d572f2023-01-17 23:58:31 +00002606 if (wpa_s->valid_links) {
2607 unsigned int i;
2608
2609 wpa_printf(MSG_DEBUG,
2610 "MLD: In association. assoc_link_id=%u, valid_links=0x%x",
2611 wpa_s->mlo_assoc_link_id, wpa_s->valid_links);
2612
2613 params.mld_params.mld_addr = wpa_s->ap_mld_addr;
2614 params.mld_params.valid_links = wpa_s->valid_links;
2615 params.mld_params.assoc_link_id = wpa_s->mlo_assoc_link_id;
2616 for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
2617 if (!(wpa_s->valid_links & BIT(i)))
2618 continue;
2619
2620 params.mld_params.mld_links[i].bssid =
2621 wpa_s->links[i].bssid;
2622 params.mld_params.mld_links[i].freq =
2623 wpa_s->links[i].freq;
2624
2625 wpa_printf(MSG_DEBUG, "MLD: id=%u, freq=%d, " MACSTR,
2626 i, wpa_s->links[i].freq,
2627 MAC2STR(wpa_s->links[i].bssid));
2628 }
2629 }
2630
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631 if (wpa_drv_associate(wpa_s, &params) < 0) {
2632 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
2633 "driver failed");
2634 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002635 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002636 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2637 return;
2638 }
2639
2640 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
2641 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002642
2643#ifdef CONFIG_TESTING_OPTIONS
2644 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
2645 wpa_s->last_assoc_req_wpa_ie = NULL;
2646 if (params.wpa_ie)
2647 wpa_s->last_assoc_req_wpa_ie =
2648 wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len);
2649#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002650}
2651
2652
2653int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
2654 const u8 *ies, size_t ies_len)
2655{
2656 if (md == NULL || ies == NULL) {
2657 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
2658 os_free(wpa_s->sme.ft_ies);
2659 wpa_s->sme.ft_ies = NULL;
2660 wpa_s->sme.ft_ies_len = 0;
2661 wpa_s->sme.ft_used = 0;
2662 return 0;
2663 }
2664
2665 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
2666 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
2667 os_free(wpa_s->sme.ft_ies);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002668 wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002669 if (wpa_s->sme.ft_ies == NULL)
2670 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002671 wpa_s->sme.ft_ies_len = ies_len;
2672 return 0;
2673}
2674
2675
2676static void sme_deauth(struct wpa_supplicant *wpa_s)
2677{
2678 int bssid_changed;
2679
2680 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2681
2682 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
2683 WLAN_REASON_DEAUTH_LEAVING) < 0) {
2684 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
2685 "failed");
2686 }
2687 wpa_s->sme.prev_bssid_set = 0;
2688
2689 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2690 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2691 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2692 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2693 if (bssid_changed)
2694 wpas_notify_bssid_changed(wpa_s);
2695}
2696
2697
2698void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
2699 union wpa_event_data *data)
2700{
2701 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
2702 "status code %d", MAC2STR(wpa_s->pending_bssid),
2703 data->assoc_reject.status_code);
2704
2705 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2706
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002707#ifdef CONFIG_SAE
2708 if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
2709 wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
2710 wpa_dbg(wpa_s, MSG_DEBUG,
2711 "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
2712 wpa_sm_aborted_cached(wpa_s->wpa);
2713 wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
2714 if (wpa_s->current_bss) {
2715 struct wpa_bss *bss = wpa_s->current_bss;
2716 struct wpa_ssid *ssid = wpa_s->current_ssid;
2717
2718 wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
2719 WLAN_REASON_DEAUTH_LEAVING);
2720 wpas_connect_work_done(wpa_s);
2721 wpa_supplicant_mark_disassoc(wpa_s);
2722 wpa_supplicant_connect(wpa_s, bss, ssid);
2723 return;
2724 }
2725 }
2726#endif /* CONFIG_SAE */
2727
Sunil Ravi77d572f2023-01-17 23:58:31 +00002728#ifdef CONFIG_DPP
2729 if (wpa_s->current_ssid &&
2730 wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
2731 !data->assoc_reject.timed_out &&
2732 data->assoc_reject.status_code == WLAN_STATUS_INVALID_PMKID) {
2733 struct rsn_pmksa_cache_entry *pmksa;
2734
2735 pmksa = pmksa_cache_get_current(wpa_s->wpa);
2736 if (pmksa) {
2737 wpa_dbg(wpa_s, MSG_DEBUG,
2738 "DPP: Drop PMKSA cache entry for the BSS due to invalid PMKID report");
2739 wpa_sm_pmksa_cache_remove(wpa_s->wpa, pmksa);
2740 }
2741 wpa_sm_aborted_cached(wpa_s->wpa);
2742 if (wpa_s->current_bss) {
2743 struct wpa_bss *bss = wpa_s->current_bss;
2744 struct wpa_ssid *ssid = wpa_s->current_ssid;
2745
2746 wpa_dbg(wpa_s, MSG_DEBUG,
2747 "DPP: Try network introduction again");
2748 wpas_connect_work_done(wpa_s);
2749 wpa_supplicant_mark_disassoc(wpa_s);
2750 wpa_supplicant_connect(wpa_s, bss, ssid);
2751 return;
2752 }
2753 }
2754#endif /* CONFIG_DPP */
2755
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002756 /*
2757 * For now, unconditionally terminate the previous authentication. In
2758 * theory, this should not be needed, but mac80211 gets quite confused
2759 * if the authentication is left pending.. Some roaming cases might
2760 * benefit from using the previous authentication, so this could be
2761 * optimized in the future.
2762 */
2763 sme_deauth(wpa_s);
2764}
2765
2766
2767void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
2768 union wpa_event_data *data)
2769{
2770 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
2771 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002772 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002773}
2774
2775
2776void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
2777 union wpa_event_data *data)
2778{
2779 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
2780 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2781 wpa_supplicant_mark_disassoc(wpa_s);
2782}
2783
2784
2785void sme_event_disassoc(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002786 struct disassoc_info *info)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002787{
2788 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002789 if (wpa_s->sme.prev_bssid_set) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002790 /*
2791 * cfg80211/mac80211 can get into somewhat confused state if
2792 * the AP only disassociates us and leaves us in authenticated
2793 * state. For now, force the state to be cleared to avoid
2794 * confusing errors if we try to associate with the AP again.
2795 */
2796 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
2797 "driver state");
2798 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
2799 WLAN_REASON_DEAUTH_LEAVING);
2800 }
2801}
2802
2803
2804static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
2805{
2806 struct wpa_supplicant *wpa_s = eloop_ctx;
2807 if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
2808 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
2809 sme_deauth(wpa_s);
2810 }
2811}
2812
2813
2814static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
2815{
2816 struct wpa_supplicant *wpa_s = eloop_ctx;
2817 if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2818 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
2819 sme_deauth(wpa_s);
2820 }
2821}
2822
2823
2824void sme_state_changed(struct wpa_supplicant *wpa_s)
2825{
2826 /* Make sure timers are cleaned up appropriately. */
2827 if (wpa_s->wpa_state != WPA_ASSOCIATING)
2828 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2829 if (wpa_s->wpa_state != WPA_AUTHENTICATING)
2830 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2831}
2832
2833
2834void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
2835 const u8 *prev_pending_bssid)
2836{
2837 /*
2838 * mac80211-workaround to force deauth on failed auth cmd,
2839 * requires us to remain in authenticating state to allow the
2840 * second authentication attempt to be continued properly.
2841 */
2842 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
2843 "to proceed after disconnection event");
2844 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
2845 os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
2846
2847 /*
2848 * Re-arm authentication timer in case auth fails for whatever reason.
2849 */
2850 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2851 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
2852 NULL);
2853}
2854
2855
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002856void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
2857{
2858 wpa_s->sme.prev_bssid_set = 0;
2859#ifdef CONFIG_SAE
2860 wpabuf_free(wpa_s->sme.sae_token);
2861 wpa_s->sme.sae_token = NULL;
2862 sae_clear_data(&wpa_s->sme.sae);
2863#endif /* CONFIG_SAE */
2864#ifdef CONFIG_IEEE80211R
Roshan Pius3a1667e2018-07-03 15:17:14 -07002865 if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002866 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
2867#endif /* CONFIG_IEEE80211R */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002868 sme_stop_sa_query(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002869}
2870
2871
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002872void sme_deinit(struct wpa_supplicant *wpa_s)
2873{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002874 sme_clear_on_disassoc(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002875#ifdef CONFIG_SAE
2876 os_free(wpa_s->sme.sae_rejected_groups);
2877 wpa_s->sme.sae_rejected_groups = NULL;
2878#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002879
2880 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2881 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002882 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
2883}
2884
2885
2886static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
2887 const u8 *chan_list, u8 num_channels,
2888 u8 num_intol)
2889{
2890 struct ieee80211_2040_bss_coex_ie *bc_ie;
2891 struct ieee80211_2040_intol_chan_report *ic_report;
2892 struct wpabuf *buf;
2893
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002894 wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
2895 " (num_channels=%u num_intol=%u)",
2896 MAC2STR(wpa_s->bssid), num_channels, num_intol);
2897 wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
2898 chan_list, num_channels);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002899
2900 buf = wpabuf_alloc(2 + /* action.category + action_code */
2901 sizeof(struct ieee80211_2040_bss_coex_ie) +
2902 sizeof(struct ieee80211_2040_intol_chan_report) +
2903 num_channels);
2904 if (buf == NULL)
2905 return;
2906
2907 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
2908 wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
2909
2910 bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
2911 bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
2912 bc_ie->length = 1;
2913 if (num_intol)
2914 bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
2915
2916 if (num_channels > 0) {
2917 ic_report = wpabuf_put(buf, sizeof(*ic_report));
2918 ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
2919 ic_report->length = num_channels + 1;
2920 ic_report->op_class = 0;
2921 os_memcpy(wpabuf_put(buf, num_channels), chan_list,
2922 num_channels);
2923 }
2924
2925 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
2926 wpa_s->own_addr, wpa_s->bssid,
2927 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
2928 wpa_msg(wpa_s, MSG_INFO,
2929 "SME: Failed to send 20/40 BSS Coexistence frame");
2930 }
2931
2932 wpabuf_free(buf);
2933}
2934
2935
Hai Shaloma20dcd72022-02-04 13:43:00 -08002936int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002937{
Hai Shaloma20dcd72022-02-04 13:43:00 -08002938 struct wpa_bss *bss;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002939 const u8 *ie;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002940 u16 ht_cap;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002941 u8 chan_list[P2P_MAX_CHANNELS], channel;
2942 u8 num_channels = 0, num_intol = 0, i;
2943
2944 if (!wpa_s->sme.sched_obss_scan)
2945 return 0;
2946
2947 wpa_s->sme.sched_obss_scan = 0;
2948 if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
2949 return 1;
2950
2951 /*
2952 * Check whether AP uses regulatory triplet or channel triplet in
2953 * country info. Right now the operating class of the BSS channel
2954 * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
2955 * based on the assumption that operating class triplet is not used in
2956 * beacon frame. If the First Channel Number/Operating Extension
2957 * Identifier octet has a positive integer value of 201 or greater,
2958 * then its operating class triplet.
2959 *
2960 * TODO: If Supported Operating Classes element is present in beacon
2961 * frame, have to lookup operating class in Annex E and fill them in
2962 * 2040 coex frame.
2963 */
2964 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
2965 if (ie && (ie[1] >= 6) && (ie[5] >= 201))
2966 return 1;
2967
2968 os_memset(chan_list, 0, sizeof(chan_list));
2969
Hai Shaloma20dcd72022-02-04 13:43:00 -08002970 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002971 /* Skip other band bss */
Hai Shaloma20dcd72022-02-04 13:43:00 -08002972 enum hostapd_hw_mode mode;
Dmitry Shmidt4b060592013-04-29 16:42:49 -07002973 mode = ieee80211_freq_to_chan(bss->freq, &channel);
2974 if (mode != HOSTAPD_MODE_IEEE80211G &&
2975 mode != HOSTAPD_MODE_IEEE80211B)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002976 continue;
2977
Hai Shaloma20dcd72022-02-04 13:43:00 -08002978 ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
2979 ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
2980 wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
2981 " freq=%u chan=%u ht_cap=0x%x",
2982 MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
2983
2984 if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
2985 if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002986 num_intol++;
2987
Dmitry Shmidt04949592012-07-19 12:16:46 -07002988 /* Check whether the channel is already considered */
2989 for (i = 0; i < num_channels; i++) {
2990 if (channel == chan_list[i])
2991 break;
2992 }
2993 if (i != num_channels)
2994 continue;
2995
Dmitry Shmidt04949592012-07-19 12:16:46 -07002996 chan_list[num_channels++] = channel;
2997 }
2998 }
2999
3000 sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
3001 return 1;
3002}
3003
3004
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003005static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
3006 struct wpa_driver_scan_params *params)
Dmitry Shmidt04949592012-07-19 12:16:46 -07003007{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003008 /* Include only affected channels */
Dmitry Shmidt04949592012-07-19 12:16:46 -07003009 struct hostapd_hw_modes *mode;
3010 int count, i;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003011 int start, end;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003012
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003013 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08003014 HOSTAPD_MODE_IEEE80211G, false);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003015 if (mode == NULL) {
3016 /* No channels supported in this band - use empty list */
3017 params->freqs = os_zalloc(sizeof(int));
3018 return;
3019 }
3020
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003021 if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
3022 wpa_s->current_bss) {
3023 const u8 *ie;
3024
3025 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
3026 if (ie && ie[1] >= 2) {
3027 u8 o;
3028
3029 o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
3030 if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
3031 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
3032 else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
3033 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
3034 }
3035 }
3036
3037 start = wpa_s->assoc_freq - 10;
3038 end = wpa_s->assoc_freq + 10;
3039 switch (wpa_s->sme.ht_sec_chan) {
3040 case HT_SEC_CHAN_UNKNOWN:
3041 /* HT40+ possible on channels 1..9 */
3042 if (wpa_s->assoc_freq <= 2452)
3043 start -= 20;
3044 /* HT40- possible on channels 5-13 */
3045 if (wpa_s->assoc_freq >= 2432)
3046 end += 20;
3047 break;
3048 case HT_SEC_CHAN_ABOVE:
3049 end += 20;
3050 break;
3051 case HT_SEC_CHAN_BELOW:
3052 start -= 20;
3053 break;
3054 }
3055 wpa_printf(MSG_DEBUG,
3056 "OBSS: assoc_freq %d possible affected range %d-%d",
3057 wpa_s->assoc_freq, start, end);
3058
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003059 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
Dmitry Shmidt04949592012-07-19 12:16:46 -07003060 if (params->freqs == NULL)
3061 return;
3062 for (count = 0, i = 0; i < mode->num_channels; i++) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003063 int freq;
3064
Dmitry Shmidt04949592012-07-19 12:16:46 -07003065 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
3066 continue;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003067 freq = mode->channels[i].freq;
3068 if (freq - 10 >= end || freq + 10 <= start)
3069 continue; /* not affected */
3070 params->freqs[count++] = freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003071 }
3072}
3073
3074
3075static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
3076{
3077 struct wpa_supplicant *wpa_s = eloop_ctx;
3078 struct wpa_driver_scan_params params;
3079
3080 if (!wpa_s->current_bss) {
3081 wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
3082 return;
3083 }
3084
3085 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003086 wpa_obss_scan_freqs_list(wpa_s, &params);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07003087 params.low_priority = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003088 wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
3089
3090 if (wpa_supplicant_trigger_scan(wpa_s, &params))
3091 wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
3092 else
3093 wpa_s->sme.sched_obss_scan = 1;
3094 os_free(params.freqs);
3095
3096 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3097 sme_obss_scan_timeout, wpa_s, NULL);
3098}
3099
3100
3101void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
3102{
3103 const u8 *ie;
3104 struct wpa_bss *bss = wpa_s->current_bss;
3105 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003106 struct hostapd_hw_modes *hw_mode = NULL;
3107 int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003108
3109 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
3110 wpa_s->sme.sched_obss_scan = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003111 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003112 if (!enable)
3113 return;
3114
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003115 /*
3116 * Schedule OBSS scan if driver is using station SME in wpa_supplicant
3117 * or it expects OBSS scan to be performed by wpa_supplicant.
3118 */
3119 if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
3120 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
Hai Shalom81f62d82019-07-22 12:10:00 -07003121 ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003122 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003123
Hai Shaloma20dcd72022-02-04 13:43:00 -08003124#ifdef CONFIG_HT_OVERRIDES
3125 /* No need for OBSS scan if HT40 is explicitly disabled */
3126 if (ssid->disable_ht40)
3127 return;
3128#endif /* CONFIG_HT_OVERRIDES */
3129
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003130 if (!wpa_s->hw.modes)
3131 return;
3132
3133 /* only HT caps in 11g mode are relevant */
3134 for (i = 0; i < wpa_s->hw.num_modes; i++) {
3135 hw_mode = &wpa_s->hw.modes[i];
3136 if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
3137 break;
3138 }
3139
3140 /* Driver does not support HT40 for 11g or doesn't have 11g. */
3141 if (i == wpa_s->hw.num_modes || !hw_mode ||
3142 !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3143 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07003144
3145 if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
3146 return; /* Not associated on 2.4 GHz band */
3147
3148 /* Check whether AP supports HT40 */
3149 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
3150 if (!ie || ie[1] < 2 ||
3151 !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3152 return; /* AP does not support HT40 */
3153
3154 ie = wpa_bss_get_ie(wpa_s->current_bss,
3155 WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
3156 if (!ie || ie[1] < 14)
3157 return; /* AP does not request OBSS scans */
3158
3159 wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
3160 if (wpa_s->sme.obss_scan_int < 10) {
3161 wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
3162 "replaced with the minimum 10 sec",
3163 wpa_s->sme.obss_scan_int);
3164 wpa_s->sme.obss_scan_int = 10;
3165 }
3166 wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
3167 wpa_s->sme.obss_scan_int);
3168 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3169 sme_obss_scan_timeout, wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003170}
3171
3172
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003173static const unsigned int sa_query_max_timeout = 1000;
3174static const unsigned int sa_query_retry_timeout = 201;
Hai Shalom74f70d42019-02-11 14:42:39 -08003175static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003176
3177static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
3178{
3179 u32 tu;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003180 struct os_reltime now, passed;
3181 os_get_reltime(&now);
3182 os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003183 tu = (passed.sec * 1000000 + passed.usec) / 1024;
3184 if (sa_query_max_timeout < tu) {
3185 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
3186 sme_stop_sa_query(wpa_s);
3187 wpa_supplicant_deauthenticate(
3188 wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
3189 return 1;
3190 }
3191
3192 return 0;
3193}
3194
3195
3196static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
3197 const u8 *trans_id)
3198{
Hai Shalom74f70d42019-02-11 14:42:39 -08003199 u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3200 u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3201
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003202 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
3203 MACSTR, MAC2STR(wpa_s->bssid));
3204 wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
3205 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
3206 req[0] = WLAN_ACTION_SA_QUERY;
3207 req[1] = WLAN_SA_QUERY_REQUEST;
3208 os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08003209
3210#ifdef CONFIG_OCV
3211 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3212 struct wpa_channel_info ci;
3213
3214 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3215 wpa_printf(MSG_WARNING,
3216 "Failed to get channel info for OCI element in SA Query Request frame");
3217 return;
3218 }
3219
Hai Shalom899fcc72020-10-19 14:38:18 -07003220#ifdef CONFIG_TESTING_OPTIONS
3221 if (wpa_s->oci_freq_override_saquery_req) {
3222 wpa_printf(MSG_INFO,
3223 "TEST: Override SA Query Request OCI frequency %d -> %d MHz",
3224 ci.frequency,
3225 wpa_s->oci_freq_override_saquery_req);
3226 ci.frequency = wpa_s->oci_freq_override_saquery_req;
3227 }
3228#endif /* CONFIG_TESTING_OPTIONS */
3229
Hai Shalom74f70d42019-02-11 14:42:39 -08003230 if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
3231 return;
3232
3233 req_len += OCV_OCI_EXTENDED_LEN;
3234 }
3235#endif /* CONFIG_OCV */
3236
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003237 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3238 wpa_s->own_addr, wpa_s->bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08003239 req, req_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003240 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
3241 "Request");
3242}
3243
3244
3245static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
3246{
3247 struct wpa_supplicant *wpa_s = eloop_ctx;
3248 unsigned int timeout, sec, usec;
3249 u8 *trans_id, *nbuf;
3250
3251 if (wpa_s->sme.sa_query_count > 0 &&
3252 sme_check_sa_query_timeout(wpa_s))
3253 return;
3254
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003255 nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
3256 wpa_s->sme.sa_query_count + 1,
3257 WLAN_SA_QUERY_TR_ID_LEN);
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003258 if (nbuf == NULL) {
3259 sme_stop_sa_query(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003260 return;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003261 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003262 if (wpa_s->sme.sa_query_count == 0) {
3263 /* Starting a new SA Query procedure */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003264 os_get_reltime(&wpa_s->sme.sa_query_start);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003265 }
3266 trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
3267 wpa_s->sme.sa_query_trans_id = nbuf;
3268 wpa_s->sme.sa_query_count++;
3269
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003270 if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
3271 wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07003272 sme_stop_sa_query(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003273 return;
3274 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003275
3276 timeout = sa_query_retry_timeout;
3277 sec = ((timeout / 1000) * 1024) / 1000;
3278 usec = (timeout % 1000) * 1024;
3279 eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
3280
3281 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
3282 wpa_s->sme.sa_query_count);
3283
3284 sme_send_sa_query_req(wpa_s, trans_id);
3285}
3286
3287
3288static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
3289{
3290 sme_sa_query_timer(wpa_s, NULL);
3291}
3292
3293
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003294static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003295{
Hai Shalom5f92bc92019-04-18 11:54:11 -07003296 if (wpa_s->sme.sa_query_trans_id)
3297 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003298 eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
3299 os_free(wpa_s->sme.sa_query_trans_id);
3300 wpa_s->sme.sa_query_trans_id = NULL;
3301 wpa_s->sme.sa_query_count = 0;
3302}
3303
3304
3305void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
3306 const u8 *da, u16 reason_code)
3307{
3308 struct wpa_ssid *ssid;
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003309 struct os_reltime now;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003310
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311 if (wpa_s->wpa_state != WPA_COMPLETED)
3312 return;
3313 ssid = wpa_s->current_ssid;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08003314 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003315 return;
3316 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
3317 return;
3318 if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
3319 reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
3320 return;
3321 if (wpa_s->sme.sa_query_count > 0)
3322 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07003323#ifdef CONFIG_TESTING_OPTIONS
3324 if (wpa_s->disable_sa_query)
3325 return;
3326#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07003328 os_get_reltime(&now);
3329 if (wpa_s->sme.last_unprot_disconnect.sec &&
3330 !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
3331 return; /* limit SA Query procedure frequency */
3332 wpa_s->sme.last_unprot_disconnect = now;
3333
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003334 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
3335 "possible AP/STA state mismatch - trigger SA Query");
3336 sme_start_sa_query(wpa_s);
3337}
3338
3339
Hai Shalom74f70d42019-02-11 14:42:39 -08003340void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
3341{
3342 unsigned int usec;
3343 u32 _rand;
3344
3345 if (wpa_s->wpa_state != WPA_COMPLETED ||
3346 !wpa_sm_ocv_enabled(wpa_s->wpa))
3347 return;
3348
3349 wpa_dbg(wpa_s, MSG_DEBUG,
3350 "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
3351 sme_stop_sa_query(wpa_s);
3352
3353 if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
3354 _rand = os_random();
3355 usec = _rand % (sa_query_ch_switch_max_delay + 1);
3356 eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
3357}
3358
3359
3360static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
3361 const u8 *sa, const u8 *data,
3362 size_t len)
3363{
3364 u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3365 u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3366
3367 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
3368 MACSTR, MAC2STR(wpa_s->bssid));
3369
3370 resp[0] = WLAN_ACTION_SA_QUERY;
3371 resp[1] = WLAN_SA_QUERY_RESPONSE;
3372 os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
3373
3374#ifdef CONFIG_OCV
3375 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3376 struct wpa_channel_info ci;
3377
3378 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3379 wpa_printf(MSG_WARNING,
3380 "Failed to get channel info for OCI element in SA Query Response frame");
3381 return;
3382 }
3383
Hai Shalom899fcc72020-10-19 14:38:18 -07003384#ifdef CONFIG_TESTING_OPTIONS
3385 if (wpa_s->oci_freq_override_saquery_resp) {
3386 wpa_printf(MSG_INFO,
3387 "TEST: Override SA Query Response OCI frequency %d -> %d MHz",
3388 ci.frequency,
3389 wpa_s->oci_freq_override_saquery_resp);
3390 ci.frequency = wpa_s->oci_freq_override_saquery_resp;
3391 }
3392#endif /* CONFIG_TESTING_OPTIONS */
3393
Hai Shalom74f70d42019-02-11 14:42:39 -08003394 if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
3395 return;
3396
3397 resp_len += OCV_OCI_EXTENDED_LEN;
3398 }
3399#endif /* CONFIG_OCV */
3400
3401 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3402 wpa_s->own_addr, wpa_s->bssid,
3403 resp, resp_len, 0) < 0)
3404 wpa_msg(wpa_s, MSG_INFO,
3405 "SME: Failed to send SA Query Response");
3406}
3407
3408
3409static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
3410 const u8 *sa, const u8 *data,
3411 size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003412{
3413 int i;
3414
Hai Shalom74f70d42019-02-11 14:42:39 -08003415 if (!wpa_s->sme.sa_query_trans_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003416 return;
Hai Shalom74f70d42019-02-11 14:42:39 -08003417
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003418 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
3419 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3420
3421 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
3422 return;
3423
3424 for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
3425 if (os_memcmp(wpa_s->sme.sa_query_trans_id +
3426 i * WLAN_SA_QUERY_TR_ID_LEN,
3427 data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
3428 break;
3429 }
3430
3431 if (i >= wpa_s->sme.sa_query_count) {
3432 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
3433 "transaction identifier found");
3434 return;
3435 }
3436
3437 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
3438 "from " MACSTR, MAC2STR(sa));
3439 sme_stop_sa_query(wpa_s);
3440}
3441
Hai Shalom74f70d42019-02-11 14:42:39 -08003442
Hai Shaloma20dcd72022-02-04 13:43:00 -08003443void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
Hai Shalom74f70d42019-02-11 14:42:39 -08003444 const u8 *data, size_t len)
3445{
3446 if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
3447 return;
Hai Shaloma20dcd72022-02-04 13:43:00 -08003448 if (is_multicast_ether_addr(da)) {
3449 wpa_printf(MSG_DEBUG,
3450 "IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
3451 MAC2STR(da), MAC2STR(sa));
3452 return;
3453 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003454
3455 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
3456 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3457
3458#ifdef CONFIG_OCV
3459 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3460 struct ieee802_11_elems elems;
3461 struct wpa_channel_info ci;
3462
3463 if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
3464 len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
3465 &elems, 1) == ParseFailed) {
3466 wpa_printf(MSG_DEBUG,
3467 "SA Query: Failed to parse elements");
3468 return;
3469 }
3470
3471 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3472 wpa_printf(MSG_WARNING,
3473 "Failed to get channel info to validate received OCI in SA Query Action frame");
3474 return;
3475 }
3476
3477 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
3478 channel_width_to_int(ci.chanwidth),
Hai Shalom899fcc72020-10-19 14:38:18 -07003479 ci.seg1_idx) != OCI_SUCCESS) {
3480 wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR
3481 " frame=saquery%s error=%s",
3482 MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ?
3483 "req" : "resp", ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08003484 return;
3485 }
3486 }
3487#endif /* CONFIG_OCV */
3488
3489 if (data[0] == WLAN_SA_QUERY_REQUEST)
3490 sme_process_sa_query_request(wpa_s, sa, data, len);
3491 else if (data[0] == WLAN_SA_QUERY_RESPONSE)
3492 sme_process_sa_query_response(wpa_s, sa, data, len);
3493}