]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/sme.c
tests: sigma_dut controlled SAE H2E misbehavior with rejected groups
[thirdparty/hostap.git] / wpa_supplicant / sme.c
CommitLineData
c2a04078
JM
1/*
2 * wpa_supplicant - SME
6ac4b15e 3 * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
c2a04078 4 *
0f3d578e
JM
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
c2a04078
JM
7 */
8
9#include "includes.h"
10
11#include "common.h"
7d878ca7 12#include "utils/eloop.h"
90973fb2 13#include "common/ieee802_11_defs.h"
d9a27b04 14#include "common/ieee802_11_common.h"
f9da7505 15#include "common/ocv.h"
c2a04078 16#include "eapol_supp/eapol_supp_sm.h"
90973fb2 17#include "common/wpa_common.h"
98efcc41 18#include "common/sae.h"
10ec6a5f 19#include "common/dpp.h"
3acb5005
JM
20#include "rsn_supp/wpa.h"
21#include "rsn_supp/pmksa_cache.h"
c2a04078
JM
22#include "config.h"
23#include "wpa_supplicant_i.h"
2d5b792d 24#include "driver_i.h"
c2a04078
JM
25#include "wpas_glue.h"
26#include "wps_supplicant.h"
5f3a6aa0 27#include "p2p_supplicant.h"
8bac466b 28#include "notify.h"
6fa81a3b 29#include "bss.h"
9ba9fa07 30#include "scan.h"
c2a04078 31#include "sme.h"
cb418324 32#include "hs20_supplicant.h"
c2a04078 33
e29853bb
BG
34#define SME_AUTH_TIMEOUT 5
35#define SME_ASSOC_TIMEOUT 5
36
37static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
38static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
c3701c66 39static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
e29853bb 40static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
e29853bb
BG
41
42
c10347f2
JM
43#ifdef CONFIG_SAE
44
625f202a
JM
45static int index_within_array(const int *array, int idx)
46{
47 int i;
48 for (i = 0; i < idx; i++) {
18ca7332 49 if (array[i] <= 0)
625f202a
JM
50 return 0;
51 }
52 return 1;
53}
54
55
56static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
57{
58 int *groups = wpa_s->conf->sae_groups;
a9fe1303 59 int default_groups[] = { 19, 20, 21, 0 };
625f202a 60
18ca7332 61 if (!groups || groups[0] <= 0)
625f202a
JM
62 groups = default_groups;
63
64 /* Configuration may have changed, so validate current index */
65 if (!index_within_array(groups, wpa_s->sme.sae_group_index))
66 return -1;
67
68 for (;;) {
69 int group = groups[wpa_s->sme.sae_group_index];
04e6c4cc 70 if (group <= 0)
625f202a
JM
71 break;
72 if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
73 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
74 wpa_s->sme.sae.group);
3d1d4691 75 return 0;
625f202a
JM
76 }
77 wpa_s->sme.sae_group_index++;
78 }
79
80 return -1;
81}
82
83
8e31e955
JM
84static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
85 struct wpa_ssid *ssid,
fd830891 86 const u8 *bssid, int external,
cfe1ea5c 87 int reuse, int *ret_use_pt)
c10347f2
JM
88{
89 struct wpabuf *buf;
d136c376 90 size_t len;
a34ca59e 91 const char *password;
cfe1ea5c
JM
92 struct wpa_bss *bss;
93 int use_pt = 0;
94
95 if (ret_use_pt)
96 *ret_use_pt = 0;
c10347f2 97
a0f19e9c
JM
98#ifdef CONFIG_TESTING_OPTIONS
99 if (wpa_s->sae_commit_override) {
100 wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
101 buf = wpabuf_alloc(4 + wpabuf_len(wpa_s->sae_commit_override));
102 if (!buf)
103 return NULL;
be609c6f
JM
104 if (!external) {
105 wpabuf_put_le16(buf, 1); /* Transaction seq# */
106 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
107 }
a0f19e9c
JM
108 wpabuf_put_buf(buf, wpa_s->sae_commit_override);
109 return buf;
110 }
111#endif /* CONFIG_TESTING_OPTIONS */
112
a34ca59e
JM
113 password = ssid->sae_password;
114 if (!password)
115 password = ssid->passphrase;
116 if (!password) {
8e31e955
JM
117 wpa_printf(MSG_DEBUG, "SAE: No password available");
118 return NULL;
119 }
120
fd830891
JM
121 if (reuse && wpa_s->sme.sae.tmp &&
122 os_memcmp(bssid, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) {
123 wpa_printf(MSG_DEBUG,
124 "SAE: Reuse previously generated PWE on a retry with the same AP");
cfe1ea5c 125 use_pt = wpa_s->sme.sae.tmp->h2e;
fd830891
JM
126 goto reuse_data;
127 }
625f202a
JM
128 if (sme_set_sae_group(wpa_s) < 0) {
129 wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
a46d72d7 130 return NULL;
625f202a 131 }
a46d72d7 132
cfe1ea5c
JM
133 if (wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) {
134 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
135 if (bss) {
136 const u8 *rsnxe;
137
138 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
139 if (rsnxe && rsnxe[1] >= 1)
140 use_pt = !!(rsnxe[2] &
141 BIT(WLAN_RSNX_CAPAB_SAE_H2E));
142 }
143
144 if (wpa_s->conf->sae_pwe == 1 && !use_pt) {
145 wpa_printf(MSG_DEBUG,
146 "SAE: Cannot use H2E with the selected AP");
147 return NULL;
148 }
149 }
150
151 if (use_pt &&
152 sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt,
153 wpa_s->own_addr, bssid,
154 wpa_s->sme.sae_rejected_groups) < 0)
155 return NULL;
156 if (!use_pt &&
157 sae_prepare_commit(wpa_s->own_addr, bssid,
a34ca59e 158 (u8 *) password, os_strlen(password),
9be19d0b 159 ssid->sae_password_id,
8e31e955
JM
160 &wpa_s->sme.sae) < 0) {
161 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
162 return NULL;
163 }
fd830891
JM
164 if (wpa_s->sme.sae.tmp)
165 os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN);
8e31e955 166
fd830891 167reuse_data:
d136c376 168 len = wpa_s->sme.sae_token ? wpabuf_len(wpa_s->sme.sae_token) : 0;
9be19d0b
JM
169 if (ssid->sae_password_id)
170 len += 4 + os_strlen(ssid->sae_password_id);
d136c376 171 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
c10347f2
JM
172 if (buf == NULL)
173 return NULL;
5ff39c13
SD
174 if (!external) {
175 wpabuf_put_le16(buf, 1); /* Transaction seq# */
cfe1ea5c
JM
176 wpabuf_put_le16(buf, use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
177 WLAN_STATUS_SUCCESS);
5ff39c13 178 }
9be19d0b
JM
179 sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
180 ssid->sae_password_id);
cfe1ea5c
JM
181 if (ret_use_pt)
182 *ret_use_pt = use_pt;
c10347f2
JM
183
184 return buf;
185}
186
187
5ff39c13
SD
188static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s,
189 int external)
c10347f2
JM
190{
191 struct wpabuf *buf;
192
fb8fcc29 193 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN);
c10347f2
JM
194 if (buf == NULL)
195 return NULL;
196
5ff39c13
SD
197 if (!external) {
198 wpabuf_put_le16(buf, 2); /* Transaction seq# */
199 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
200 }
fb8fcc29 201 sae_write_confirm(&wpa_s->sme.sae, buf);
c10347f2
JM
202
203 return buf;
204}
205
206#endif /* CONFIG_SAE */
207
208
b361d580
AK
209/**
210 * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt
211 * @wpa_s: Pointer to wpa_supplicant data
212 * @bss: Pointer to the bss which is the target of authentication attempt
213 */
214static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
215 struct wpa_bss *bss)
216{
217 const u8 rrm_ie_len = 5;
218 u8 *pos;
219 const u8 *rrm_ie;
220
221 wpa_s->rrm.rrm_used = 0;
222
223 wpa_printf(MSG_DEBUG,
224 "RRM: Determining whether RRM can be used - device support: 0x%x",
225 wpa_s->drv_rrm_flags);
226
227 rrm_ie = wpa_bss_get_ie(bss, WLAN_EID_RRM_ENABLED_CAPABILITIES);
228 if (!rrm_ie || !(bss->caps & IEEE80211_CAP_RRM)) {
229 wpa_printf(MSG_DEBUG, "RRM: No RRM in network");
230 return;
231 }
232
00ed0aa2
BL
233 if (!((wpa_s->drv_rrm_flags &
234 WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
235 (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
236 !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) {
b361d580
AK
237 wpa_printf(MSG_DEBUG,
238 "RRM: Insufficient RRM support in driver - do not use RRM");
239 return;
240 }
241
849367af
JM
242 if (sizeof(wpa_s->sme.assoc_req_ie) <
243 wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) {
b361d580
AK
244 wpa_printf(MSG_INFO,
245 "RRM: Unable to use RRM, no room for RRM IE");
246 return;
247 }
248
249 wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to Association Request");
250 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
b361d580
AK
251 os_memset(pos, 0, 2 + rrm_ie_len);
252 *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
253 *pos++ = rrm_ie_len;
70d1e728
AO
254
255 /* Set supported capabilites flags */
256 if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
257 *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
258
d7342014
JM
259 *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
260 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
261 WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
76196ddb 262
4a742011
DS
263 if (wpa_s->lci)
264 pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
265
b361d580
AK
266 wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
267 wpa_s->rrm.rrm_used = 1;
268}
269
270
215ae884
JM
271static void sme_send_authentication(struct wpa_supplicant *wpa_s,
272 struct wpa_bss *bss, struct wpa_ssid *ssid,
273 int start)
c2a04078
JM
274{
275 struct wpa_driver_auth_params params;
8bac466b 276 struct wpa_ssid *old_ssid;
fdbe50ed 277#ifdef CONFIG_IEEE80211R
c2a04078 278 const u8 *ie;
fdbe50ed 279#endif /* CONFIG_IEEE80211R */
af3e362f 280#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
c2a04078 281 const u8 *md = NULL;
af3e362f 282#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
8bac466b 283 int i, bssid_changed;
c10347f2 284 struct wpabuf *resp = NULL;
0bbaa9b9 285 u8 ext_capab[18];
03e47c9c 286 int ext_capab_len;
59b416c7 287 int skip_auth;
170244a1
IP
288 u8 *wpa_ie;
289 size_t wpa_ie_len;
077232f6
BL
290#ifdef CONFIG_MBO
291 const u8 *mbo_ie;
292#endif /* CONFIG_MBO */
c2a04078
JM
293
294 if (bss == NULL) {
f049052b
BG
295 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
296 "the network");
6ac4b15e 297 wpas_connect_work_done(wpa_s);
c2a04078
JM
298 return;
299 }
300
59b416c7
JM
301 skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
302 wpa_s->reassoc_same_bss;
8f770587
JM
303 wpa_s->current_bss = bss;
304
c2a04078
JM
305 os_memset(&params, 0, sizeof(params));
306 wpa_s->reassociate = 0;
307
308 params.freq = bss->freq;
309 params.bssid = bss->bssid;
6fa81a3b
JM
310 params.ssid = bss->ssid;
311 params.ssid_len = bss->ssid_len;
2f4f73b1 312 params.p2p = ssid->p2p_group;
c2a04078 313
62fa124c
JM
314 if (wpa_s->sme.ssid_len != params.ssid_len ||
315 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
316 wpa_s->sme.prev_bssid_set = 0;
317
c2a04078
JM
318 wpa_s->sme.freq = params.freq;
319 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
320 wpa_s->sme.ssid_len = params.ssid_len;
321
abd9fafa 322 params.auth_alg = WPA_AUTH_ALG_OPEN;
c2a04078
JM
323#ifdef IEEE8021X_EAPOL
324 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
325 if (ssid->leap) {
326 if (ssid->non_leap == 0)
abd9fafa 327 params.auth_alg = WPA_AUTH_ALG_LEAP;
c2a04078 328 else
abd9fafa 329 params.auth_alg |= WPA_AUTH_ALG_LEAP;
c2a04078
JM
330 }
331 }
332#endif /* IEEE8021X_EAPOL */
f049052b
BG
333 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
334 params.auth_alg);
c2a04078 335 if (ssid->auth_alg) {
abd9fafa 336 params.auth_alg = ssid->auth_alg;
f049052b
BG
337 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
338 "0x%x", params.auth_alg);
c2a04078 339 }
c10347f2 340#ifdef CONFIG_SAE
bc26ac50 341 wpa_s->sme.sae_pmksa_caching = 0;
c10347f2
JM
342 if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
343 const u8 *rsn;
344 struct wpa_ie_data ied;
345
346 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
267ac3bc
JM
347 if (!rsn) {
348 wpa_dbg(wpa_s, MSG_DEBUG,
349 "SAE enabled, but target BSS does not advertise RSN");
dd6c5980
JM
350#ifdef CONFIG_DPP
351 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
352 (ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
353 (ied.key_mgmt & WPA_KEY_MGMT_DPP)) {
354 wpa_dbg(wpa_s, MSG_DEBUG, "Prefer DPP over SAE when both are enabled");
355#endif /* CONFIG_DPP */
267ac3bc
JM
356 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
357 wpa_key_mgmt_sae(ied.key_mgmt)) {
358 wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
359 params.auth_alg = WPA_AUTH_ALG_SAE;
360 } else {
361 wpa_dbg(wpa_s, MSG_DEBUG,
362 "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
c10347f2
JM
363 }
364 }
365#endif /* CONFIG_SAE */
c2a04078 366
a0b2f99b
JM
367 for (i = 0; i < NUM_WEP_KEYS; i++) {
368 if (ssid->wep_key_len[i])
369 params.wep_key[i] = ssid->wep_key[i];
370 params.wep_key_len[i] = ssid->wep_key_len[i];
371 }
372 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
373
8bac466b 374 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
c2a04078
JM
375 os_memset(wpa_s->bssid, 0, ETH_ALEN);
376 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
8bac466b
JM
377 if (bssid_changed)
378 wpas_notify_bssid_changed(wpa_s);
c2a04078 379
f337f0e9
JM
380 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
381 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
0bf927a0 382 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
c2a04078 383 int try_opportunistic;
869af307
JM
384 const u8 *cache_id = NULL;
385
6e202021
JM
386 try_opportunistic = (ssid->proactive_key_caching < 0 ?
387 wpa_s->conf->okc :
388 ssid->proactive_key_caching) &&
c2a04078 389 (ssid->proto & WPA_PROTO_RSN);
869af307
JM
390#ifdef CONFIG_FILS
391 if (wpa_key_mgmt_fils(ssid->key_mgmt))
392 cache_id = wpa_bss_get_fils_cache_id(bss);
393#endif /* CONFIG_FILS */
c2a04078
JM
394 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
395 wpa_s->current_ssid,
852b2f27
JM
396 try_opportunistic, cache_id,
397 0) == 0)
ba422613 398 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
c2a04078
JM
399 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
400 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
401 wpa_s->sme.assoc_req_ie,
402 &wpa_s->sme.assoc_req_ie_len)) {
f049052b
BG
403 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
404 "key management and encryption suites");
6ac4b15e 405 wpas_connect_work_done(wpa_s);
c2a04078
JM
406 return;
407 }
dc673aec
JM
408#ifdef CONFIG_HS20
409 } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
410 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
411 /* No PMKSA caching, but otherwise similar to RSN/WPA */
412 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
413 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
414 wpa_s->sme.assoc_req_ie,
415 &wpa_s->sme.assoc_req_ie_len)) {
416 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
417 "key management and encryption suites");
418 wpas_connect_work_done(wpa_s);
419 return;
420 }
421#endif /* CONFIG_HS20 */
a3f7e518
JM
422 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
423 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
424 /*
425 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
426 * use non-WPA since the scan results did not indicate that the
427 * AP is using WPA or WPA2.
428 */
429 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
430 wpa_s->sme.assoc_req_ie_len = 0;
0bf927a0 431 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
c2a04078
JM
432 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
433 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
434 wpa_s->sme.assoc_req_ie,
435 &wpa_s->sme.assoc_req_ie_len)) {
f049052b
BG
436 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
437 "key management and encryption suites (no "
438 "scan results)");
6ac4b15e 439 wpas_connect_work_done(wpa_s);
c2a04078
JM
440 return;
441 }
442#ifdef CONFIG_WPS
443 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
444 struct wpabuf *wps_ie;
445 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
446 if (wps_ie && wpabuf_len(wps_ie) <=
447 sizeof(wpa_s->sme.assoc_req_ie)) {
448 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
449 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
450 wpa_s->sme.assoc_req_ie_len);
451 } else
452 wpa_s->sme.assoc_req_ie_len = 0;
453 wpabuf_free(wps_ie);
454 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
455#endif /* CONFIG_WPS */
456 } else {
457 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
458 wpa_s->sme.assoc_req_ie_len = 0;
459 }
460
170244a1
IP
461 /* In case the WPA vendor IE is used, it should be placed after all the
462 * non-vendor IEs, as the lower layer expects the IEs to be ordered as
463 * defined in the standard. Store the WPA IE so it can later be
464 * inserted at the correct location.
465 */
466 wpa_ie = NULL;
467 wpa_ie_len = 0;
468 if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
469 wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
470 wpa_s->sme.assoc_req_ie_len);
471 if (wpa_ie) {
472 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
473
474 wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
475 wpa_s->sme.assoc_req_ie_len = 0;
476 } else {
477 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
478 wpas_connect_work_done(wpa_s);
479 return;
480 }
481 }
482
c2a04078 483#ifdef CONFIG_IEEE80211R
6fa81a3b 484 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
c2a04078
JM
485 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
486 md = ie + 2;
e7846b68 487 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
322d328e
JM
488 if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
489 !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
490 md = NULL;
c2a04078
JM
491 if (md) {
492 /* Prepare for the next transition */
76b7981d 493 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
c2a04078
JM
494 }
495
af3e362f
JM
496 if (md) {
497 wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
498 md[0], md[1]);
499
c2a04078
JM
500 if (wpa_s->sme.assoc_req_ie_len + 5 <
501 sizeof(wpa_s->sme.assoc_req_ie)) {
502 struct rsn_mdie *mdie;
503 u8 *pos = wpa_s->sme.assoc_req_ie +
504 wpa_s->sme.assoc_req_ie_len;
505 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
506 *pos++ = sizeof(*mdie);
507 mdie = (struct rsn_mdie *) pos;
508 os_memcpy(mdie->mobility_domain, md,
509 MOBILITY_DOMAIN_ID_LEN);
f4ec630d 510 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
c2a04078
JM
511 wpa_s->sme.assoc_req_ie_len += 5;
512 }
513
f808bd59 514 if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
0d7b4409
JM
515 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
516 wpa_sm_has_ptk(wpa_s->wpa)) {
f049052b
BG
517 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
518 "over-the-air");
abd9fafa 519 params.auth_alg = WPA_AUTH_ALG_FT;
c2a04078
JM
520 params.ie = wpa_s->sme.ft_ies;
521 params.ie_len = wpa_s->sme.ft_ies_len;
522 }
523 }
524#endif /* CONFIG_IEEE80211R */
525
3f56a2b7 526 wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
62d49803 527 if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
6fa81a3b 528 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
c2a04078
JM
529 struct wpa_ie_data _ie;
530 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
531 _ie.capabilities &
532 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
f049052b
BG
533 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
534 "MFP: require MFP");
c2a04078
JM
535 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
536 }
537 }
c2a04078 538
5f3a6aa0
JM
539#ifdef CONFIG_P2P
540 if (wpa_s->global->p2p) {
541 u8 *pos;
542 size_t len;
543 int res;
5f3a6aa0
JM
544 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
545 len = sizeof(wpa_s->sme.assoc_req_ie) -
546 wpa_s->sme.assoc_req_ie_len;
ffad8858
JM
547 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
548 ssid->p2p_group);
5f3a6aa0
JM
549 if (res >= 0)
550 wpa_s->sme.assoc_req_ie_len += res;
551 }
552#endif /* CONFIG_P2P */
553
b36a3a65
AN
554#ifdef CONFIG_FST
555 if (wpa_s->fst_ies) {
556 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
557
558 if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <=
559 sizeof(wpa_s->sme.assoc_req_ie)) {
560 os_memcpy(wpa_s->sme.assoc_req_ie +
561 wpa_s->sme.assoc_req_ie_len,
562 wpabuf_head(wpa_s->fst_ies),
563 fst_ies_len);
564 wpa_s->sme.assoc_req_ie_len += fst_ies_len;
565 }
566 }
567#endif /* CONFIG_FST */
568
a0c38e5d
AS
569 sme_auth_handle_rrm(wpa_s, bss);
570
065c029a 571 wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
cb828507 572 wpa_s, ssid, bss->freq,
065c029a 573 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
574 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
5e57ba25 575
cc9a2575
KV
576 if (params.p2p)
577 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
578 else
579 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
580
0bbaa9b9
JM
581 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
582 sizeof(ext_capab));
03e47c9c 583 if (ext_capab_len > 0) {
92cbcf91
JM
584 u8 *pos = wpa_s->sme.assoc_req_ie;
585 if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
586 pos += 2 + pos[1];
03e47c9c 587 os_memmove(pos + ext_capab_len, pos,
92cbcf91
JM
588 wpa_s->sme.assoc_req_ie_len -
589 (pos - wpa_s->sme.assoc_req_ie));
03e47c9c
JM
590 wpa_s->sme.assoc_req_ie_len += ext_capab_len;
591 os_memcpy(pos, ext_capab, ext_capab_len);
92cbcf91 592 }
92cbcf91 593
6d6c8877
JM
594 if (wpa_s->rsnxe_len > 0 &&
595 wpa_s->rsnxe_len <=
596 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
597 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
598 wpa_s->rsnxe, wpa_s->rsnxe_len);
599 wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
600 }
601
c484b198
AS
602#ifdef CONFIG_HS20
603 if (is_hs20_network(wpa_s, ssid, bss)) {
604 struct wpabuf *hs20;
605
4204669c 606 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
c484b198
AS
607 if (hs20) {
608 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
609 size_t len;
610
ec2cf403
JM
611 wpas_hs20_add_indication(hs20, pps_mo_id,
612 get_hs20_version(bss));
4204669c 613 wpas_hs20_add_roam_cons_sel(hs20, ssid);
c484b198
AS
614 len = sizeof(wpa_s->sme.assoc_req_ie) -
615 wpa_s->sme.assoc_req_ie_len;
616 if (wpabuf_len(hs20) <= len) {
617 os_memcpy(wpa_s->sme.assoc_req_ie +
618 wpa_s->sme.assoc_req_ie_len,
619 wpabuf_head(hs20), wpabuf_len(hs20));
620 wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
621 }
622 wpabuf_free(hs20);
623 }
624 }
625#endif /* CONFIG_HS20 */
626
170244a1
IP
627 if (wpa_ie) {
628 size_t len;
629
630 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
631
632 len = sizeof(wpa_s->sme.assoc_req_ie) -
633 wpa_s->sme.assoc_req_ie_len;
634
635 if (len > wpa_ie_len) {
636 os_memcpy(wpa_s->sme.assoc_req_ie +
637 wpa_s->sme.assoc_req_ie_len,
638 wpa_ie, wpa_ie_len);
639 wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
640 } else {
641 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
642 }
643
644 os_free(wpa_ie);
645 }
646
d29fa3a7
JM
647 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
648 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
649 size_t len;
650
651 len = sizeof(wpa_s->sme.assoc_req_ie) -
652 wpa_s->sme.assoc_req_ie_len;
653 if (wpabuf_len(buf) <= len) {
654 os_memcpy(wpa_s->sme.assoc_req_ie +
655 wpa_s->sme.assoc_req_ie_len,
656 wpabuf_head(buf), wpabuf_len(buf));
657 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
658 }
659 }
660
92c6e2e3 661#ifdef CONFIG_MBO
077232f6 662 mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
2e06cef8 663 if (!wpa_s->disable_mbo_oce && mbo_ie) {
5e57ba25 664 int len;
92c6e2e3 665
5e57ba25
AS
666 len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
667 wpa_s->sme.assoc_req_ie_len,
668 sizeof(wpa_s->sme.assoc_req_ie) -
077232f6
BL
669 wpa_s->sme.assoc_req_ie_len,
670 !!mbo_attr_from_mbo_ie(mbo_ie,
671 OCE_ATTR_ID_CAPA_IND));
5e57ba25
AS
672 if (len >= 0)
673 wpa_s->sme.assoc_req_ie_len += len;
92c6e2e3
DS
674 }
675#endif /* CONFIG_MBO */
676
c10347f2 677#ifdef CONFIG_SAE
59b416c7 678 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
869af307 679 pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0,
ab3aebcc
JM
680 NULL,
681 wpa_s->key_mgmt == WPA_KEY_MGMT_FT_SAE ?
682 WPA_KEY_MGMT_FT_SAE :
683 WPA_KEY_MGMT_SAE) == 0) {
bc26ac50
JM
684 wpa_dbg(wpa_s, MSG_DEBUG,
685 "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
06b1a104 686 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
bc26ac50
JM
687 params.auth_alg = WPA_AUTH_ALG_OPEN;
688 wpa_s->sme.sae_pmksa_caching = 1;
689 }
690
59b416c7 691 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
c10347f2 692 if (start)
8e31e955 693 resp = sme_auth_build_sae_commit(wpa_s, ssid,
fd830891 694 bss->bssid, 0,
cfe1ea5c 695 start == 2, NULL);
c10347f2 696 else
5ff39c13 697 resp = sme_auth_build_sae_confirm(wpa_s, 0);
6ac4b15e 698 if (resp == NULL) {
81648d00 699 wpas_connection_failed(wpa_s, bss->bssid);
c10347f2 700 return;
6ac4b15e 701 }
ce16c489
JM
702 params.auth_data = wpabuf_head(resp);
703 params.auth_data_len = wpabuf_len(resp);
dd43026a 704 wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
c10347f2
JM
705 }
706#endif /* CONFIG_SAE */
707
f00b9b88
JM
708 old_ssid = wpa_s->current_ssid;
709 wpa_s->current_ssid = ssid;
710 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
711 wpa_supplicant_initiate_eapol(wpa_s);
712
713#ifdef CONFIG_FILS
714 /* TODO: FILS operations can in some cases be done between different
715 * network_ctx (i.e., same credentials can be used with multiple
716 * networks). */
717 if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
718 wpa_key_mgmt_fils(ssid->key_mgmt)) {
64983516
JM
719 const u8 *indic;
720 u16 fils_info;
af835d75
AB
721 const u8 *realm, *username, *rrk;
722 size_t realm_len, username_len, rrk_len;
723 u16 next_seq_num;
64983516
JM
724
725 /*
726 * Check FILS Indication element (FILS Information field) bits
727 * indicating supported authentication algorithms against local
728 * configuration (ssid->fils_dh_group). Try to use FILS
729 * authentication only if the AP supports the combination in the
730 * network profile. */
731 indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
732 if (!indic || indic[1] < 2) {
733 wpa_printf(MSG_DEBUG, "SME: " MACSTR
734 " does not include FILS Indication element - cannot use FILS authentication with it",
735 MAC2STR(bss->bssid));
736 goto no_fils;
737 }
738
739 fils_info = WPA_GET_LE16(indic + 2);
740 if (ssid->fils_dh_group == 0 && !(fils_info & BIT(9))) {
741 wpa_printf(MSG_DEBUG, "SME: " MACSTR
742 " does not support FILS SK without PFS - cannot use FILS authentication with it",
743 MAC2STR(bss->bssid));
744 goto no_fils;
745 }
746 if (ssid->fils_dh_group != 0 && !(fils_info & BIT(10))) {
747 wpa_printf(MSG_DEBUG, "SME: " MACSTR
748 " does not support FILS SK with PFS - cannot use FILS authentication with it",
749 MAC2STR(bss->bssid));
750 goto no_fils;
751 }
752
af835d75
AB
753 if (wpa_s->last_con_fail_realm &&
754 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
755 &username, &username_len,
756 &realm, &realm_len, &next_seq_num,
757 &rrk, &rrk_len) == 0 &&
758 realm && realm_len == wpa_s->last_con_fail_realm_len &&
759 os_memcmp(realm, wpa_s->last_con_fail_realm,
760 realm_len) == 0) {
761 wpa_printf(MSG_DEBUG,
762 "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
763 goto no_fils;
764 }
765
f00b9b88 766 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
869af307 767 ssid, 0,
852b2f27
JM
768 wpa_bss_get_fils_cache_id(bss),
769 0) == 0)
f00b9b88
JM
770 wpa_printf(MSG_DEBUG,
771 "SME: Try to use FILS with PMKSA caching");
af3e362f 772 resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
f00b9b88 773 if (resp) {
76e20f4f
JM
774 int auth_alg;
775
776 if (ssid->fils_dh_group)
777 wpa_printf(MSG_DEBUG,
778 "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
779 ssid->fils_dh_group);
780 else
781 wpa_printf(MSG_DEBUG,
782 "SME: Try to use FILS SK authentication without PFS");
783 auth_alg = ssid->fils_dh_group ?
784 WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
785 params.auth_alg = auth_alg;
f00b9b88
JM
786 params.auth_data = wpabuf_head(resp);
787 params.auth_data_len = wpabuf_len(resp);
76e20f4f 788 wpa_s->sme.auth_alg = auth_alg;
f00b9b88
JM
789 }
790 }
64983516 791no_fils:
f00b9b88
JM
792#endif /* CONFIG_FILS */
793
a4cba8f1 794 wpa_supplicant_cancel_sched_scan(wpa_s);
c2a04078
JM
795 wpa_supplicant_cancel_scan(wpa_s);
796
f049052b 797 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
c2a04078
JM
798 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
799 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
800
6aea02e5 801 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
c2a04078
JM
802 wpa_clear_keys(wpa_s, bss->bssid);
803 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
8bac466b
JM
804 if (old_ssid != wpa_s->current_ssid)
805 wpas_notify_network_changed(wpa_s);
c2a04078 806
ece4ac5f
MG
807#ifdef CONFIG_HS20
808 hs20_configure_frame_filters(wpa_s);
809#endif /* CONFIG_HS20 */
810
d0df6437
IP
811#ifdef CONFIG_P2P
812 /*
813 * If multi-channel concurrency is not supported, check for any
814 * frequency conflict. In case of any frequency conflict, remove the
815 * least prioritized connection.
816 */
817 if (wpa_s->num_multichan_concurrent < 2) {
818 int freq, num;
819 num = get_shared_radio_freqs(wpa_s, &freq, 1);
820 if (num > 0 && freq > 0 && freq != params.freq) {
821 wpa_printf(MSG_DEBUG,
822 "Conflicting frequency found (%d != %d)",
823 freq, params.freq);
824 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
825 params.freq,
826 ssid) < 0) {
827 wpas_connection_failed(wpa_s, bss->bssid);
828 wpa_supplicant_mark_disassoc(wpa_s);
829 wpabuf_free(resp);
830 wpas_connect_work_done(wpa_s);
831 return;
832 }
833 }
834 }
835#endif /* CONFIG_P2P */
836
59b416c7
JM
837 if (skip_auth) {
838 wpa_msg(wpa_s, MSG_DEBUG,
839 "SME: Skip authentication step on reassoc-to-same-BSS");
840 wpabuf_free(resp);
841 sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN);
842 return;
843 }
844
845
62c72d72 846 wpa_s->sme.auth_alg = params.auth_alg;
c2a04078 847 if (wpa_drv_authenticate(wpa_s, &params) < 0) {
f049052b 848 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
c2a04078 849 "driver failed");
ed57c590 850 wpas_connection_failed(wpa_s, bss->bssid);
1193dc8f 851 wpa_supplicant_mark_disassoc(wpa_s);
c10347f2 852 wpabuf_free(resp);
6ac4b15e 853 wpas_connect_work_done(wpa_s);
c2a04078
JM
854 return;
855 }
856
e29853bb
BG
857 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
858 NULL);
c2a04078
JM
859
860 /*
861 * Association will be started based on the authentication event from
862 * the driver.
863 */
c10347f2
JM
864
865 wpabuf_free(resp);
866}
867
868
6ac4b15e
JM
869static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
870{
871 struct wpa_connect_work *cwork = work->ctx;
872 struct wpa_supplicant *wpa_s = work->wpa_s;
873
874 if (deinit) {
b3253ebb
AO
875 if (work->started)
876 wpa_s->connect_work = NULL;
877
6ac4b15e
JM
878 wpas_connect_work_free(cwork);
879 return;
880 }
881
882 wpa_s->connect_work = work;
883
a7f5271d 884 if (cwork->bss_removed ||
6108536d
HW
885 !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
886 wpas_network_disabled(wpa_s, cwork->ssid)) {
6ac4b15e
JM
887 wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
888 wpas_connect_work_done(wpa_s);
889 return;
890 }
891
2c2c5579
JM
892 /* Starting new connection, so clear the possibly used WPA IE from the
893 * previous association. */
894 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
6d6c8877
JM
895 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
896 wpa_s->rsnxe_len = 0;
2c2c5579 897
6ac4b15e
JM
898 sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
899}
900
901
c10347f2
JM
902void sme_authenticate(struct wpa_supplicant *wpa_s,
903 struct wpa_bss *bss, struct wpa_ssid *ssid)
904{
6ac4b15e
JM
905 struct wpa_connect_work *cwork;
906
907 if (bss == NULL || ssid == NULL)
908 return;
909 if (wpa_s->connect_work) {
910 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
911 return;
912 }
913
f0e30c84 914 if (radio_work_pending(wpa_s, "sme-connect")) {
f1c4dbf5
IP
915 /*
916 * The previous sme-connect work might no longer be valid due to
917 * the fact that the BSS list was updated. In addition, it makes
918 * sense to adhere to the 'newer' decision.
919 */
920 wpa_dbg(wpa_s, MSG_DEBUG,
921 "SME: Remove previous pending sme-connect");
922 radio_remove_works(wpa_s, "sme-connect", 0);
f0e30c84
JM
923 }
924
4ead7cfd
KV
925 wpas_abort_ongoing_scan(wpa_s);
926
6ac4b15e
JM
927 cwork = os_zalloc(sizeof(*cwork));
928 if (cwork == NULL)
929 return;
930 cwork->bss = bss;
931 cwork->ssid = ssid;
932 cwork->sme = 1;
933
98efcc41 934#ifdef CONFIG_SAE
dd43026a 935 wpa_s->sme.sae.state = SAE_NOTHING;
98efcc41 936 wpa_s->sme.sae.send_confirm = 0;
18ca7332 937 wpa_s->sme.sae_group_index = 0;
98efcc41 938#endif /* CONFIG_SAE */
6ac4b15e
JM
939
940 if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
941 sme_auth_start_cb, cwork) < 0)
942 wpas_connect_work_free(cwork);
c2a04078
JM
943}
944
945
c10347f2 946#ifdef CONFIG_SAE
21af6d15 947
5ff39c13
SD
948static int sme_external_auth_build_buf(struct wpabuf *buf,
949 struct wpabuf *params,
950 const u8 *sa, const u8 *da,
cfe1ea5c
JM
951 u16 auth_transaction, u16 seq_num,
952 u16 status_code)
5ff39c13
SD
953{
954 struct ieee80211_mgmt *resp;
955
956 resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
957 u.auth.variable));
958
959 resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
960 (WLAN_FC_STYPE_AUTH << 4));
961 os_memcpy(resp->da, da, ETH_ALEN);
962 os_memcpy(resp->sa, sa, ETH_ALEN);
963 os_memcpy(resp->bssid, da, ETH_ALEN);
fcb3f11e
AP
964 resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
965 resp->seq_ctrl = host_to_le16(seq_num << 4);
966 resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
cfe1ea5c 967 resp->u.auth.status_code = host_to_le16(status_code);
5ff39c13
SD
968 if (params)
969 wpabuf_put_buf(buf, params);
970
971 return 0;
972}
973
974
fb6ebd1c
SD
975static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
976 const u8 *bssid,
977 struct wpa_ssid *ssid)
5ff39c13
SD
978{
979 struct wpabuf *resp, *buf;
cfe1ea5c 980 int use_pt;
5ff39c13 981
cfe1ea5c 982 resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt);
fb6ebd1c
SD
983 if (!resp) {
984 wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
985 return -1;
986 }
5ff39c13
SD
987
988 wpa_s->sme.sae.state = SAE_COMMITTED;
989 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp));
990 if (!buf) {
991 wpabuf_free(resp);
fb6ebd1c 992 return -1;
5ff39c13
SD
993 }
994
995 wpa_s->sme.seq_num++;
996 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
cfe1ea5c
JM
997 bssid, 1, wpa_s->sme.seq_num,
998 use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
999 WLAN_STATUS_SUCCESS);
5ff39c13
SD
1000 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0);
1001 wpabuf_free(resp);
1002 wpabuf_free(buf);
fb6ebd1c
SD
1003
1004 return 0;
5ff39c13
SD
1005}
1006
1007
1008static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
1009 u16 status)
1010{
1011 struct external_auth params;
1012
1013 os_memset(&params, 0, sizeof(params));
1014 params.status = status;
d42df8d6
JM
1015 params.ssid = wpa_s->sme.ext_auth_ssid;
1016 params.ssid_len = wpa_s->sme.ext_auth_ssid_len;
1017 params.bssid = wpa_s->sme.ext_auth_bssid;
346d10cf
SD
1018 if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
1019 params.pmkid = wpa_s->sme.sae.pmkid;
5ff39c13
SD
1020 wpa_drv_send_external_auth_status(wpa_s, &params);
1021}
1022
1023
fb6ebd1c
SD
1024static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
1025 union wpa_event_data *data)
5ff39c13
SD
1026{
1027 struct wpa_ssid *ssid;
1028 size_t ssid_str_len = data->external_auth.ssid_len;
dd1a8cef 1029 const u8 *ssid_str = data->external_auth.ssid;
5ff39c13
SD
1030
1031 /* Get the SSID conf from the ssid string obtained */
1032 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1033 if (!wpas_network_disabled(wpa_s, ssid) &&
1034 ssid_str_len == ssid->ssid_len &&
18a0508a 1035 os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
bcf19000 1036 (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)))
5ff39c13
SD
1037 break;
1038 }
fb6ebd1c
SD
1039 if (!ssid ||
1040 sme_external_auth_send_sae_commit(wpa_s, data->external_auth.bssid,
1041 ssid) < 0)
1042 return -1;
1043
1044 return 0;
5ff39c13
SD
1045}
1046
1047
1048static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
1049 const u8 *da)
1050{
1051 struct wpabuf *resp, *buf;
1052
1053 resp = sme_auth_build_sae_confirm(wpa_s, 1);
1054 if (!resp) {
1055 wpa_printf(MSG_DEBUG, "SAE: Confirm message buf alloc failure");
1056 return;
1057 }
1058
1059 wpa_s->sme.sae.state = SAE_CONFIRMED;
1060 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp));
1061 if (!buf) {
1062 wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure");
1063 wpabuf_free(resp);
1064 return;
1065 }
1066 wpa_s->sme.seq_num++;
1067 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
cfe1ea5c
JM
1068 da, 2, wpa_s->sme.seq_num,
1069 WLAN_STATUS_SUCCESS);
5ff39c13
SD
1070 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0);
1071 wpabuf_free(resp);
1072 wpabuf_free(buf);
1073}
1074
1075
1076void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
1077 union wpa_event_data *data)
1078{
1079 if (RSN_SELECTOR_GET(&data->external_auth.key_mgmt_suite) !=
1080 RSN_AUTH_KEY_MGMT_SAE)
1081 return;
1082
1083 if (data->external_auth.action == EXT_AUTH_START) {
d42df8d6
JM
1084 if (!data->external_auth.bssid || !data->external_auth.ssid)
1085 return;
1086 os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid,
1087 ETH_ALEN);
1088 os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid,
1089 data->external_auth.ssid_len);
1090 wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len;
5ff39c13
SD
1091 wpa_s->sme.seq_num = 0;
1092 wpa_s->sme.sae.state = SAE_NOTHING;
1093 wpa_s->sme.sae.send_confirm = 0;
1094 wpa_s->sme.sae_group_index = 0;
fb6ebd1c
SD
1095 if (sme_handle_external_auth_start(wpa_s, data) < 0)
1096 sme_send_external_auth_status(wpa_s,
1097 WLAN_STATUS_UNSPECIFIED_FAILURE);
5ff39c13
SD
1098 } else if (data->external_auth.action == EXT_AUTH_ABORT) {
1099 /* Report failure to driver for the wrong trigger */
1100 sme_send_external_auth_status(wpa_s,
1101 WLAN_STATUS_UNSPECIFIED_FAILURE);
1102 }
1103}
1104
1105
444d76f7
JM
1106static int sme_sae_is_group_enabled(struct wpa_supplicant *wpa_s, int group)
1107{
1108 int *groups = wpa_s->conf->sae_groups;
1109 int default_groups[] = { 19, 20, 21, 0 };
1110 int i;
1111
1112 if (!groups)
1113 groups = default_groups;
1114
1115 for (i = 0; groups[i] > 0; i++) {
1116 if (groups[i] == group)
1117 return 1;
1118 }
1119
1120 return 0;
1121}
1122
1123
1124static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
1125 const struct wpabuf *groups)
1126{
1127 size_t i, count;
1128 const u8 *pos;
1129
1130 if (!groups)
1131 return 0;
1132
1133 pos = wpabuf_head(groups);
1134 count = wpabuf_len(groups) / 2;
1135 for (i = 0; i < count; i++) {
1136 int enabled;
1137 u16 group;
1138
1139 group = WPA_GET_LE16(pos);
1140 pos += 2;
1141 enabled = sme_sae_is_group_enabled(wpa_s, group);
1142 wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
1143 group, enabled ? "enabled" : "disabled");
1144 if (enabled)
1145 return 1;
1146 }
1147
1148 return 0;
1149}
1150
1151
c10347f2 1152static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
5ff39c13
SD
1153 u16 status_code, const u8 *data, size_t len,
1154 int external, const u8 *sa)
c10347f2 1155{
a959a3b6
MH
1156 int *groups;
1157
c10347f2
JM
1158 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
1159 "status code %u", auth_transaction, status_code);
c10347f2 1160
d136c376
JM
1161 if (auth_transaction == 1 &&
1162 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1163 wpa_s->sme.sae.state == SAE_COMMITTED &&
5ff39c13 1164 (external || wpa_s->current_bss) && wpa_s->current_ssid) {
a9fe1303 1165 int default_groups[] = { 19, 20, 21, 0 };
a959a3b6
MH
1166 u16 group;
1167
1168 groups = wpa_s->conf->sae_groups;
1169 if (!groups || groups[0] <= 0)
1170 groups = default_groups;
1171
1172 if (len < sizeof(le16)) {
1173 wpa_dbg(wpa_s, MSG_DEBUG,
1174 "SME: Too short SAE anti-clogging token request");
1175 return -1;
1176 }
1177 group = WPA_GET_LE16(data);
1178 wpa_dbg(wpa_s, MSG_DEBUG,
1179 "SME: SAE anti-clogging token requested (group %u)",
1180 group);
1181 if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
1182 WLAN_STATUS_SUCCESS) {
1183 wpa_dbg(wpa_s, MSG_ERROR,
1184 "SME: SAE group %u of anti-clogging request is invalid",
1185 group);
1186 return -1;
1187 }
d136c376 1188 wpabuf_free(wpa_s->sme.sae_token);
a959a3b6
MH
1189 wpa_s->sme.sae_token = wpabuf_alloc_copy(data + sizeof(le16),
1190 len - sizeof(le16));
5ff39c13
SD
1191 if (!external)
1192 sme_send_authentication(wpa_s, wpa_s->current_bss,
fd830891 1193 wpa_s->current_ssid, 2);
5ff39c13
SD
1194 else
1195 sme_external_auth_send_sae_commit(
d42df8d6 1196 wpa_s, wpa_s->sme.ext_auth_bssid,
5ff39c13 1197 wpa_s->current_ssid);
d136c376
JM
1198 return 0;
1199 }
1200
625f202a
JM
1201 if (auth_transaction == 1 &&
1202 status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1203 wpa_s->sme.sae.state == SAE_COMMITTED &&
5ff39c13 1204 (external || wpa_s->current_bss) && wpa_s->current_ssid) {
625f202a 1205 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
447cd5f2
JM
1206 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1207 wpa_s->sme.sae.group);
625f202a
JM
1208 wpa_s->sme.sae_group_index++;
1209 if (sme_set_sae_group(wpa_s) < 0)
1210 return -1; /* no other groups enabled */
1211 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
5ff39c13
SD
1212 if (!external)
1213 sme_send_authentication(wpa_s, wpa_s->current_bss,
1214 wpa_s->current_ssid, 1);
1215 else
1216 sme_external_auth_send_sae_commit(
d42df8d6 1217 wpa_s, wpa_s->sme.ext_auth_bssid,
5ff39c13 1218 wpa_s->current_ssid);
625f202a
JM
1219 return 0;
1220 }
1221
9be19d0b
JM
1222 if (auth_transaction == 1 &&
1223 status_code == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1224 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1225
1226 wpa_msg(wpa_s, MSG_INFO,
1227 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR,
1228 MAC2STR(bssid));
1229 return -1;
1230 }
1231
cfe1ea5c
JM
1232 if (status_code != WLAN_STATUS_SUCCESS &&
1233 status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT)
c10347f2
JM
1234 return -1;
1235
1236 if (auth_transaction == 1) {
6a58444d
JM
1237 u16 res;
1238
a959a3b6 1239 groups = wpa_s->conf->sae_groups;
18ca7332 1240
c10347f2 1241 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
5ff39c13 1242 if ((!external && wpa_s->current_bss == NULL) ||
c10347f2
JM
1243 wpa_s->current_ssid == NULL)
1244 return -1;
1b5865a5
JM
1245 if (wpa_s->sme.sae.state != SAE_COMMITTED) {
1246 wpa_printf(MSG_DEBUG,
1247 "SAE: Ignore commit message while waiting for confirm");
1248 return 0;
1249 }
18ca7332
JM
1250 if (groups && groups[0] <= 0)
1251 groups = NULL;
6a58444d 1252 res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
86f60848
JM
1253 groups, status_code ==
1254 WLAN_STATUS_SAE_HASH_TO_ELEMENT);
6a58444d
JM
1255 if (res == SAE_SILENTLY_DISCARD) {
1256 wpa_printf(MSG_DEBUG,
1257 "SAE: Drop commit message due to reflection attack");
1258 return 0;
1259 }
1260 if (res != WLAN_STATUS_SUCCESS)
21af6d15 1261 return -1;
146f6c9a 1262
444d76f7
JM
1263 if (wpa_s->sme.sae.tmp &&
1264 sme_check_sae_rejected_groups(
1265 wpa_s,
c88e01e1 1266 wpa_s->sme.sae.tmp->peer_rejected_groups))
444d76f7
JM
1267 return -1;
1268
146f6c9a
JM
1269 if (sae_process_commit(&wpa_s->sme.sae) < 0) {
1270 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
1271 "commit");
1272 return -1;
1273 }
1274
d136c376
JM
1275 wpabuf_free(wpa_s->sme.sae_token);
1276 wpa_s->sme.sae_token = NULL;
5ff39c13
SD
1277 if (!external)
1278 sme_send_authentication(wpa_s, wpa_s->current_bss,
1279 wpa_s->current_ssid, 0);
1280 else
1281 sme_external_auth_send_sae_confirm(wpa_s, sa);
c10347f2
JM
1282 return 0;
1283 } else if (auth_transaction == 2) {
cfe1ea5c
JM
1284 if (status_code != WLAN_STATUS_SUCCESS)
1285 return -1;
c10347f2 1286 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
dd43026a 1287 if (wpa_s->sme.sae.state != SAE_CONFIRMED)
21af6d15 1288 return -1;
f2e9818f 1289 if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0)
21af6d15 1290 return -1;
dd43026a 1291 wpa_s->sme.sae.state = SAE_ACCEPTED;
b4fd3613 1292 sae_clear_temp_data(&wpa_s->sme.sae);
5ff39c13
SD
1293
1294 if (external) {
1295 /* Report success to driver */
1296 sme_send_external_auth_status(wpa_s,
1297 WLAN_STATUS_SUCCESS);
1298 }
1299
c10347f2
JM
1300 return 1;
1301 }
1302
1303 return -1;
1304}
5ff39c13
SD
1305
1306
b7cd6487 1307static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
d2b20838
JM
1308{
1309 wpa_printf(MSG_DEBUG,
1310 "SME: SAE completed - setting PMK for 4-way handshake");
1311 wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN,
b7cd6487 1312 wpa_s->sme.sae.pmkid, bssid);
d2b20838
JM
1313 if (wpa_s->conf->sae_pmkid_in_assoc) {
1314 /* Update the own RSNE contents now that we have set the PMK
1315 * and added a PMKSA cache entry based on the successfully
1316 * completed SAE exchange. In practice, this will add the PMKID
1317 * into RSNE. */
1318 if (wpa_s->sme.assoc_req_ie_len + 2 + PMKID_LEN >
1319 sizeof(wpa_s->sme.assoc_req_ie)) {
1320 wpa_msg(wpa_s, MSG_WARNING,
1321 "RSN: Not enough room for inserting own PMKID into RSNE");
1322 return -1;
1323 }
1324 if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
1325 &wpa_s->sme.assoc_req_ie_len,
1326 wpa_s->sme.sae.pmkid) < 0)
1327 return -1;
1328 wpa_hexdump(MSG_DEBUG,
1329 "SME: Updated Association Request IEs",
1330 wpa_s->sme.assoc_req_ie,
1331 wpa_s->sme.assoc_req_ie_len);
1332 }
1333
1334 return 0;
1335}
1336
1337
5ff39c13
SD
1338void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
1339 const u8 *auth_frame, size_t len)
1340{
1341 const struct ieee80211_mgmt *header;
1342 size_t auth_length;
1343
1344 header = (const struct ieee80211_mgmt *) auth_frame;
1345 auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);
1346
1347 if (len < auth_length) {
1348 /* Notify failure to the driver */
1349 sme_send_external_auth_status(wpa_s,
1350 WLAN_STATUS_UNSPECIFIED_FAILURE);
1351 return;
1352 }
1353
fcb3f11e 1354 if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
5ff39c13
SD
1355 int res;
1356
fcb3f11e
AP
1357 res = sme_sae_auth(
1358 wpa_s, le_to_host16(header->u.auth.auth_transaction),
1359 le_to_host16(header->u.auth.status_code),
1360 header->u.auth.variable,
1361 len - auth_length, 1, header->sa);
5ff39c13
SD
1362 if (res < 0) {
1363 /* Notify failure to the driver */
1364 sme_send_external_auth_status(
1365 wpa_s, WLAN_STATUS_UNSPECIFIED_FAILURE);
1366 return;
1367 }
1368 if (res != 1)
1369 return;
1370
b7cd6487 1371 if (sme_sae_set_pmk(wpa_s, wpa_s->sme.ext_auth_bssid) < 0)
d2b20838 1372 return;
5ff39c13
SD
1373 }
1374}
1375
c10347f2
JM
1376#endif /* CONFIG_SAE */
1377
1378
c2a04078
JM
1379void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
1380{
c2a04078
JM
1381 struct wpa_ssid *ssid = wpa_s->current_ssid;
1382
1383 if (ssid == NULL) {
f049052b
BG
1384 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1385 "when network is not selected");
c2a04078
JM
1386 return;
1387 }
1388
1389 if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
f049052b
BG
1390 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1391 "when not in authenticating state");
c2a04078
JM
1392 return;
1393 }
1394
1395 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) {
f049052b
BG
1396 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
1397 "unexpected peer " MACSTR,
1398 MAC2STR(data->auth.peer));
c2a04078
JM
1399 return;
1400 }
1401
f049052b 1402 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
c10347f2 1403 " auth_type=%d auth_transaction=%d status_code=%d",
f049052b 1404 MAC2STR(data->auth.peer), data->auth.auth_type,
c10347f2 1405 data->auth.auth_transaction, data->auth.status_code);
c2a04078
JM
1406 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
1407 data->auth.ies, data->auth.ies_len);
1408
e29853bb
BG
1409 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
1410
c10347f2
JM
1411#ifdef CONFIG_SAE
1412 if (data->auth.auth_type == WLAN_AUTH_SAE) {
21af6d15
JM
1413 int res;
1414 res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
1415 data->auth.status_code, data->auth.ies,
5ff39c13 1416 data->auth.ies_len, 0, NULL);
21af6d15
JM
1417 if (res < 0) {
1418 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1419 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1420
1421 }
1422 if (res != 1)
c10347f2 1423 return;
47b55a3e 1424
b7cd6487 1425 if (sme_sae_set_pmk(wpa_s, wpa_s->pending_bssid) < 0)
d2b20838 1426 return;
c10347f2
JM
1427 }
1428#endif /* CONFIG_SAE */
1429
c2a04078 1430 if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
ec4387f9
JM
1431 char *ie_txt = NULL;
1432
1433 if (data->auth.ies && data->auth.ies_len) {
1434 size_t buflen = 2 * data->auth.ies_len + 1;
1435 ie_txt = os_malloc(buflen);
1436 if (ie_txt) {
1437 wpa_snprintf_hex(ie_txt, buflen, data->auth.ies,
1438 data->auth.ies_len);
1439 }
1440 }
1441 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
5f11880f 1442 " auth_type=%u auth_transaction=%u status_code=%u%s%s",
ec4387f9
JM
1443 MAC2STR(data->auth.peer), data->auth.auth_type,
1444 data->auth.auth_transaction, data->auth.status_code,
5f11880f
JM
1445 ie_txt ? " ie=" : "",
1446 ie_txt ? ie_txt : "");
ec4387f9 1447 os_free(ie_txt);
cb1583f6 1448
af835d75
AB
1449#ifdef CONFIG_FILS
1450 if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
1451 wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS)
1452 fils_connection_failure(wpa_s);
1453#endif /* CONFIG_FILS */
1454
cb1583f6
SO
1455 if (data->auth.status_code !=
1456 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
1457 wpa_s->sme.auth_alg == data->auth.auth_type ||
7e6646c7 1458 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
0fb337c1 1459 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
c1c02342 1460 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
cb1583f6 1461 return;
7e6646c7 1462 }
cb1583f6 1463
d9504779
JM
1464 wpas_connect_work_done(wpa_s);
1465
cb1583f6
SO
1466 switch (data->auth.auth_type) {
1467 case WLAN_AUTH_OPEN:
1468 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
1469
f049052b 1470 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
cb1583f6
SO
1471 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
1472 wpa_s->current_ssid);
1473 return;
1474
1475 case WLAN_AUTH_SHARED_KEY:
1476 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
1477
f049052b 1478 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
cb1583f6
SO
1479 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
1480 wpa_s->current_ssid);
1481 return;
1482
1483 default:
1484 return;
1485 }
c2a04078
JM
1486 }
1487
1488#ifdef CONFIG_IEEE80211R
1489 if (data->auth.auth_type == WLAN_AUTH_FT) {
c6c41f6e
JM
1490 const u8 *ric_ies = NULL;
1491 size_t ric_ies_len = 0;
1492
1493 if (wpa_s->ric_ies) {
1494 ric_ies = wpabuf_head(wpa_s->ric_ies);
1495 ric_ies_len = wpabuf_len(wpa_s->ric_ies);
1496 }
ee140ef9
JM
1497 if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
1498 data->auth.ies_len, 0,
c6c41f6e
JM
1499 data->auth.peer,
1500 ric_ies, ric_ies_len) < 0) {
ee140ef9
JM
1501 wpa_dbg(wpa_s, MSG_DEBUG,
1502 "SME: FT Authentication response processing failed");
1503 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
1504 MACSTR
1505 " reason=%d locally_generated=1",
1506 MAC2STR(wpa_s->pending_bssid),
1507 WLAN_REASON_DEAUTH_LEAVING);
1508 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1509 wpa_supplicant_mark_disassoc(wpa_s);
1510 return;
1511 }
c2a04078
JM
1512 }
1513#endif /* CONFIG_IEEE80211R */
1514
a6609937 1515#ifdef CONFIG_FILS
76e20f4f
JM
1516 if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
1517 data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
1518 u16 expect_auth_type;
1519
1520 expect_auth_type = wpa_s->sme.auth_alg ==
1521 WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
1522 WLAN_AUTH_FILS_SK;
1523 if (data->auth.auth_type != expect_auth_type) {
1524 wpa_dbg(wpa_s, MSG_DEBUG,
1525 "SME: FILS Authentication response used different auth alg (%u; expected %u)",
1526 data->auth.auth_type, expect_auth_type);
1527 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
1528 MACSTR
1529 " reason=%d locally_generated=1",
1530 MAC2STR(wpa_s->pending_bssid),
1531 WLAN_REASON_DEAUTH_LEAVING);
1532 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1533 wpa_supplicant_mark_disassoc(wpa_s);
1534 return;
1535 }
1536
ba9774bd
JM
1537 if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
1538 data->auth.ies, data->auth.ies_len) < 0) {
a6609937
JM
1539 wpa_dbg(wpa_s, MSG_DEBUG,
1540 "SME: FILS Authentication response processing failed");
1541 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
1542 MACSTR
1543 " reason=%d locally_generated=1",
1544 MAC2STR(wpa_s->pending_bssid),
1545 WLAN_REASON_DEAUTH_LEAVING);
1546 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1547 wpa_supplicant_mark_disassoc(wpa_s);
1548 return;
1549 }
1550 }
1551#endif /* CONFIG_FILS */
1552
71024cb2
JM
1553 sme_associate(wpa_s, ssid->mode, data->auth.peer,
1554 data->auth.auth_type);
1555}
1556
1557
7d440a3b
JM
1558#ifdef CONFIG_IEEE80211R
1559static void remove_ie(u8 *buf, size_t *len, u8 eid)
1560{
1561 u8 *pos, *next, *end;
1562
1563 pos = (u8 *) get_ie(buf, *len, eid);
1564 if (pos) {
1565 next = pos + 2 + pos[1];
1566 end = buf + *len;
1567 *len -= 2 + pos[1];
1568 os_memmove(pos, next, end - next);
1569 }
1570}
1571#endif /* CONFIG_IEEE80211R */
1572
1573
71024cb2
JM
1574void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
1575 const u8 *bssid, u16 auth_type)
1576{
1577 struct wpa_driver_associate_params params;
d9a27b04 1578 struct ieee802_11_elems elems;
86cd6928
JM
1579#ifdef CONFIG_FILS
1580 u8 nonces[2 * FILS_NONCE_LEN];
1581#endif /* CONFIG_FILS */
80e8a5ee
BG
1582#ifdef CONFIG_HT_OVERRIDES
1583 struct ieee80211_ht_capabilities htcaps;
1584 struct ieee80211_ht_capabilities htcaps_mask;
1585#endif /* CONFIG_HT_OVERRIDES */
e9ee8dc3
JB
1586#ifdef CONFIG_VHT_OVERRIDES
1587 struct ieee80211_vht_capabilities vhtcaps;
1588 struct ieee80211_vht_capabilities vhtcaps_mask;
1589#endif /* CONFIG_VHT_OVERRIDES */
71024cb2 1590
c2a04078 1591 os_memset(&params, 0, sizeof(params));
86cd6928
JM
1592
1593#ifdef CONFIG_FILS
76e20f4f
JM
1594 if (auth_type == WLAN_AUTH_FILS_SK ||
1595 auth_type == WLAN_AUTH_FILS_SK_PFS) {
86cd6928
JM
1596 struct wpabuf *buf;
1597 const u8 *snonce, *anonce;
5732b770
JM
1598 const unsigned int max_hlp = 20;
1599 struct wpabuf *hlp[max_hlp];
1600 unsigned int i, num_hlp = 0;
1601 struct fils_hlp_req *req;
1602
1603 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
1604 list) {
1605 hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
1606 wpabuf_len(req->pkt));
1607 if (!hlp[num_hlp])
1608 break;
1609 wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
1610 wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
1611 ETH_ALEN);
1612 wpabuf_put_data(hlp[num_hlp],
1613 "\xaa\xaa\x03\x00\x00\x00", 6);
1614 wpabuf_put_buf(hlp[num_hlp], req->pkt);
1615 num_hlp++;
1616 if (num_hlp >= max_hlp)
1617 break;
1618 }
86cd6928
JM
1619
1620 buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
1621 &params.fils_kek_len, &snonce,
5732b770
JM
1622 &anonce,
1623 (const struct wpabuf **) hlp,
1624 num_hlp);
1625 for (i = 0; i < num_hlp; i++)
1626 wpabuf_free(hlp[i]);
86cd6928
JM
1627 if (!buf)
1628 return;
7d440a3b
JM
1629 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req before FILS elements",
1630 wpa_s->sme.assoc_req_ie,
1631 wpa_s->sme.assoc_req_ie_len);
1632#ifdef CONFIG_IEEE80211R
1633 if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
1634 /* Remove RSNE and MDE to allow them to be overridden
1635 * with FILS+FT specific values from
1636 * fils_build_assoc_req(). */
1637 remove_ie(wpa_s->sme.assoc_req_ie,
1638 &wpa_s->sme.assoc_req_ie_len,
1639 WLAN_EID_RSN);
1640 wpa_hexdump(MSG_DEBUG,
1641 "FILS: assoc_req after RSNE removal",
1642 wpa_s->sme.assoc_req_ie,
1643 wpa_s->sme.assoc_req_ie_len);
1644 remove_ie(wpa_s->sme.assoc_req_ie,
1645 &wpa_s->sme.assoc_req_ie_len,
1646 WLAN_EID_MOBILITY_DOMAIN);
1647 wpa_hexdump(MSG_DEBUG,
1648 "FILS: assoc_req after MDE removal",
1649 wpa_s->sme.assoc_req_ie,
1650 wpa_s->sme.assoc_req_ie_len);
1651 }
1652#endif /* CONFIG_IEEE80211R */
86cd6928
JM
1653 /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
1654 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
1655 sizeof(wpa_s->sme.assoc_req_ie)) {
1656 wpa_printf(MSG_ERROR,
1657 "FILS: Not enough buffer room for own AssocReq elements");
1658 wpabuf_free(buf);
1659 return;
1660 }
1661 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1662 wpabuf_head(buf), wpabuf_len(buf));
1663 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
1664 wpabuf_free(buf);
7d440a3b
JM
1665 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req after FILS elements",
1666 wpa_s->sme.assoc_req_ie,
1667 wpa_s->sme.assoc_req_ie_len);
86cd6928
JM
1668
1669 os_memcpy(nonces, snonce, FILS_NONCE_LEN);
1670 os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
1671 params.fils_nonces = nonces;
1672 params.fils_nonces_len = sizeof(nonces);
1673 }
1674#endif /* CONFIG_FILS */
1675
0a614799 1676#ifdef CONFIG_OWE
265bda34
JM
1677#ifdef CONFIG_TESTING_OPTIONS
1678 if (get_ie_ext(wpa_s->sme.assoc_req_ie, wpa_s->sme.assoc_req_ie_len,
1679 WLAN_EID_EXT_OWE_DH_PARAM)) {
1680 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
1681 } else
1682#endif /* CONFIG_TESTING_OPTIONS */
0a614799
JM
1683 if (auth_type == WLAN_AUTH_OPEN &&
1684 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1685 struct wpabuf *owe_ie;
2cb40e9f 1686 u16 group;
0a614799 1687
2cb40e9f 1688 if (wpa_s->current_ssid && wpa_s->current_ssid->owe_group) {
ec9f4837 1689 group = wpa_s->current_ssid->owe_group;
698c9e20
AK
1690 } else if (wpa_s->assoc_status_code ==
1691 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
2cb40e9f
JM
1692 if (wpa_s->last_owe_group == 19)
1693 group = 20;
1694 else if (wpa_s->last_owe_group == 20)
1695 group = 21;
1696 else
1697 group = OWE_DH_GROUP;
698c9e20
AK
1698 } else {
1699 group = OWE_DH_GROUP;
2cb40e9f 1700 }
698c9e20 1701
2cb40e9f
JM
1702 wpa_s->last_owe_group = group;
1703 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
ec9f4837 1704 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
0a614799
JM
1705 if (!owe_ie) {
1706 wpa_printf(MSG_ERROR,
1707 "OWE: Failed to build IE for Association Request frame");
1708 return;
1709 }
1710 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(owe_ie) >
1711 sizeof(wpa_s->sme.assoc_req_ie)) {
1712 wpa_printf(MSG_ERROR,
1713 "OWE: Not enough buffer room for own Association Request frame elements");
1714 wpabuf_free(owe_ie);
1715 return;
1716 }
1717 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1718 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
1719 wpa_s->sme.assoc_req_ie_len += wpabuf_len(owe_ie);
1720 wpabuf_free(owe_ie);
1721 }
1722#endif /* CONFIG_OWE */
1723
10ec6a5f
JM
1724#ifdef CONFIG_DPP2
1725 if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->current_ssid &&
1726 wpa_s->current_ssid->dpp_netaccesskey) {
1727 struct wpa_ssid *ssid = wpa_s->current_ssid;
1728
1729 dpp_pfs_free(wpa_s->dpp_pfs);
1730 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
1731 ssid->dpp_netaccesskey_len);
1732 if (!wpa_s->dpp_pfs) {
1733 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
1734 /* Try to continue without PFS */
1735 goto pfs_fail;
1736 }
1737 if (wpa_s->sme.assoc_req_ie_len +
1738 wpabuf_len(wpa_s->dpp_pfs->ie) >
1739 sizeof(wpa_s->sme.assoc_req_ie)) {
1740 wpa_printf(MSG_ERROR,
1741 "DPP: Not enough buffer room for own Association Request frame elements");
1742 dpp_pfs_free(wpa_s->dpp_pfs);
1743 wpa_s->dpp_pfs = NULL;
1744 goto pfs_fail;
1745 }
1746 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1747 wpabuf_head(wpa_s->dpp_pfs->ie),
1748 wpabuf_len(wpa_s->dpp_pfs->ie));
1749 wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
1750 }
1751pfs_fail:
1752#endif /* CONFIG_DPP2 */
1753
5abc7823
VN
1754 if (wpa_s->current_ssid && wpa_s->current_ssid->multi_ap_backhaul_sta) {
1755 size_t multi_ap_ie_len;
1756
1757 multi_ap_ie_len = add_multi_ap_ie(
1758 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1759 sizeof(wpa_s->sme.assoc_req_ie) -
1760 wpa_s->sme.assoc_req_ie_len,
1761 MULTI_AP_BACKHAUL_STA);
1762 if (multi_ap_ie_len == 0) {
1763 wpa_printf(MSG_ERROR,
1764 "Multi-AP: Failed to build Multi-AP IE");
1765 return;
1766 }
1767 wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
1768 }
1769
71024cb2 1770 params.bssid = bssid;
c2a04078
JM
1771 params.ssid = wpa_s->sme.ssid;
1772 params.ssid_len = wpa_s->sme.ssid_len;
4ec68377 1773 params.freq.freq = wpa_s->sme.freq;
1f6c0ab8
BS
1774 params.bg_scan_period = wpa_s->current_ssid ?
1775 wpa_s->current_ssid->bg_scan_period : -1;
c2a04078
JM
1776 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
1777 wpa_s->sme.assoc_req_ie : NULL;
1778 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
8c41734e
JM
1779 wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
1780 params.wpa_ie, params.wpa_ie_len);
4848a38d
JM
1781 params.pairwise_suite = wpa_s->pairwise_cipher;
1782 params.group_suite = wpa_s->group_cipher;
61a56c14 1783 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
163f801e
JM
1784 params.key_mgmt_suite = wpa_s->key_mgmt;
1785 params.wpa_proto = wpa_s->wpa_proto;
80e8a5ee
BG
1786#ifdef CONFIG_HT_OVERRIDES
1787 os_memset(&htcaps, 0, sizeof(htcaps));
1788 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1789 params.htcaps = (u8 *) &htcaps;
1790 params.htcaps_mask = (u8 *) &htcaps_mask;
1791 wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, &params);
1792#endif /* CONFIG_HT_OVERRIDES */
e9ee8dc3
JB
1793#ifdef CONFIG_VHT_OVERRIDES
1794 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
1795 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
1796 params.vhtcaps = &vhtcaps;
1797 params.vhtcaps_mask = &vhtcaps_mask;
1798 wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
1799#endif /* CONFIG_VHT_OVERRIDES */
c2a04078 1800#ifdef CONFIG_IEEE80211R
8c41734e
JM
1801 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
1802 get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
1803 WLAN_EID_RIC_DATA)) {
1804 /* There seems to be a pretty inconvenient bug in the Linux
1805 * kernel IE splitting functionality when RIC is used. For now,
1806 * skip correct behavior in IE construction here (i.e., drop the
1807 * additional non-FT-specific IEs) to avoid kernel issues. This
1808 * is fine since RIC is used only for testing purposes in the
1809 * current implementation. */
1810 wpa_printf(MSG_INFO,
1811 "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
c2a04078
JM
1812 params.wpa_ie = wpa_s->sme.ft_ies;
1813 params.wpa_ie_len = wpa_s->sme.ft_ies_len;
8c41734e
JM
1814 } else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
1815 const u8 *rm_en, *pos, *end;
1816 size_t rm_en_len = 0;
1817 u8 *rm_en_dup = NULL, *wpos;
1818
1819 /* Remove RSNE, MDE, FTE to allow them to be overridden with
1820 * FT specific values */
1821 remove_ie(wpa_s->sme.assoc_req_ie,
1822 &wpa_s->sme.assoc_req_ie_len,
1823 WLAN_EID_RSN);
1824 remove_ie(wpa_s->sme.assoc_req_ie,
1825 &wpa_s->sme.assoc_req_ie_len,
1826 WLAN_EID_MOBILITY_DOMAIN);
1827 remove_ie(wpa_s->sme.assoc_req_ie,
1828 &wpa_s->sme.assoc_req_ie_len,
1829 WLAN_EID_FAST_BSS_TRANSITION);
1830 rm_en = get_ie(wpa_s->sme.assoc_req_ie,
1831 wpa_s->sme.assoc_req_ie_len,
1832 WLAN_EID_RRM_ENABLED_CAPABILITIES);
1833 if (rm_en) {
1834 /* Need to remove RM Enabled Capabilities element as
1835 * well temporarily, so that it can be placed between
1836 * RSNE and MDE. */
1837 rm_en_len = 2 + rm_en[1];
1838 rm_en_dup = os_memdup(rm_en, rm_en_len);
1839 remove_ie(wpa_s->sme.assoc_req_ie,
1840 &wpa_s->sme.assoc_req_ie_len,
1841 WLAN_EID_RRM_ENABLED_CAPABILITIES);
1842 }
1843 wpa_hexdump(MSG_DEBUG,
1844 "SME: Association Request IEs after FT IE removal",
1845 wpa_s->sme.assoc_req_ie,
1846 wpa_s->sme.assoc_req_ie_len);
1847 if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
1848 rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
1849 wpa_printf(MSG_ERROR,
1850 "SME: Not enough buffer room for FT IEs in Association Request frame");
1851 os_free(rm_en_dup);
1852 return;
1853 }
1854
1855 os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
1856 rm_en_len,
1857 wpa_s->sme.assoc_req_ie,
1858 wpa_s->sme.assoc_req_ie_len);
1859 pos = wpa_s->sme.ft_ies;
1860 end = pos + wpa_s->sme.ft_ies_len;
1861 wpos = wpa_s->sme.assoc_req_ie;
1862 if (*pos == WLAN_EID_RSN) {
1863 os_memcpy(wpos, pos, 2 + pos[1]);
1864 wpos += 2 + pos[1];
1865 pos += 2 + pos[1];
1866 }
1867 if (rm_en_dup) {
1868 os_memcpy(wpos, rm_en_dup, rm_en_len);
1869 wpos += rm_en_len;
1870 os_free(rm_en_dup);
1871 }
1872 os_memcpy(wpos, pos, end - pos);
1873 wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
1874 rm_en_len;
1875 params.wpa_ie = wpa_s->sme.assoc_req_ie;
1876 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
1877 wpa_hexdump(MSG_DEBUG,
1878 "SME: Association Request IEs after FT override",
1879 params.wpa_ie, params.wpa_ie_len);
c2a04078
JM
1880 }
1881#endif /* CONFIG_IEEE80211R */
71024cb2 1882 params.mode = mode;
c2a04078 1883 params.mgmt_frame_protection = wpa_s->sme.mfp;
b361d580 1884 params.rrm_used = wpa_s->rrm.rrm_used;
62fa124c
JM
1885 if (wpa_s->sme.prev_bssid_set)
1886 params.prev_bssid = wpa_s->sme.prev_bssid;
c2a04078
JM
1887
1888 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
1889 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
1890 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
4ec68377 1891 params.freq.freq);
c2a04078
JM
1892
1893 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1894
9efc3f2a
JM
1895 if (params.wpa_ie == NULL ||
1896 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
d9a27b04 1897 < 0) {
f049052b 1898 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
d9a27b04
JM
1899 os_memset(&elems, 0, sizeof(elems));
1900 }
64fa840a
JM
1901 if (elems.rsn_ie) {
1902 params.wpa_proto = WPA_PROTO_RSN;
d9a27b04
JM
1903 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
1904 elems.rsn_ie_len + 2);
64fa840a
JM
1905 } else if (elems.wpa_ie) {
1906 params.wpa_proto = WPA_PROTO_WPA;
d9a27b04
JM
1907 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
1908 elems.wpa_ie_len + 2);
df0f01d9
JM
1909 } else if (elems.osen) {
1910 params.wpa_proto = WPA_PROTO_OSEN;
1911 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
1912 elems.osen_len + 2);
64fa840a 1913 } else
d9a27b04 1914 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
6d6c8877
JM
1915 if (elems.rsnxe)
1916 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, elems.rsnxe - 2,
1917 elems.rsnxe_len + 2);
1918 else
1919 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
ffad8858 1920 if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group)
6e3f4b89 1921 params.p2p = 1;
d9a27b04 1922
ba307f85
LD
1923 if (wpa_s->p2pdev->set_sta_uapsd)
1924 params.uapsd = wpa_s->p2pdev->sta_uapsd;
eea2fd9e
JM
1925 else
1926 params.uapsd = -1;
1927
c2a04078 1928 if (wpa_drv_associate(wpa_s, &params) < 0) {
f049052b
BG
1929 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
1930 "driver failed");
e5ad96b7 1931 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
c1c02342 1932 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
e5ad96b7 1933 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
c2a04078
JM
1934 return;
1935 }
1936
e29853bb
BG
1937 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
1938 NULL);
daa40960
JM
1939
1940#ifdef CONFIG_TESTING_OPTIONS
1941 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
1942 wpa_s->last_assoc_req_wpa_ie = NULL;
1943 if (params.wpa_ie)
1944 wpa_s->last_assoc_req_wpa_ie =
1945 wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len);
1946#endif /* CONFIG_TESTING_OPTIONS */
c2a04078
JM
1947}
1948
1949
1950int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
1951 const u8 *ies, size_t ies_len)
1952{
1953 if (md == NULL || ies == NULL) {
f049052b 1954 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
c2a04078
JM
1955 os_free(wpa_s->sme.ft_ies);
1956 wpa_s->sme.ft_ies = NULL;
1957 wpa_s->sme.ft_ies_len = 0;
1958 wpa_s->sme.ft_used = 0;
1959 return 0;
1960 }
1961
1962 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
1963 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
1964 os_free(wpa_s->sme.ft_ies);
a1f11e34 1965 wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
c2a04078
JM
1966 if (wpa_s->sme.ft_ies == NULL)
1967 return -1;
c2a04078
JM
1968 wpa_s->sme.ft_ies_len = ies_len;
1969 return 0;
1970}
efa46078
JM
1971
1972
e29853bb 1973static void sme_deauth(struct wpa_supplicant *wpa_s)
efa46078 1974{
8bac466b
JM
1975 int bssid_changed;
1976
8bac466b 1977 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
76d11d3f 1978
76d11d3f
JM
1979 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
1980 WLAN_REASON_DEAUTH_LEAVING) < 0) {
f049052b
BG
1981 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
1982 "failed");
76d11d3f 1983 }
62fa124c 1984 wpa_s->sme.prev_bssid_set = 0;
76d11d3f 1985
0fb337c1 1986 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
76d11d3f 1987 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
efa46078
JM
1988 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1989 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
8bac466b
JM
1990 if (bssid_changed)
1991 wpas_notify_bssid_changed(wpa_s);
efa46078 1992}
da1fb17c
JM
1993
1994
e29853bb
BG
1995void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
1996 union wpa_event_data *data)
1997{
1998 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
1999 "status code %d", MAC2STR(wpa_s->pending_bssid),
2000 data->assoc_reject.status_code);
2001
2002 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2003
bc26ac50
JM
2004#ifdef CONFIG_SAE
2005 if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
2006 wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
2007 wpa_dbg(wpa_s, MSG_DEBUG,
2008 "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
2009 wpa_sm_aborted_cached(wpa_s->wpa);
2010 wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
2011 if (wpa_s->current_bss) {
2012 struct wpa_bss *bss = wpa_s->current_bss;
2013 struct wpa_ssid *ssid = wpa_s->current_ssid;
2014
2015 wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
2016 WLAN_REASON_DEAUTH_LEAVING);
2017 wpas_connect_work_done(wpa_s);
2018 wpa_supplicant_mark_disassoc(wpa_s);
2019 wpa_supplicant_connect(wpa_s, bss, ssid);
2020 return;
2021 }
2022 }
2023#endif /* CONFIG_SAE */
2024
e29853bb
BG
2025 /*
2026 * For now, unconditionally terminate the previous authentication. In
2027 * theory, this should not be needed, but mac80211 gets quite confused
2028 * if the authentication is left pending.. Some roaming cases might
2029 * benefit from using the previous authentication, so this could be
2030 * optimized in the future.
2031 */
2032 sme_deauth(wpa_s);
2033}
2034
2035
da1fb17c
JM
2036void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
2037 union wpa_event_data *data)
2038{
f049052b 2039 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
0fb337c1 2040 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1193dc8f 2041 wpa_supplicant_mark_disassoc(wpa_s);
da1fb17c
JM
2042}
2043
2044
2045void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
2046 union wpa_event_data *data)
2047{
f049052b 2048 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
0fb337c1 2049 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
da1fb17c 2050 wpa_supplicant_mark_disassoc(wpa_s);
da1fb17c 2051}
a84ed99e
JM
2052
2053
2054void sme_event_disassoc(struct wpa_supplicant *wpa_s,
d7df0fa7 2055 struct disassoc_info *info)
a84ed99e 2056{
f049052b 2057 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
17fbb751 2058 if (wpa_s->sme.prev_bssid_set) {
a84ed99e
JM
2059 /*
2060 * cfg80211/mac80211 can get into somewhat confused state if
2061 * the AP only disassociates us and leaves us in authenticated
2062 * state. For now, force the state to be cleared to avoid
2063 * confusing errors if we try to associate with the AP again.
2064 */
f049052b
BG
2065 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
2066 "driver state");
7e26053a 2067 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
a84ed99e
JM
2068 WLAN_REASON_DEAUTH_LEAVING);
2069 }
2070}
7d878ca7
JM
2071
2072
e29853bb
BG
2073static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
2074{
2075 struct wpa_supplicant *wpa_s = eloop_ctx;
2076 if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
2077 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
2078 sme_deauth(wpa_s);
2079 }
2080}
2081
2082
2083static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
2084{
2085 struct wpa_supplicant *wpa_s = eloop_ctx;
2086 if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2087 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
2088 sme_deauth(wpa_s);
2089 }
2090}
2091
2092
2093void sme_state_changed(struct wpa_supplicant *wpa_s)
2094{
2095 /* Make sure timers are cleaned up appropriately. */
2096 if (wpa_s->wpa_state != WPA_ASSOCIATING)
2097 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2098 if (wpa_s->wpa_state != WPA_AUTHENTICATING)
2099 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2100}
2101
2102
2103void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
2104 const u8 *prev_pending_bssid)
2105{
2106 /*
2107 * mac80211-workaround to force deauth on failed auth cmd,
2108 * requires us to remain in authenticating state to allow the
2109 * second authentication attempt to be continued properly.
2110 */
2111 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
2112 "to proceed after disconnection event");
2113 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
2114 os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
2115
2116 /*
2117 * Re-arm authentication timer in case auth fails for whatever reason.
2118 */
2119 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2120 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
2121 NULL);
2122}
2123
2124
4e70bbf1
JM
2125void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
2126{
2127 wpa_s->sme.prev_bssid_set = 0;
2128#ifdef CONFIG_SAE
2129 wpabuf_free(wpa_s->sme.sae_token);
2130 wpa_s->sme.sae_token = NULL;
2131 sae_clear_data(&wpa_s->sme.sae);
2132#endif /* CONFIG_SAE */
2133#ifdef CONFIG_IEEE80211R
60a5737e 2134 if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
4e70bbf1
JM
2135 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
2136#endif /* CONFIG_IEEE80211R */
01ac337b 2137 sme_stop_sa_query(wpa_s);
4e70bbf1
JM
2138}
2139
2140
e29853bb
BG
2141void sme_deinit(struct wpa_supplicant *wpa_s)
2142{
4e70bbf1 2143 sme_clear_on_disassoc(wpa_s);
447cd5f2
JM
2144#ifdef CONFIG_SAE
2145 os_free(wpa_s->sme.sae_rejected_groups);
2146 wpa_s->sme.sae_rejected_groups = NULL;
2147#endif /* CONFIG_SAE */
e29853bb
BG
2148
2149 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2150 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
c3701c66
RM
2151 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
2152}
2153
2154
2155static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
2156 const u8 *chan_list, u8 num_channels,
2157 u8 num_intol)
2158{
2159 struct ieee80211_2040_bss_coex_ie *bc_ie;
2160 struct ieee80211_2040_intol_chan_report *ic_report;
2161 struct wpabuf *buf;
2162
31ded52e
JM
2163 wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
2164 " (num_channels=%u num_intol=%u)",
2165 MAC2STR(wpa_s->bssid), num_channels, num_intol);
2166 wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
2167 chan_list, num_channels);
c3701c66
RM
2168
2169 buf = wpabuf_alloc(2 + /* action.category + action_code */
2170 sizeof(struct ieee80211_2040_bss_coex_ie) +
2171 sizeof(struct ieee80211_2040_intol_chan_report) +
2172 num_channels);
2173 if (buf == NULL)
2174 return;
2175
2176 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
2177 wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
2178
2179 bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
2180 bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
2181 bc_ie->length = 1;
2182 if (num_intol)
2183 bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
2184
2185 if (num_channels > 0) {
2186 ic_report = wpabuf_put(buf, sizeof(*ic_report));
2187 ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
2188 ic_report->length = num_channels + 1;
2189 ic_report->op_class = 0;
2190 os_memcpy(wpabuf_put(buf, num_channels), chan_list,
2191 num_channels);
2192 }
2193
2194 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
2195 wpa_s->own_addr, wpa_s->bssid,
2196 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
2197 wpa_msg(wpa_s, MSG_INFO,
2198 "SME: Failed to send 20/40 BSS Coexistence frame");
2199 }
2200
2201 wpabuf_free(buf);
2202}
2203
2204
c3701c66
RM
2205int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
2206{
2207 struct wpa_bss *bss;
2208 const u8 *ie;
2209 u16 ht_cap;
2210 u8 chan_list[P2P_MAX_CHANNELS], channel;
2211 u8 num_channels = 0, num_intol = 0, i;
2212
2213 if (!wpa_s->sme.sched_obss_scan)
2214 return 0;
2215
2216 wpa_s->sme.sched_obss_scan = 0;
2217 if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
2218 return 1;
2219
2220 /*
2221 * Check whether AP uses regulatory triplet or channel triplet in
2222 * country info. Right now the operating class of the BSS channel
2223 * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
2224 * based on the assumption that operating class triplet is not used in
2225 * beacon frame. If the First Channel Number/Operating Extension
2226 * Identifier octet has a positive integer value of 201 or greater,
2227 * then its operating class triplet.
2228 *
2229 * TODO: If Supported Operating Classes element is present in beacon
2230 * frame, have to lookup operating class in Annex E and fill them in
2231 * 2040 coex frame.
2232 */
2233 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
2234 if (ie && (ie[1] >= 6) && (ie[5] >= 201))
2235 return 1;
2236
2237 os_memset(chan_list, 0, sizeof(chan_list));
2238
2239 dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
2240 /* Skip other band bss */
e864c0ae
JM
2241 enum hostapd_hw_mode mode;
2242 mode = ieee80211_freq_to_chan(bss->freq, &channel);
2243 if (mode != HOSTAPD_MODE_IEEE80211G &&
2244 mode != HOSTAPD_MODE_IEEE80211B)
c3701c66
RM
2245 continue;
2246
2247 ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
2248 ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
31ded52e
JM
2249 wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
2250 " freq=%u chan=%u ht_cap=0x%x",
2251 MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
c3701c66
RM
2252
2253 if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
7f8eb34d
JM
2254 if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
2255 num_intol++;
2256
c3701c66
RM
2257 /* Check whether the channel is already considered */
2258 for (i = 0; i < num_channels; i++) {
2259 if (channel == chan_list[i])
2260 break;
2261 }
2262 if (i != num_channels)
2263 continue;
2264
c3701c66
RM
2265 chan_list[num_channels++] = channel;
2266 }
2267 }
2268
2269 sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
2270 return 1;
2271}
2272
2273
d97a3c48
JM
2274static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
2275 struct wpa_driver_scan_params *params)
6434ad09 2276{
d97a3c48 2277 /* Include only affected channels */
6434ad09
JM
2278 struct hostapd_hw_modes *mode;
2279 int count, i;
d97a3c48 2280 int start, end;
6434ad09 2281
d97a3c48
JM
2282 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
2283 HOSTAPD_MODE_IEEE80211G);
6434ad09
JM
2284 if (mode == NULL) {
2285 /* No channels supported in this band - use empty list */
2286 params->freqs = os_zalloc(sizeof(int));
2287 return;
2288 }
2289
d97a3c48
JM
2290 if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
2291 wpa_s->current_bss) {
2292 const u8 *ie;
2293
2294 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
2295 if (ie && ie[1] >= 2) {
2296 u8 o;
2297
2298 o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
2299 if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
2300 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
2301 else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
2302 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
2303 }
2304 }
2305
2306 start = wpa_s->assoc_freq - 10;
2307 end = wpa_s->assoc_freq + 10;
2308 switch (wpa_s->sme.ht_sec_chan) {
2309 case HT_SEC_CHAN_UNKNOWN:
2310 /* HT40+ possible on channels 1..9 */
2311 if (wpa_s->assoc_freq <= 2452)
2312 start -= 20;
2313 /* HT40- possible on channels 5-13 */
2314 if (wpa_s->assoc_freq >= 2432)
2315 end += 20;
2316 break;
2317 case HT_SEC_CHAN_ABOVE:
2318 end += 20;
2319 break;
2320 case HT_SEC_CHAN_BELOW:
2321 start -= 20;
2322 break;
2323 }
2324 wpa_printf(MSG_DEBUG,
2325 "OBSS: assoc_freq %d possible affected range %d-%d",
2326 wpa_s->assoc_freq, start, end);
2327
f9884c09 2328 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
6434ad09
JM
2329 if (params->freqs == NULL)
2330 return;
2331 for (count = 0, i = 0; i < mode->num_channels; i++) {
d97a3c48
JM
2332 int freq;
2333
6434ad09
JM
2334 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
2335 continue;
d97a3c48
JM
2336 freq = mode->channels[i].freq;
2337 if (freq - 10 >= end || freq + 10 <= start)
2338 continue; /* not affected */
2339 params->freqs[count++] = freq;
6434ad09
JM
2340 }
2341}
2342
2343
c3701c66
RM
2344static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
2345{
2346 struct wpa_supplicant *wpa_s = eloop_ctx;
2347 struct wpa_driver_scan_params params;
2348
2349 if (!wpa_s->current_bss) {
2350 wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
2351 return;
2352 }
2353
2354 os_memset(&params, 0, sizeof(params));
d97a3c48 2355 wpa_obss_scan_freqs_list(wpa_s, &params);
57a8f8af 2356 params.low_priority = 1;
c3701c66
RM
2357 wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
2358
2359 if (wpa_supplicant_trigger_scan(wpa_s, &params))
2360 wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
2361 else
2362 wpa_s->sme.sched_obss_scan = 1;
6434ad09 2363 os_free(params.freqs);
c3701c66
RM
2364
2365 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
2366 sme_obss_scan_timeout, wpa_s, NULL);
2367}
2368
2369
2370void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
2371{
2372 const u8 *ie;
2373 struct wpa_bss *bss = wpa_s->current_bss;
2374 struct wpa_ssid *ssid = wpa_s->current_ssid;
b6871ebb
AN
2375 struct hostapd_hw_modes *hw_mode = NULL;
2376 int i;
c3701c66
RM
2377
2378 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
2379 wpa_s->sme.sched_obss_scan = 0;
d97a3c48 2380 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
c3701c66
RM
2381 if (!enable)
2382 return;
2383
368b1957
AK
2384 /*
2385 * Schedule OBSS scan if driver is using station SME in wpa_supplicant
2386 * or it expects OBSS scan to be performed by wpa_supplicant.
2387 */
2388 if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
2389 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
f74618cb 2390 ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
368b1957 2391 return;
c3701c66 2392
b6871ebb
AN
2393 if (!wpa_s->hw.modes)
2394 return;
2395
2396 /* only HT caps in 11g mode are relevant */
2397 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2398 hw_mode = &wpa_s->hw.modes[i];
2399 if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
2400 break;
2401 }
2402
2403 /* Driver does not support HT40 for 11g or doesn't have 11g. */
2404 if (i == wpa_s->hw.num_modes || !hw_mode ||
2405 !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
2406 return;
c3701c66
RM
2407
2408 if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
2409 return; /* Not associated on 2.4 GHz band */
2410
2411 /* Check whether AP supports HT40 */
2412 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
2413 if (!ie || ie[1] < 2 ||
2414 !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
2415 return; /* AP does not support HT40 */
2416
2417 ie = wpa_bss_get_ie(wpa_s->current_bss,
2418 WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
2419 if (!ie || ie[1] < 14)
2420 return; /* AP does not request OBSS scans */
2421
2422 wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
2423 if (wpa_s->sme.obss_scan_int < 10) {
2424 wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
2425 "replaced with the minimum 10 sec",
2426 wpa_s->sme.obss_scan_int);
2427 wpa_s->sme.obss_scan_int = 10;
2428 }
2429 wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
2430 wpa_s->sme.obss_scan_int);
2431 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
2432 sme_obss_scan_timeout, wpa_s, NULL);
e29853bb
BG
2433}
2434
2435
7d878ca7
JM
2436static const unsigned int sa_query_max_timeout = 1000;
2437static const unsigned int sa_query_retry_timeout = 201;
f91e68e9 2438static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
7d878ca7
JM
2439
2440static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
2441{
2442 u32 tu;
46b8d4c0
JB
2443 struct os_reltime now, passed;
2444 os_get_reltime(&now);
2445 os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
7d878ca7
JM
2446 tu = (passed.sec * 1000000 + passed.usec) / 1024;
2447 if (sa_query_max_timeout < tu) {
f049052b 2448 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
7d878ca7
JM
2449 sme_stop_sa_query(wpa_s);
2450 wpa_supplicant_deauthenticate(
2451 wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
2452 return 1;
2453 }
2454
2455 return 0;
2456}
2457
2458
2459static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
2460 const u8 *trans_id)
2461{
f9da7505
MV
2462 u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
2463 u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
2464
f049052b
BG
2465 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
2466 MACSTR, MAC2STR(wpa_s->bssid));
7d878ca7
JM
2467 wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
2468 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
2469 req[0] = WLAN_ACTION_SA_QUERY;
2470 req[1] = WLAN_SA_QUERY_REQUEST;
2471 os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
f9da7505
MV
2472
2473#ifdef CONFIG_OCV
2474 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
2475 struct wpa_channel_info ci;
2476
2477 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
2478 wpa_printf(MSG_WARNING,
2479 "Failed to get channel info for OCI element in SA Query Request frame");
2480 return;
2481 }
2482
2483 if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
2484 return;
2485
2486 req_len += OCV_OCI_EXTENDED_LEN;
2487 }
2488#endif /* CONFIG_OCV */
2489
190b9062 2490 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
7d878ca7 2491 wpa_s->own_addr, wpa_s->bssid,
f9da7505 2492 req, req_len, 0) < 0)
f049052b
BG
2493 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
2494 "Request");
7d878ca7
JM
2495}
2496
2497
2498static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
2499{
2500 struct wpa_supplicant *wpa_s = eloop_ctx;
2501 unsigned int timeout, sec, usec;
2502 u8 *trans_id, *nbuf;
2503
2504 if (wpa_s->sme.sa_query_count > 0 &&
2505 sme_check_sa_query_timeout(wpa_s))
2506 return;
2507
067ffa26
JM
2508 nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
2509 wpa_s->sme.sa_query_count + 1,
2510 WLAN_SA_QUERY_TR_ID_LEN);
f8608fab
JM
2511 if (nbuf == NULL) {
2512 sme_stop_sa_query(wpa_s);
7d878ca7 2513 return;
f8608fab 2514 }
7d878ca7
JM
2515 if (wpa_s->sme.sa_query_count == 0) {
2516 /* Starting a new SA Query procedure */
46b8d4c0 2517 os_get_reltime(&wpa_s->sme.sa_query_start);
7d878ca7
JM
2518 }
2519 trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
2520 wpa_s->sme.sa_query_trans_id = nbuf;
2521 wpa_s->sme.sa_query_count++;
2522
cb5ef952
JM
2523 if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
2524 wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
f8608fab 2525 sme_stop_sa_query(wpa_s);
cb5ef952
JM
2526 return;
2527 }
7d878ca7
JM
2528
2529 timeout = sa_query_retry_timeout;
2530 sec = ((timeout / 1000) * 1024) / 1000;
2531 usec = (timeout % 1000) * 1024;
2532 eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
2533
f049052b
BG
2534 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
2535 wpa_s->sme.sa_query_count);
7d878ca7
JM
2536
2537 sme_send_sa_query_req(wpa_s, trans_id);
2538}
2539
2540
2541static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
2542{
2543 sme_sa_query_timer(wpa_s, NULL);
2544}
2545
2546
19df9b07 2547static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
7d878ca7 2548{
7a206c50
JM
2549 if (wpa_s->sme.sa_query_trans_id)
2550 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
7d878ca7
JM
2551 eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
2552 os_free(wpa_s->sme.sa_query_trans_id);
2553 wpa_s->sme.sa_query_trans_id = NULL;
2554 wpa_s->sme.sa_query_count = 0;
2555}
2556
2557
2558void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
2559 const u8 *da, u16 reason_code)
2560{
2561 struct wpa_ssid *ssid;
3302b7c2 2562 struct os_reltime now;
7d878ca7 2563
7d878ca7
JM
2564 if (wpa_s->wpa_state != WPA_COMPLETED)
2565 return;
2566 ssid = wpa_s->current_ssid;
3f56a2b7 2567 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
7d878ca7
JM
2568 return;
2569 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
2570 return;
2571 if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
2572 reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
2573 return;
2574 if (wpa_s->sme.sa_query_count > 0)
2575 return;
2576
3302b7c2
JM
2577 os_get_reltime(&now);
2578 if (wpa_s->sme.last_unprot_disconnect.sec &&
2579 !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
2580 return; /* limit SA Query procedure frequency */
2581 wpa_s->sme.last_unprot_disconnect = now;
2582
f049052b
BG
2583 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
2584 "possible AP/STA state mismatch - trigger SA Query");
7d878ca7
JM
2585 sme_start_sa_query(wpa_s);
2586}
2587
2588
f91e68e9
MV
2589void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
2590{
2591 unsigned int usec;
2592 u32 _rand;
2593
2594 if (wpa_s->wpa_state != WPA_COMPLETED ||
2595 !wpa_sm_ocv_enabled(wpa_s->wpa))
2596 return;
2597
2598 wpa_dbg(wpa_s, MSG_DEBUG,
2599 "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
2600 sme_stop_sa_query(wpa_s);
2601
2602 if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
2603 _rand = os_random();
2604 usec = _rand % (sa_query_ch_switch_max_delay + 1);
2605 eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
2606}
2607
2608
f9da7505
MV
2609static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
2610 const u8 *sa, const u8 *data,
2611 size_t len)
2612{
2613 u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
2614 u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
2615
2616 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
2617 MACSTR, MAC2STR(wpa_s->bssid));
2618
2619 resp[0] = WLAN_ACTION_SA_QUERY;
2620 resp[1] = WLAN_SA_QUERY_RESPONSE;
2621 os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
2622
2623#ifdef CONFIG_OCV
2624 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
2625 struct wpa_channel_info ci;
2626
2627 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
2628 wpa_printf(MSG_WARNING,
2629 "Failed to get channel info for OCI element in SA Query Response frame");
2630 return;
2631 }
2632
2633 if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
2634 return;
2635
2636 resp_len += OCV_OCI_EXTENDED_LEN;
2637 }
2638#endif /* CONFIG_OCV */
2639
2640 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
2641 wpa_s->own_addr, wpa_s->bssid,
2642 resp, resp_len, 0) < 0)
2643 wpa_msg(wpa_s, MSG_INFO,
2644 "SME: Failed to send SA Query Response");
2645}
2646
2647
2648static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
2649 const u8 *sa, const u8 *data,
2650 size_t len)
7d878ca7
JM
2651{
2652 int i;
2653
f9da7505 2654 if (!wpa_s->sme.sa_query_trans_id)
7d878ca7 2655 return;
f9da7505 2656
f049052b
BG
2657 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
2658 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
7d878ca7
JM
2659
2660 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
2661 return;
2662
2663 for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
2664 if (os_memcmp(wpa_s->sme.sa_query_trans_id +
2665 i * WLAN_SA_QUERY_TR_ID_LEN,
2666 data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
2667 break;
2668 }
2669
2670 if (i >= wpa_s->sme.sa_query_count) {
f049052b
BG
2671 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
2672 "transaction identifier found");
7d878ca7
JM
2673 return;
2674 }
2675
f049052b
BG
2676 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
2677 "from " MACSTR, MAC2STR(sa));
7d878ca7
JM
2678 sme_stop_sa_query(wpa_s);
2679}
2680
f9da7505
MV
2681
2682void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
2683 const u8 *data, size_t len)
2684{
2685 if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
2686 return;
2687
2688 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
2689 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
2690
2691#ifdef CONFIG_OCV
2692 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
2693 struct ieee802_11_elems elems;
2694 struct wpa_channel_info ci;
2695
2696 if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
2697 len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
2698 &elems, 1) == ParseFailed) {
2699 wpa_printf(MSG_DEBUG,
2700 "SA Query: Failed to parse elements");
2701 return;
2702 }
2703
2704 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
2705 wpa_printf(MSG_WARNING,
2706 "Failed to get channel info to validate received OCI in SA Query Action frame");
2707 return;
2708 }
2709
2710 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
2711 channel_width_to_int(ci.chanwidth),
2712 ci.seg1_idx) != 0) {
2713 wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
2714 return;
2715 }
2716 }
2717#endif /* CONFIG_OCV */
2718
2719 if (data[0] == WLAN_SA_QUERY_REQUEST)
2720 sme_process_sa_query_request(wpa_s, sa, data, len);
2721 else if (data[0] == WLAN_SA_QUERY_RESPONSE)
2722 sme_process_sa_query_response(wpa_s, sa, data, len);
2723}