blob: cfb5bb33da41f14065d8471b3b9061d2d327d9c5 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * wpa_supplicant - SME
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003 * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "utils/eloop.h"
13#include "common/ieee802_11_defs.h"
14#include "common/ieee802_11_common.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080015#include "common/ocv.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070016#include "eapol_supp/eapol_supp_sm.h"
17#include "common/wpa_common.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080018#include "common/sae.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070019#include "common/dpp.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070020#include "rsn_supp/wpa.h"
21#include "rsn_supp/pmksa_cache.h"
22#include "config.h"
23#include "wpa_supplicant_i.h"
24#include "driver_i.h"
25#include "wpas_glue.h"
26#include "wps_supplicant.h"
27#include "p2p_supplicant.h"
28#include "notify.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070029#include "bss.h"
30#include "scan.h"
31#include "sme.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070032#include "hs20_supplicant.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070033
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);
Dmitry Shmidt04949592012-07-19 12:16:46 -070039static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041
42
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080043#ifdef CONFIG_SAE
44
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080045static int index_within_array(const int *array, int idx)
46{
47 int i;
48 for (i = 0; i < idx; i++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -080049 if (array[i] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080050 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;
Hai Shalom021b0b52019-04-10 11:17:58 -070059 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080060
Dmitry Shmidtcce06662013-11-04 18:44:24 -080061 if (!groups || groups[0] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080062 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];
Dmitry Shmidt41712582015-06-29 11:02:15 -070070 if (group <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080071 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);
Hai Shalom74f70d42019-02-11 14:42:39 -080075 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080076 }
77 wpa_s->sme.sae_group_index++;
78 }
79
80 return -1;
81}
82
83
84static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
85 struct wpa_ssid *ssid,
Hai Shalom021b0b52019-04-10 11:17:58 -070086 const u8 *bssid, int external,
Hai Shalomc3565922019-10-28 11:58:20 -070087 int reuse, int *ret_use_pt)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080088{
89 struct wpabuf *buf;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080090 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070091 const char *password;
Hai Shalomc3565922019-10-28 11:58:20 -070092 struct wpa_bss *bss;
93 int use_pt = 0;
94
95 if (ret_use_pt)
96 *ret_use_pt = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080097
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070098#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;
Hai Shalom021b0b52019-04-10 11:17:58 -0700104 if (!external) {
105 wpabuf_put_le16(buf, 1); /* Transaction seq# */
106 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
107 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700108 wpabuf_put_buf(buf, wpa_s->sae_commit_override);
109 return buf;
110 }
111#endif /* CONFIG_TESTING_OPTIONS */
112
113 password = ssid->sae_password;
114 if (!password)
115 password = ssid->passphrase;
116 if (!password) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800117 wpa_printf(MSG_DEBUG, "SAE: No password available");
118 return NULL;
119 }
120
Hai Shalom021b0b52019-04-10 11:17:58 -0700121 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");
Hai Shalomc3565922019-10-28 11:58:20 -0700125 use_pt = wpa_s->sme.sae.tmp->h2e;
Hai Shalom021b0b52019-04-10 11:17:58 -0700126 goto reuse_data;
127 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800128 if (sme_set_sae_group(wpa_s) < 0) {
129 wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
130 return NULL;
131 }
132
Hai Shalomc3565922019-10-28 11:58:20 -0700133 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,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700158 (u8 *) password, os_strlen(password),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700159 ssid->sae_password_id,
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800160 &wpa_s->sme.sae) < 0) {
161 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
162 return NULL;
163 }
Hai Shalom021b0b52019-04-10 11:17:58 -0700164 if (wpa_s->sme.sae.tmp)
165 os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800166
Hai Shalom021b0b52019-04-10 11:17:58 -0700167reuse_data:
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800168 len = wpa_s->sme.sae_token ? wpabuf_len(wpa_s->sme.sae_token) : 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700169 if (ssid->sae_password_id)
170 len += 4 + os_strlen(ssid->sae_password_id);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800171 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800172 if (buf == NULL)
173 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700174 if (!external) {
175 wpabuf_put_le16(buf, 1); /* Transaction seq# */
Hai Shalomc3565922019-10-28 11:58:20 -0700176 wpabuf_put_le16(buf, use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
177 WLAN_STATUS_SUCCESS);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700178 }
179 sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
180 ssid->sae_password_id);
Hai Shalomc3565922019-10-28 11:58:20 -0700181 if (ret_use_pt)
182 *ret_use_pt = use_pt;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800183
184 return buf;
185}
186
187
Roshan Pius3a1667e2018-07-03 15:17:14 -0700188static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s,
189 int external)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800190{
191 struct wpabuf *buf;
192
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800193 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800194 if (buf == NULL)
195 return NULL;
196
Roshan Pius3a1667e2018-07-03 15:17:14 -0700197 if (!external) {
198 wpabuf_put_le16(buf, 2); /* Transaction seq# */
199 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
200 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800201 sae_write_confirm(&wpa_s->sme.sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800202
203 return buf;
204}
205
206#endif /* CONFIG_SAE */
207
208
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800209/**
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
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700233 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)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800237 wpa_printf(MSG_DEBUG,
238 "RRM: Insufficient RRM support in driver - do not use RRM");
239 return;
240 }
241
242 if (sizeof(wpa_s->sme.assoc_req_ie) <
243 wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) {
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;
251 os_memset(pos, 0, 2 + rrm_ie_len);
252 *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
253 *pos++ = rrm_ie_len;
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
Dmitry Shmidt29333592017-01-09 12:27:11 -0800259 *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
260 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
261 WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
262
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700263 if (wpa_s->lci)
264 pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
265
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800266 wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
267 wpa_s->rrm.rrm_used = 1;
268}
269
270
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800271static void sme_send_authentication(struct wpa_supplicant *wpa_s,
272 struct wpa_bss *bss, struct wpa_ssid *ssid,
273 int start)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700274{
275 struct wpa_driver_auth_params params;
276 struct wpa_ssid *old_ssid;
277#ifdef CONFIG_IEEE80211R
278 const u8 *ie;
279#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700280#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700281 const u8 *md = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700282#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700283 int i, bssid_changed;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800284 struct wpabuf *resp = NULL;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700285 u8 ext_capab[18];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800286 int ext_capab_len;
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800287 int skip_auth;
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800288 u8 *wpa_ie;
289 size_t wpa_ie_len;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700290#ifdef CONFIG_MBO
291 const u8 *mbo_ie;
292#endif /* CONFIG_MBO */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700293
294 if (bss == NULL) {
295 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
296 "the network");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800297 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700298 return;
299 }
300
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800301 skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
302 wpa_s->reassoc_same_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303 wpa_s->current_bss = bss;
304
305 os_memset(&params, 0, sizeof(params));
306 wpa_s->reassociate = 0;
307
308 params.freq = bss->freq;
309 params.bssid = bss->bssid;
310 params.ssid = bss->ssid;
311 params.ssid_len = bss->ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800312 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700313
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
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
322 params.auth_alg = WPA_AUTH_ALG_OPEN;
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)
327 params.auth_alg = WPA_AUTH_ALG_LEAP;
328 else
329 params.auth_alg |= WPA_AUTH_ALG_LEAP;
330 }
331 }
332#endif /* IEEE8021X_EAPOL */
333 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
334 params.auth_alg);
335 if (ssid->auth_alg) {
336 params.auth_alg = ssid->auth_alg;
337 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
338 "0x%x", params.auth_alg);
339 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800340#ifdef CONFIG_SAE
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800341 wpa_s->sme.sae_pmksa_caching = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800342 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);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800347 if (!rsn) {
348 wpa_dbg(wpa_s, MSG_DEBUG,
349 "SAE enabled, but target BSS does not advertise RSN");
Hai Shalom021b0b52019-04-10 11:17:58 -0700350#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 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800356 } 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");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800363 }
364 }
365#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366
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
374 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
375 os_memset(wpa_s->bssid, 0, ETH_ALEN);
376 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
377 if (bssid_changed)
378 wpas_notify_bssid_changed(wpa_s);
379
380 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
381 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800382 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700383 int try_opportunistic;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700384 const u8 *cache_id = NULL;
385
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800386 try_opportunistic = (ssid->proactive_key_caching < 0 ?
387 wpa_s->conf->okc :
388 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700389 (ssid->proto & WPA_PROTO_RSN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700390#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 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700394 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
395 wpa_s->current_ssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700396 try_opportunistic, cache_id,
397 0) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800398 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700399 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)) {
403 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
404 "key management and encryption suites");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800405 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406 return;
407 }
Hai Shalom74f70d42019-02-11 14:42:39 -0800408#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 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700422 } 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;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800431 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432 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)) {
436 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
437 "key management and encryption suites (no "
438 "scan results)");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800439 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700440 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
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800461 /* 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700483#ifdef CONFIG_IEEE80211R
484 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
485 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
486 md = ie + 2;
487 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
Hai Shalom021b0b52019-04-10 11:17:58 -0700488 if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
489 !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
490 md = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700491 if (md) {
492 /* Prepare for the next transition */
493 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
494 }
495
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700496 if (md) {
497 wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
498 md[0], md[1]);
499
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700500 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);
510 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
511 wpa_s->sme.assoc_req_ie_len += 5;
512 }
513
Hai Shalom74f70d42019-02-11 14:42:39 -0800514 if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
516 wpa_sm_has_ptk(wpa_s->wpa)) {
517 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
518 "over-the-air");
519 params.auth_alg = WPA_AUTH_ALG_FT;
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
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800526 wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800527 if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700528 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
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)) {
533 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
534 "MFP: require MFP");
535 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
536 }
537 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700538
539#ifdef CONFIG_P2P
540 if (wpa_s->global->p2p) {
541 u8 *pos;
542 size_t len;
543 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700544 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;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800547 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
548 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549 if (res >= 0)
550 wpa_s->sme.assoc_req_ie_len += res;
551 }
552#endif /* CONFIG_P2P */
553
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800554#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
569 sme_auth_handle_rrm(wpa_s, bss);
570
Dmitry Shmidt29333592017-01-09 12:27:11 -0800571 wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
Hai Shalom74f70d42019-02-11 14:42:39 -0800572 wpa_s, ssid, bss->freq,
Dmitry Shmidt29333592017-01-09 12:27:11 -0800573 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);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800575
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700576 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
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800581 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
582 sizeof(ext_capab));
583 if (ext_capab_len > 0) {
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];
587 os_memmove(pos + ext_capab_len, pos,
588 wpa_s->sme.assoc_req_ie_len -
589 (pos - wpa_s->sme.assoc_req_ie));
590 wpa_s->sme.assoc_req_ie_len += ext_capab_len;
591 os_memcpy(pos, ext_capab, ext_capab_len);
592 }
593
Hai Shalomc3565922019-10-28 11:58:20 -0700594 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
Dmitry Shmidt04949592012-07-19 12:16:46 -0700602#ifdef CONFIG_HS20
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700603 if (is_hs20_network(wpa_s, ssid, bss)) {
Dmitry Shmidt04949592012-07-19 12:16:46 -0700604 struct wpabuf *hs20;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800605
Roshan Pius3a1667e2018-07-03 15:17:14 -0700606 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700607 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800608 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700609 size_t len;
610
Hai Shalom74f70d42019-02-11 14:42:39 -0800611 wpas_hs20_add_indication(hs20, pps_mo_id,
612 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -0700613 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700614 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 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700622 wpabuf_free(hs20);
623 }
624 }
625#endif /* CONFIG_HS20 */
626
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800627 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
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800647 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
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800661#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -0700662 mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -0700663 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800664 int len;
665
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) -
Hai Shalomce48b4a2018-09-05 11:41:35 -0700669 wpa_s->sme.assoc_req_ie_len,
670 !!mbo_attr_from_mbo_ie(mbo_ie,
671 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800672 if (len >= 0)
673 wpa_s->sme.assoc_req_ie_len += len;
674 }
675#endif /* CONFIG_MBO */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800676
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800677#ifdef CONFIG_SAE
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800678 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700679 pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0,
Hai Shalom021b0b52019-04-10 11:17:58 -0700680 NULL,
681 wpa_s->key_mgmt == WPA_KEY_MGMT_FT_SAE ?
682 WPA_KEY_MGMT_FT_SAE :
683 WPA_KEY_MGMT_SAE) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800684 wpa_dbg(wpa_s, MSG_DEBUG,
685 "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700686 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800687 params.auth_alg = WPA_AUTH_ALG_OPEN;
688 wpa_s->sme.sae_pmksa_caching = 1;
689 }
690
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800691 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800692 if (start)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800693 resp = sme_auth_build_sae_commit(wpa_s, ssid,
Hai Shalom021b0b52019-04-10 11:17:58 -0700694 bss->bssid, 0,
Hai Shalomc3565922019-10-28 11:58:20 -0700695 start == 2, NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800696 else
Roshan Pius3a1667e2018-07-03 15:17:14 -0700697 resp = sme_auth_build_sae_confirm(wpa_s, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800698 if (resp == NULL) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800699 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800700 return;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800701 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800702 params.auth_data = wpabuf_head(resp);
703 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800704 wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800705 }
706#endif /* CONFIG_SAE */
707
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800708 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)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700719 const u8 *indic;
720 u16 fils_info;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700721 const u8 *realm, *username, *rrk;
722 size_t realm_len, username_len, rrk_len;
723 u16 next_seq_num;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700724
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
Hai Shalomce48b4a2018-09-05 11:41:35 -0700753 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
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800766 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700767 ssid, 0,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700768 wpa_bss_get_fils_cache_id(bss),
769 0) == 0)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800770 wpa_printf(MSG_DEBUG,
771 "SME: Try to use FILS with PMKSA caching");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700772 resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800773 if (resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700774 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;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800786 params.auth_data = wpabuf_head(resp);
787 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700788 wpa_s->sme.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800789 }
790 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700791no_fils:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800792#endif /* CONFIG_FILS */
793
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800794 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700795 wpa_supplicant_cancel_scan(wpa_s);
796
797 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
798 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
799 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
800
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700801 eapol_sm_notify_portValid(wpa_s->eapol, FALSE);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700802 wpa_clear_keys(wpa_s, bss->bssid);
803 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700804 if (old_ssid != wpa_s->current_ssid)
805 wpas_notify_network_changed(wpa_s);
806
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700807#ifdef CONFIG_HS20
808 hs20_configure_frame_filters(wpa_s);
809#endif /* CONFIG_HS20 */
810
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700811#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
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800837 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700846 wpa_s->sme.auth_alg = params.auth_alg;
847 if (wpa_drv_authenticate(wpa_s, &params) < 0) {
848 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
849 "driver failed");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800850 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800851 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800852 wpabuf_free(resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800853 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700854 return;
855 }
856
857 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
858 NULL);
859
860 /*
861 * Association will be started based on the authentication event from
862 * the driver.
863 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800864
865 wpabuf_free(resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700866}
867
868
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800869static 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) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -0800875 if (work->started)
876 wpa_s->connect_work = NULL;
877
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800878 wpas_connect_work_free(cwork);
879 return;
880 }
881
882 wpa_s->connect_work = work;
883
Dmitry Shmidt2e425d62014-11-10 11:18:27 -0800884 if (cwork->bss_removed ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800885 !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
886 wpas_network_disabled(wpa_s, cwork->ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800887 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
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800892 /* 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);
Hai Shalomc3565922019-10-28 11:58:20 -0700895 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
896 wpa_s->rsnxe_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800897
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800898 sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
899}
900
901
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800902void sme_authenticate(struct wpa_supplicant *wpa_s,
903 struct wpa_bss *bss, struct wpa_ssid *ssid)
904{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800905 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
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800914 if (radio_work_pending(wpa_s, "sme-connect")) {
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700915 /*
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);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800923 }
924
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800925 wpas_abort_ongoing_scan(wpa_s);
926
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800927 cwork = os_zalloc(sizeof(*cwork));
928 if (cwork == NULL)
929 return;
930 cwork->bss = bss;
931 cwork->ssid = ssid;
932 cwork->sme = 1;
933
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800934#ifdef CONFIG_SAE
935 wpa_s->sme.sae.state = SAE_NOTHING;
936 wpa_s->sme.sae.send_confirm = 0;
Dmitry Shmidtcce06662013-11-04 18:44:24 -0800937 wpa_s->sme.sae_group_index = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800938#endif /* CONFIG_SAE */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800939
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);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800943}
944
945
946#ifdef CONFIG_SAE
947
Roshan Pius3a1667e2018-07-03 15:17:14 -0700948static int sme_external_auth_build_buf(struct wpabuf *buf,
949 struct wpabuf *params,
950 const u8 *sa, const u8 *da,
Hai Shalomc3565922019-10-28 11:58:20 -0700951 u16 auth_transaction, u16 seq_num,
952 u16 status_code)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700953{
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);
Hai Shalom74f70d42019-02-11 14:42:39 -0800964 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);
Hai Shalomc3565922019-10-28 11:58:20 -0700967 resp->u.auth.status_code = host_to_le16(status_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700968 if (params)
969 wpabuf_put_buf(buf, params);
970
971 return 0;
972}
973
974
Hai Shalom81f62d82019-07-22 12:10:00 -0700975static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
976 const u8 *bssid,
977 struct wpa_ssid *ssid)
Roshan Pius3a1667e2018-07-03 15:17:14 -0700978{
979 struct wpabuf *resp, *buf;
Hai Shalomc3565922019-10-28 11:58:20 -0700980 int use_pt;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700981
Hai Shalomc3565922019-10-28 11:58:20 -0700982 resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt);
Hai Shalom81f62d82019-07-22 12:10:00 -0700983 if (!resp) {
984 wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
985 return -1;
986 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700987
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);
Hai Shalom81f62d82019-07-22 12:10:00 -0700992 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700993 }
994
995 wpa_s->sme.seq_num++;
996 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Hai Shalomc3565922019-10-28 11:58:20 -0700997 bssid, 1, wpa_s->sme.seq_num,
998 use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT :
999 WLAN_STATUS_SUCCESS);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001000 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0);
1001 wpabuf_free(resp);
1002 wpabuf_free(buf);
Hai Shalom81f62d82019-07-22 12:10:00 -07001003
1004 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001005}
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;
Hai Shalom66904732019-05-29 11:54:04 -07001015 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;
Hai Shalomc3565922019-10-28 11:58:20 -07001018 if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
1019 params.pmkid = wpa_s->sme.sae.pmkid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001020 wpa_drv_send_external_auth_status(wpa_s, &params);
1021}
1022
1023
Hai Shalom81f62d82019-07-22 12:10:00 -07001024static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
1025 union wpa_event_data *data)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001026{
1027 struct wpa_ssid *ssid;
1028 size_t ssid_str_len = data->external_auth.ssid_len;
Hai Shalom5f92bc92019-04-18 11:54:11 -07001029 const u8 *ssid_str = data->external_auth.ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001030
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 &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001035 os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001036 (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001037 break;
1038 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001039 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;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001045}
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,
Hai Shalomc3565922019-10-28 11:58:20 -07001068 da, 2, wpa_s->sme.seq_num,
1069 WLAN_STATUS_SUCCESS);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001070 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) {
Hai Shalom66904732019-05-29 11:54:04 -07001084 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;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001091 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;
Hai Shalom81f62d82019-07-22 12:10:00 -07001095 if (sme_handle_external_auth_start(wpa_s, data) < 0)
1096 sme_send_external_auth_status(wpa_s,
1097 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001098 } 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
Hai Shalomc3565922019-10-28 11:58:20 -07001106static 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
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001152static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001153 u16 status_code, const u8 *data, size_t len,
1154 int external, const u8 *sa)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001155{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001156 int *groups;
1157
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001158 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
1159 "status code %u", auth_transaction, status_code);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001160
1161 if (auth_transaction == 1 &&
1162 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1163 wpa_s->sme.sae.state == SAE_COMMITTED &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001164 (external || wpa_s->current_bss) && wpa_s->current_ssid) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001165 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001166 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 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001188 wpabuf_free(wpa_s->sme.sae_token);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001189 wpa_s->sme.sae_token = wpabuf_alloc_copy(data + sizeof(le16),
1190 len - sizeof(le16));
Roshan Pius3a1667e2018-07-03 15:17:14 -07001191 if (!external)
1192 sme_send_authentication(wpa_s, wpa_s->current_bss,
Hai Shalom021b0b52019-04-10 11:17:58 -07001193 wpa_s->current_ssid, 2);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001194 else
1195 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001196 wpa_s, wpa_s->sme.ext_auth_bssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001197 wpa_s->current_ssid);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001198 return 0;
1199 }
1200
1201 if (auth_transaction == 1 &&
1202 status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1203 wpa_s->sme.sae.state == SAE_COMMITTED &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001204 (external || wpa_s->current_bss) && wpa_s->current_ssid) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001205 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
Hai Shalomc3565922019-10-28 11:58:20 -07001206 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1207 wpa_s->sme.sae.group);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001208 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");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001212 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(
Hai Shalom66904732019-05-29 11:54:04 -07001217 wpa_s, wpa_s->sme.ext_auth_bssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001218 wpa_s->current_ssid);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001219 return 0;
1220 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001221
Roshan Pius3a1667e2018-07-03 15:17:14 -07001222 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
Hai Shalomc3565922019-10-28 11:58:20 -07001232 if (status_code != WLAN_STATUS_SUCCESS &&
1233 status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001234 return -1;
1235
1236 if (auth_transaction == 1) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07001237 u16 res;
1238
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001239 groups = wpa_s->conf->sae_groups;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001240
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001241 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001242 if ((!external && wpa_s->current_bss == NULL) ||
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001243 wpa_s->current_ssid == NULL)
1244 return -1;
Hai Shalomc3565922019-10-28 11:58:20 -07001245 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 }
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001250 if (groups && groups[0] <= 0)
1251 groups = NULL;
Dmitry Shmidt41712582015-06-29 11:02:15 -07001252 res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
Hai Shalomc3565922019-10-28 11:58:20 -07001253 groups, status_code ==
1254 WLAN_STATUS_SAE_HASH_TO_ELEMENT);
Dmitry Shmidt41712582015-06-29 11:02:15 -07001255 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)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001261 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001262
Hai Shalomc3565922019-10-28 11:58:20 -07001263 if (wpa_s->sme.sae.tmp &&
1264 sme_check_sae_rejected_groups(
1265 wpa_s,
1266 wpa_s->sme.sae.tmp->peer_rejected_groups) < 0)
1267 return -1;
1268
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001269 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
1275 wpabuf_free(wpa_s->sme.sae_token);
1276 wpa_s->sme.sae_token = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001277 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);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001282 return 0;
1283 } else if (auth_transaction == 2) {
Hai Shalomc3565922019-10-28 11:58:20 -07001284 if (status_code != WLAN_STATUS_SUCCESS)
1285 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001286 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001287 if (wpa_s->sme.sae.state != SAE_CONFIRMED)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001288 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001289 if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001290 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001291 wpa_s->sme.sae.state = SAE_ACCEPTED;
1292 sae_clear_temp_data(&wpa_s->sme.sae);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001293
1294 if (external) {
1295 /* Report success to driver */
1296 sme_send_external_auth_status(wpa_s,
1297 WLAN_STATUS_SUCCESS);
1298 }
1299
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001300 return 1;
1301 }
1302
1303 return -1;
1304}
Roshan Pius3a1667e2018-07-03 15:17:14 -07001305
1306
Hai Shalomc3565922019-10-28 11:58:20 -07001307static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
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,
1312 wpa_s->sme.sae.pmkid, bssid);
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
Roshan Pius3a1667e2018-07-03 15:17:14 -07001338void 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
Hai Shalom74f70d42019-02-11 14:42:39 -08001354 if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001355 int res;
1356
Hai Shalom74f70d42019-02-11 14:42:39 -08001357 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);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001362 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
Hai Shalomc3565922019-10-28 11:58:20 -07001371 if (sme_sae_set_pmk(wpa_s, wpa_s->sme.ext_auth_bssid) < 0)
1372 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001373 }
1374}
1375
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001376#endif /* CONFIG_SAE */
1377
1378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001379void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
1380{
1381 struct wpa_ssid *ssid = wpa_s->current_ssid;
1382
1383 if (ssid == NULL) {
1384 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1385 "when network is not selected");
1386 return;
1387 }
1388
1389 if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
1390 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1391 "when not in authenticating state");
1392 return;
1393 }
1394
1395 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) {
1396 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
1397 "unexpected peer " MACSTR,
1398 MAC2STR(data->auth.peer));
1399 return;
1400 }
1401
1402 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001403 " auth_type=%d auth_transaction=%d status_code=%d",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001404 MAC2STR(data->auth.peer), data->auth.auth_type,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001405 data->auth.auth_transaction, data->auth.status_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001406 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
1407 data->auth.ies, data->auth.ies_len);
1408
1409 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
1410
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001411#ifdef CONFIG_SAE
1412 if (data->auth.auth_type == WLAN_AUTH_SAE) {
1413 int res;
1414 res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
1415 data->auth.status_code, data->auth.ies,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001416 data->auth.ies_len, 0, NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001417 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)
1423 return;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001424
Hai Shalomc3565922019-10-28 11:58:20 -07001425 if (sme_sae_set_pmk(wpa_s, wpa_s->pending_bssid) < 0)
1426 return;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001427 }
1428#endif /* CONFIG_SAE */
1429
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001430 if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001431 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
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001442 " auth_type=%u auth_transaction=%u status_code=%u%s%s",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001443 MAC2STR(data->auth.peer), data->auth.auth_type,
1444 data->auth.auth_transaction, data->auth.status_code,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001445 ie_txt ? " ie=" : "",
1446 ie_txt ? ie_txt : "");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001447 os_free(ie_txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001448
Hai Shalomce48b4a2018-09-05 11:41:35 -07001449#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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001455 if (data->auth.status_code !=
1456 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
1457 wpa_s->sme.auth_alg == data->auth.auth_type ||
1458 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
1459 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001460 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001461 return;
1462 }
1463
Dmitry Shmidt97672262014-02-03 13:02:54 -08001464 wpas_connect_work_done(wpa_s);
1465
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466 switch (data->auth.auth_type) {
1467 case WLAN_AUTH_OPEN:
1468 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
1469
1470 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
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
1478 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
1479 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
1480 wpa_s->current_ssid);
1481 return;
1482
1483 default:
1484 return;
1485 }
1486 }
1487
1488#ifdef CONFIG_IEEE80211R
1489 if (data->auth.auth_type == WLAN_AUTH_FT) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001490 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 }
Dmitry Shmidt41712582015-06-29 11:02:15 -07001497 if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
1498 data->auth.ies_len, 0,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001499 data->auth.peer,
1500 ric_ies, ric_ies_len) < 0) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07001501 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 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001512 }
1513#endif /* CONFIG_IEEE80211R */
1514
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001515#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001516 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
1537 if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
1538 data->auth.ies, data->auth.ies_len) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001539 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001553 sme_associate(wpa_s, ssid->mode, data->auth.peer,
1554 data->auth.auth_type);
1555}
1556
1557
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001558#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 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001572
1573
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001574void 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;
1578 struct ieee802_11_elems elems;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001579#ifdef CONFIG_FILS
1580 u8 nonces[2 * FILS_NONCE_LEN];
1581#endif /* CONFIG_FILS */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001582#ifdef CONFIG_HT_OVERRIDES
1583 struct ieee80211_ht_capabilities htcaps;
1584 struct ieee80211_ht_capabilities htcaps_mask;
1585#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001586#ifdef CONFIG_VHT_OVERRIDES
1587 struct ieee80211_vht_capabilities vhtcaps;
1588 struct ieee80211_vht_capabilities vhtcaps_mask;
1589#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001590
1591 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001592
1593#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001594 if (auth_type == WLAN_AUTH_FILS_SK ||
1595 auth_type == WLAN_AUTH_FILS_SK_PFS) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001596 struct wpabuf *buf;
1597 const u8 *snonce, *anonce;
Paul Stewart092955c2017-02-06 09:13:09 -08001598 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 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001619
1620 buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
1621 &params.fils_kek_len, &snonce,
Paul Stewart092955c2017-02-06 09:13:09 -08001622 &anonce,
1623 (const struct wpabuf **) hlp,
1624 num_hlp);
1625 for (i = 0; i < num_hlp; i++)
1626 wpabuf_free(hlp[i]);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001627 if (!buf)
1628 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001629 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 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001653 /* 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);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001665 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);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001668
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
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001676#ifdef CONFIG_OWE
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 */
1683 if (auth_type == WLAN_AUTH_OPEN &&
1684 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1685 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001686 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001687
Roshan Pius3a1667e2018-07-03 15:17:14 -07001688 if (wpa_s->current_ssid && wpa_s->current_ssid->owe_group) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001689 group = wpa_s->current_ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08001690 } else if (wpa_s->assoc_status_code ==
1691 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001692 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;
Hai Shalom74f70d42019-02-11 14:42:39 -08001698 } else {
1699 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001700 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001701
Roshan Pius3a1667e2018-07-03 15:17:14 -07001702 wpa_s->last_owe_group = group;
1703 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001704 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
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
Hai Shalom021b0b52019-04-10 11:17:58 -07001724#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
Hai Shalom74f70d42019-02-11 14:42:39 -08001754 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001770 params.bssid = bssid;
1771 params.ssid = wpa_s->sme.ssid;
1772 params.ssid_len = wpa_s->sme.ssid_len;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001773 params.freq.freq = wpa_s->sme.freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001774 params.bg_scan_period = wpa_s->current_ssid ?
1775 wpa_s->current_ssid->bg_scan_period : -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001776 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;
Hai Shalom74f70d42019-02-11 14:42:39 -08001779 wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
1780 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001781 params.pairwise_suite = wpa_s->pairwise_cipher;
1782 params.group_suite = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001783 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
Dmitry Shmidt15907092014-03-25 10:42:57 -07001784 params.key_mgmt_suite = wpa_s->key_mgmt;
1785 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001786#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 */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001793#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 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001800#ifdef CONFIG_IEEE80211R
Hai Shalom74f70d42019-02-11 14:42:39 -08001801 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");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001812 params.wpa_ie = wpa_s->sme.ft_ies;
1813 params.wpa_ie_len = wpa_s->sme.ft_ies_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08001814 } 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);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001880 }
1881#endif /* CONFIG_IEEE80211R */
1882 params.mode = mode;
1883 params.mgmt_frame_protection = wpa_s->sme.mfp;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001884 params.rrm_used = wpa_s->rrm.rrm_used;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885 if (wpa_s->sme.prev_bssid_set)
1886 params.prev_bssid = wpa_s->sme.prev_bssid;
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) : "",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001891 params.freq.freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001892
1893 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
1894
1895 if (params.wpa_ie == NULL ||
1896 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
1897 < 0) {
1898 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
1899 os_memset(&elems, 0, sizeof(elems));
1900 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001901 if (elems.rsn_ie) {
1902 params.wpa_proto = WPA_PROTO_RSN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001903 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
1904 elems.rsn_ie_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001905 } else if (elems.wpa_ie) {
1906 params.wpa_proto = WPA_PROTO_WPA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001907 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
1908 elems.wpa_ie_len + 2);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08001909 } 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);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001913 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001914 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07001915 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);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001920 if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001921 params.p2p = 1;
1922
Dmitry Shmidt9c175262016-03-03 10:20:07 -08001923 if (wpa_s->p2pdev->set_sta_uapsd)
1924 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001925 else
1926 params.uapsd = -1;
1927
1928 if (wpa_drv_associate(wpa_s, &params) < 0) {
1929 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
1930 "driver failed");
1931 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001932 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001933 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1934 return;
1935 }
1936
1937 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
1938 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001939
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 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001947}
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) {
1954 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
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);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001965 wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001966 if (wpa_s->sme.ft_ies == NULL)
1967 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968 wpa_s->sme.ft_ies_len = ies_len;
1969 return 0;
1970}
1971
1972
1973static void sme_deauth(struct wpa_supplicant *wpa_s)
1974{
1975 int bssid_changed;
1976
1977 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1978
1979 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
1980 WLAN_REASON_DEAUTH_LEAVING) < 0) {
1981 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
1982 "failed");
1983 }
1984 wpa_s->sme.prev_bssid_set = 0;
1985
1986 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1987 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1988 os_memset(wpa_s->bssid, 0, ETH_ALEN);
1989 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
1990 if (bssid_changed)
1991 wpas_notify_bssid_changed(wpa_s);
1992}
1993
1994
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
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002004#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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002025 /*
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
2036void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
2037 union wpa_event_data *data)
2038{
2039 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
2040 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002041 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042}
2043
2044
2045void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
2046 union wpa_event_data *data)
2047{
2048 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
2049 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2050 wpa_supplicant_mark_disassoc(wpa_s);
2051}
2052
2053
2054void sme_event_disassoc(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002055 struct disassoc_info *info)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002056{
2057 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002058 if (wpa_s->sme.prev_bssid_set) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002059 /*
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 */
2065 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
2066 "driver state");
2067 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
2068 WLAN_REASON_DEAUTH_LEAVING);
2069 }
2070}
2071
2072
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
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002125void 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
Roshan Pius3a1667e2018-07-03 15:17:14 -07002134 if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002135 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
2136#endif /* CONFIG_IEEE80211R */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002137 sme_stop_sa_query(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002138}
2139
2140
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002141void sme_deinit(struct wpa_supplicant *wpa_s)
2142{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002143 sme_clear_on_disassoc(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002144#ifdef CONFIG_SAE
2145 os_free(wpa_s->sme.sae_rejected_groups);
2146 wpa_s->sme.sae_rejected_groups = NULL;
2147#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002148
2149 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2150 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002151 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
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002163 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);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002168
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
Dmitry Shmidt04949592012-07-19 12:16:46 -07002205int 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 */
Dmitry Shmidt4b060592013-04-29 16:42:49 -07002241 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)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002245 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;
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002249 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);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002252
2253 if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002254 if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
2255 num_intol++;
2256
Dmitry Shmidt04949592012-07-19 12:16:46 -07002257 /* 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
Dmitry Shmidt04949592012-07-19 12:16:46 -07002265 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
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002274static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
2275 struct wpa_driver_scan_params *params)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002276{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002277 /* Include only affected channels */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002278 struct hostapd_hw_modes *mode;
2279 int count, i;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002280 int start, end;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002281
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002282 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
2283 HOSTAPD_MODE_IEEE80211G);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002284 if (mode == NULL) {
2285 /* No channels supported in this band - use empty list */
2286 params->freqs = os_zalloc(sizeof(int));
2287 return;
2288 }
2289
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002290 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
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002328 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
Dmitry Shmidt04949592012-07-19 12:16:46 -07002329 if (params->freqs == NULL)
2330 return;
2331 for (count = 0, i = 0; i < mode->num_channels; i++) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002332 int freq;
2333
Dmitry Shmidt04949592012-07-19 12:16:46 -07002334 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
2335 continue;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002336 freq = mode->channels[i].freq;
2337 if (freq - 10 >= end || freq + 10 <= start)
2338 continue; /* not affected */
2339 params->freqs[count++] = freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002340 }
2341}
2342
2343
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));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002355 wpa_obss_scan_freqs_list(wpa_s, &params);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07002356 params.low_priority = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002357 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;
2363 os_free(params.freqs);
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;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002375 struct hostapd_hw_modes *hw_mode = NULL;
2376 int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002377
2378 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
2379 wpa_s->sme.sched_obss_scan = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002380 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002381 if (!enable)
2382 return;
2383
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002384 /*
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)) ||
Hai Shalom81f62d82019-07-22 12:10:00 -07002390 ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002391 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002392
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002393 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;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002407
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);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433}
2434
2435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436static const unsigned int sa_query_max_timeout = 1000;
2437static const unsigned int sa_query_retry_timeout = 201;
Hai Shalom74f70d42019-02-11 14:42:39 -08002438static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439
2440static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
2441{
2442 u32 tu;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002443 struct os_reltime now, passed;
2444 os_get_reltime(&now);
2445 os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002446 tu = (passed.sec * 1000000 + passed.usec) / 1024;
2447 if (sa_query_max_timeout < tu) {
2448 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
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{
Hai Shalom74f70d42019-02-11 14:42:39 -08002462 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
2466 MACSTR, MAC2STR(wpa_s->bssid));
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);
Hai Shalom74f70d42019-02-11 14:42:39 -08002472
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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002490 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
2491 wpa_s->own_addr, wpa_s->bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08002492 req, req_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
2494 "Request");
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
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002508 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);
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002511 if (nbuf == NULL) {
2512 sme_stop_sa_query(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 return;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002514 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 if (wpa_s->sme.sa_query_count == 0) {
2516 /* Starting a new SA Query procedure */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002517 os_get_reltime(&wpa_s->sme.sa_query_start);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 }
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
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002523 if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
2524 wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002525 sme_stop_sa_query(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002526 return;
2527 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002528
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
2534 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
2535 wpa_s->sme.sa_query_count);
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
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002547static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548{
Hai Shalom5f92bc92019-04-18 11:54:11 -07002549 if (wpa_s->sme.sa_query_trans_id)
2550 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 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;
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002562 struct os_reltime now;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002563
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564 if (wpa_s->wpa_state != WPA_COMPLETED)
2565 return;
2566 ssid = wpa_s->current_ssid;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002567 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002568 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
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002577 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
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002583 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
2584 "possible AP/STA state mismatch - trigger SA Query");
2585 sme_start_sa_query(wpa_s);
2586}
2587
2588
Hai Shalom74f70d42019-02-11 14:42:39 -08002589void 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
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)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651{
2652 int i;
2653
Hai Shalom74f70d42019-02-11 14:42:39 -08002654 if (!wpa_s->sme.sa_query_trans_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002655 return;
Hai Shalom74f70d42019-02-11 14:42:39 -08002656
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
2658 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
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) {
2671 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
2672 "transaction identifier found");
2673 return;
2674 }
2675
2676 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
2677 "from " MACSTR, MAC2STR(sa));
2678 sme_stop_sa_query(wpa_s);
2679}
2680
Hai Shalom74f70d42019-02-11 14:42:39 -08002681
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}