blob: 5a771e85f6b53c182228b1d29f848237c9620146 [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"
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -080016#include "common/hw_features_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070017#include "eapol_supp/eapol_supp_sm.h"
18#include "common/wpa_common.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080019#include "common/sae.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070020#include "common/dpp.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070021#include "rsn_supp/wpa.h"
22#include "rsn_supp/pmksa_cache.h"
23#include "config.h"
24#include "wpa_supplicant_i.h"
25#include "driver_i.h"
26#include "wpas_glue.h"
27#include "wps_supplicant.h"
28#include "p2p_supplicant.h"
29#include "notify.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "bss.h"
31#include "scan.h"
32#include "sme.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070033#include "hs20_supplicant.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034
35#define SME_AUTH_TIMEOUT 5
36#define SME_ASSOC_TIMEOUT 5
37
38static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
39static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt04949592012-07-19 12:16:46 -070040static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070041static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070042
43
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080044#ifdef CONFIG_SAE
45
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080046static int index_within_array(const int *array, int idx)
47{
48 int i;
49 for (i = 0; i < idx; i++) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -080050 if (array[i] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080051 return 0;
52 }
53 return 1;
54}
55
56
57static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
58{
59 int *groups = wpa_s->conf->sae_groups;
Hai Shalom021b0b52019-04-10 11:17:58 -070060 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080061
Dmitry Shmidtcce06662013-11-04 18:44:24 -080062 if (!groups || groups[0] <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080063 groups = default_groups;
64
65 /* Configuration may have changed, so validate current index */
66 if (!index_within_array(groups, wpa_s->sme.sae_group_index))
67 return -1;
68
69 for (;;) {
70 int group = groups[wpa_s->sme.sae_group_index];
Dmitry Shmidt41712582015-06-29 11:02:15 -070071 if (group <= 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080072 break;
73 if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
74 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
75 wpa_s->sme.sae.group);
Hai Shalom74f70d42019-02-11 14:42:39 -080076 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080077 }
78 wpa_s->sme.sae_group_index++;
79 }
80
81 return -1;
82}
83
84
85static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
86 struct wpa_ssid *ssid,
Hai Shalom021b0b52019-04-10 11:17:58 -070087 const u8 *bssid, int external,
Hai Shalom899fcc72020-10-19 14:38:18 -070088 int reuse, int *ret_use_pt,
89 bool *ret_use_pk)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080090{
91 struct wpabuf *buf;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080092 size_t len;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070093 const char *password;
Hai Shalomc3565922019-10-28 11:58:20 -070094 struct wpa_bss *bss;
95 int use_pt = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -070096 bool use_pk = false;
97 u8 rsnxe_capa = 0;
Hai Shalomc3565922019-10-28 11:58:20 -070098
99 if (ret_use_pt)
100 *ret_use_pt = 0;
Hai Shalom899fcc72020-10-19 14:38:18 -0700101 if (ret_use_pk)
102 *ret_use_pk = false;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800103
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700104#ifdef CONFIG_TESTING_OPTIONS
105 if (wpa_s->sae_commit_override) {
106 wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
107 buf = wpabuf_alloc(4 + wpabuf_len(wpa_s->sae_commit_override));
108 if (!buf)
109 return NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -0700110 if (!external) {
111 wpabuf_put_le16(buf, 1); /* Transaction seq# */
112 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
113 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700114 wpabuf_put_buf(buf, wpa_s->sae_commit_override);
115 return buf;
116 }
117#endif /* CONFIG_TESTING_OPTIONS */
118
119 password = ssid->sae_password;
120 if (!password)
121 password = ssid->passphrase;
122 if (!password) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800123 wpa_printf(MSG_DEBUG, "SAE: No password available");
124 return NULL;
125 }
126
Hai Shalom021b0b52019-04-10 11:17:58 -0700127 if (reuse && wpa_s->sme.sae.tmp &&
128 os_memcmp(bssid, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) {
129 wpa_printf(MSG_DEBUG,
130 "SAE: Reuse previously generated PWE on a retry with the same AP");
Hai Shalom899fcc72020-10-19 14:38:18 -0700131 use_pt = wpa_s->sme.sae.h2e;
132 use_pk = wpa_s->sme.sae.pk;
Hai Shalom021b0b52019-04-10 11:17:58 -0700133 goto reuse_data;
134 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800135 if (sme_set_sae_group(wpa_s) < 0) {
136 wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
137 return NULL;
138 }
139
Hai Shalom899fcc72020-10-19 14:38:18 -0700140 bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
141 if (bss) {
142 const u8 *rsnxe;
143
144 rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
145 if (rsnxe && rsnxe[1] >= 1)
146 rsnxe_capa = rsnxe[2];
147 }
148
Hai Shalomfdcde762020-04-02 11:19:20 -0700149 if (ssid->sae_password_id && wpa_s->conf->sae_pwe != 3)
150 use_pt = 1;
Hai Shalom899fcc72020-10-19 14:38:18 -0700151#ifdef CONFIG_SAE_PK
152 if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
153 ssid->sae_pk != SAE_PK_MODE_DISABLED &&
154 ((ssid->sae_password &&
155 sae_pk_valid_password(ssid->sae_password)) ||
156 (!ssid->sae_password && ssid->passphrase &&
157 sae_pk_valid_password(ssid->passphrase)))) {
158 use_pt = 1;
159 use_pk = true;
160 }
161
162 if (ssid->sae_pk == SAE_PK_MODE_ONLY && !use_pk) {
163 wpa_printf(MSG_DEBUG,
164 "SAE: Cannot use PK with the selected AP");
165 return NULL;
166 }
167#endif /* CONFIG_SAE_PK */
Hai Shalomfdcde762020-04-02 11:19:20 -0700168
169 if (use_pt || wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700170 use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
Hai Shalomc3565922019-10-28 11:58:20 -0700171
Hai Shalomfdcde762020-04-02 11:19:20 -0700172 if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) &&
173 wpa_s->conf->sae_pwe != 3 &&
174 !use_pt) {
Hai Shalomc3565922019-10-28 11:58:20 -0700175 wpa_printf(MSG_DEBUG,
176 "SAE: Cannot use H2E with the selected AP");
177 return NULL;
178 }
179 }
180
181 if (use_pt &&
182 sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt,
183 wpa_s->own_addr, bssid,
Hai Shalom899fcc72020-10-19 14:38:18 -0700184 wpa_s->sme.sae_rejected_groups, NULL) < 0)
Hai Shalomc3565922019-10-28 11:58:20 -0700185 return NULL;
186 if (!use_pt &&
187 sae_prepare_commit(wpa_s->own_addr, bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700188 (u8 *) password, os_strlen(password),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700189 ssid->sae_password_id,
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800190 &wpa_s->sme.sae) < 0) {
191 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
192 return NULL;
193 }
Hai Shalom899fcc72020-10-19 14:38:18 -0700194 if (wpa_s->sme.sae.tmp) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700195 os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN);
Hai Shalom899fcc72020-10-19 14:38:18 -0700196 if (use_pt && use_pk)
197 wpa_s->sme.sae.pk = 1;
198#ifdef CONFIG_SAE_PK
199 os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr,
200 ETH_ALEN);
201 os_memcpy(wpa_s->sme.sae.tmp->peer_addr, bssid, ETH_ALEN);
202 sae_pk_set_password(&wpa_s->sme.sae, password);
203#endif /* CONFIG_SAE_PK */
204 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800205
Hai Shalom021b0b52019-04-10 11:17:58 -0700206reuse_data:
Hai Shalomfdcde762020-04-02 11:19:20 -0700207 len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700208 if (ssid->sae_password_id)
209 len += 4 + os_strlen(ssid->sae_password_id);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800210 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800211 if (buf == NULL)
212 return NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700213 if (!external) {
214 wpabuf_put_le16(buf, 1); /* Transaction seq# */
Hai Shalom899fcc72020-10-19 14:38:18 -0700215 if (use_pk)
216 wpabuf_put_le16(buf, WLAN_STATUS_SAE_PK);
217 else if (use_pt)
218 wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
219 else
220 wpabuf_put_le16(buf,WLAN_STATUS_SUCCESS);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700221 }
Hai Shalomfdcde762020-04-02 11:19:20 -0700222 if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
223 ssid->sae_password_id) < 0) {
224 wpabuf_free(buf);
225 return NULL;
226 }
Hai Shalomc3565922019-10-28 11:58:20 -0700227 if (ret_use_pt)
228 *ret_use_pt = use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -0700229 if (ret_use_pk)
230 *ret_use_pk = use_pk;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800231
232 return buf;
233}
234
235
Roshan Pius3a1667e2018-07-03 15:17:14 -0700236static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s,
237 int external)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800238{
239 struct wpabuf *buf;
240
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800241 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800242 if (buf == NULL)
243 return NULL;
244
Roshan Pius3a1667e2018-07-03 15:17:14 -0700245 if (!external) {
246 wpabuf_put_le16(buf, 2); /* Transaction seq# */
247 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
248 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800249 sae_write_confirm(&wpa_s->sme.sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800250
251 return buf;
252}
253
254#endif /* CONFIG_SAE */
255
256
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800257/**
258 * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt
259 * @wpa_s: Pointer to wpa_supplicant data
260 * @bss: Pointer to the bss which is the target of authentication attempt
261 */
262static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
263 struct wpa_bss *bss)
264{
265 const u8 rrm_ie_len = 5;
266 u8 *pos;
267 const u8 *rrm_ie;
268
269 wpa_s->rrm.rrm_used = 0;
270
271 wpa_printf(MSG_DEBUG,
272 "RRM: Determining whether RRM can be used - device support: 0x%x",
273 wpa_s->drv_rrm_flags);
274
275 rrm_ie = wpa_bss_get_ie(bss, WLAN_EID_RRM_ENABLED_CAPABILITIES);
276 if (!rrm_ie || !(bss->caps & IEEE80211_CAP_RRM)) {
277 wpa_printf(MSG_DEBUG, "RRM: No RRM in network");
278 return;
279 }
280
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700281 if (!((wpa_s->drv_rrm_flags &
282 WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
283 (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
284 !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800285 wpa_printf(MSG_DEBUG,
286 "RRM: Insufficient RRM support in driver - do not use RRM");
287 return;
288 }
289
290 if (sizeof(wpa_s->sme.assoc_req_ie) <
291 wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) {
292 wpa_printf(MSG_INFO,
293 "RRM: Unable to use RRM, no room for RRM IE");
294 return;
295 }
296
297 wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to Association Request");
298 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
299 os_memset(pos, 0, 2 + rrm_ie_len);
300 *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
301 *pos++ = rrm_ie_len;
302
Hai Shalom60840252021-02-19 19:02:11 -0800303 /* Set supported capabilities flags */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800304 if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
305 *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
306
Dmitry Shmidt29333592017-01-09 12:27:11 -0800307 *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
308 WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
309 WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
310
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700311 if (wpa_s->lci)
312 pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
313
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800314 wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
315 wpa_s->rrm.rrm_used = 1;
316}
317
318
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800319static void sme_send_authentication(struct wpa_supplicant *wpa_s,
320 struct wpa_bss *bss, struct wpa_ssid *ssid,
321 int start)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700322{
323 struct wpa_driver_auth_params params;
324 struct wpa_ssid *old_ssid;
325#ifdef CONFIG_IEEE80211R
326 const u8 *ie;
327#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700328#if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700329 const u8 *md = NULL;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700330#endif /* CONFIG_IEEE80211R || CONFIG_FILS */
Hai Shalomfdcde762020-04-02 11:19:20 -0700331 int bssid_changed;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800332 struct wpabuf *resp = NULL;
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700333 u8 ext_capab[18];
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800334 int ext_capab_len;
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800335 int skip_auth;
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800336 u8 *wpa_ie;
337 size_t wpa_ie_len;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700338#ifdef CONFIG_MBO
339 const u8 *mbo_ie;
340#endif /* CONFIG_MBO */
Hai Shalomfdcde762020-04-02 11:19:20 -0700341 int omit_rsnxe = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700342
343 if (bss == NULL) {
344 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
345 "the network");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800346 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700347 return;
348 }
349
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800350 skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
351 wpa_s->reassoc_same_bss;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700352 wpa_s->current_bss = bss;
353
354 os_memset(&params, 0, sizeof(params));
355 wpa_s->reassociate = 0;
356
357 params.freq = bss->freq;
358 params.bssid = bss->bssid;
359 params.ssid = bss->ssid;
360 params.ssid_len = bss->ssid_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800361 params.p2p = ssid->p2p_group;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700362
363 if (wpa_s->sme.ssid_len != params.ssid_len ||
364 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
365 wpa_s->sme.prev_bssid_set = 0;
366
367 wpa_s->sme.freq = params.freq;
368 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
369 wpa_s->sme.ssid_len = params.ssid_len;
370
371 params.auth_alg = WPA_AUTH_ALG_OPEN;
372#ifdef IEEE8021X_EAPOL
373 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
374 if (ssid->leap) {
375 if (ssid->non_leap == 0)
376 params.auth_alg = WPA_AUTH_ALG_LEAP;
377 else
378 params.auth_alg |= WPA_AUTH_ALG_LEAP;
379 }
380 }
381#endif /* IEEE8021X_EAPOL */
382 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
383 params.auth_alg);
384 if (ssid->auth_alg) {
385 params.auth_alg = ssid->auth_alg;
386 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
387 "0x%x", params.auth_alg);
388 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800389#ifdef CONFIG_SAE
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800390 wpa_s->sme.sae_pmksa_caching = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800391 if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
392 const u8 *rsn;
393 struct wpa_ie_data ied;
394
395 rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800396 if (!rsn) {
397 wpa_dbg(wpa_s, MSG_DEBUG,
398 "SAE enabled, but target BSS does not advertise RSN");
Hai Shalom021b0b52019-04-10 11:17:58 -0700399#ifdef CONFIG_DPP
400 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
401 (ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
402 (ied.key_mgmt & WPA_KEY_MGMT_DPP)) {
403 wpa_dbg(wpa_s, MSG_DEBUG, "Prefer DPP over SAE when both are enabled");
404#endif /* CONFIG_DPP */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800405 } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
406 wpa_key_mgmt_sae(ied.key_mgmt)) {
407 wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
408 params.auth_alg = WPA_AUTH_ALG_SAE;
409 } else {
410 wpa_dbg(wpa_s, MSG_DEBUG,
411 "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800412 }
413 }
414#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415
Hai Shalomfdcde762020-04-02 11:19:20 -0700416#ifdef CONFIG_WEP
417 {
418 int i;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700419
Hai Shalomfdcde762020-04-02 11:19:20 -0700420 for (i = 0; i < NUM_WEP_KEYS; i++) {
421 if (ssid->wep_key_len[i])
422 params.wep_key[i] = ssid->wep_key[i];
423 params.wep_key_len[i] = ssid->wep_key_len[i];
424 }
425 params.wep_tx_keyidx = ssid->wep_tx_keyidx;
426 }
427#endif /* CONFIG_WEP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700428
429 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
430 wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800431 wpa_key_mgmt_wpa(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700432 int try_opportunistic;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700433 const u8 *cache_id = NULL;
434
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800435 try_opportunistic = (ssid->proactive_key_caching < 0 ?
436 wpa_s->conf->okc :
437 ssid->proactive_key_caching) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700438 (ssid->proto & WPA_PROTO_RSN);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700439#ifdef CONFIG_FILS
440 if (wpa_key_mgmt_fils(ssid->key_mgmt))
441 cache_id = wpa_bss_get_fils_cache_id(bss);
442#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700443 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
444 wpa_s->current_ssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700445 try_opportunistic, cache_id,
446 0) == 0)
Dmitry Shmidt216983b2015-02-06 10:50:36 -0800447 eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700448 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
449 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
450 wpa_s->sme.assoc_req_ie,
451 &wpa_s->sme.assoc_req_ie_len)) {
452 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
453 "key management and encryption suites");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800454 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700455 return;
456 }
Hai Shalom74f70d42019-02-11 14:42:39 -0800457#ifdef CONFIG_HS20
458 } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
459 (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
460 /* No PMKSA caching, but otherwise similar to RSN/WPA */
461 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
462 if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
463 wpa_s->sme.assoc_req_ie,
464 &wpa_s->sme.assoc_req_ie_len)) {
465 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
466 "key management and encryption suites");
467 wpas_connect_work_done(wpa_s);
468 return;
469 }
470#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700471 } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
472 wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
473 /*
474 * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
475 * use non-WPA since the scan results did not indicate that the
476 * AP is using WPA or WPA2.
477 */
478 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
479 wpa_s->sme.assoc_req_ie_len = 0;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800480 } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700481 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
482 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
483 wpa_s->sme.assoc_req_ie,
484 &wpa_s->sme.assoc_req_ie_len)) {
485 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
486 "key management and encryption suites (no "
487 "scan results)");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800488 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700489 return;
490 }
491#ifdef CONFIG_WPS
492 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
493 struct wpabuf *wps_ie;
494 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
495 if (wps_ie && wpabuf_len(wps_ie) <=
496 sizeof(wpa_s->sme.assoc_req_ie)) {
497 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
498 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
499 wpa_s->sme.assoc_req_ie_len);
500 } else
501 wpa_s->sme.assoc_req_ie_len = 0;
502 wpabuf_free(wps_ie);
503 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
504#endif /* CONFIG_WPS */
505 } else {
506 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
507 wpa_s->sme.assoc_req_ie_len = 0;
508 }
509
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800510 /* In case the WPA vendor IE is used, it should be placed after all the
511 * non-vendor IEs, as the lower layer expects the IEs to be ordered as
512 * defined in the standard. Store the WPA IE so it can later be
513 * inserted at the correct location.
514 */
515 wpa_ie = NULL;
516 wpa_ie_len = 0;
517 if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
518 wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
519 wpa_s->sme.assoc_req_ie_len);
520 if (wpa_ie) {
521 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
522
523 wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
524 wpa_s->sme.assoc_req_ie_len = 0;
525 } else {
526 wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
527 wpas_connect_work_done(wpa_s);
528 return;
529 }
530 }
531
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700532#ifdef CONFIG_IEEE80211R
533 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
534 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
535 md = ie + 2;
536 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
Hai Shalom021b0b52019-04-10 11:17:58 -0700537 if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
538 !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
539 md = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700540 if (md) {
541 /* Prepare for the next transition */
542 wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
543 }
544
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700545 if (md) {
546 wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
547 md[0], md[1]);
548
Hai Shalomfdcde762020-04-02 11:19:20 -0700549 omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700550 if (wpa_s->sme.assoc_req_ie_len + 5 <
551 sizeof(wpa_s->sme.assoc_req_ie)) {
552 struct rsn_mdie *mdie;
553 u8 *pos = wpa_s->sme.assoc_req_ie +
554 wpa_s->sme.assoc_req_ie_len;
555 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
556 *pos++ = sizeof(*mdie);
557 mdie = (struct rsn_mdie *) pos;
558 os_memcpy(mdie->mobility_domain, md,
559 MOBILITY_DOMAIN_ID_LEN);
560 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
561 wpa_s->sme.assoc_req_ie_len += 5;
562 }
563
Hai Shalom74f70d42019-02-11 14:42:39 -0800564 if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700565 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
566 wpa_sm_has_ptk(wpa_s->wpa)) {
567 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
568 "over-the-air");
569 params.auth_alg = WPA_AUTH_ALG_FT;
570 params.ie = wpa_s->sme.ft_ies;
571 params.ie_len = wpa_s->sme.ft_ies_len;
572 }
573 }
574#endif /* CONFIG_IEEE80211R */
575
Dmitry Shmidt807291d2015-01-27 13:40:23 -0800576 wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800577 if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700578 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
579 struct wpa_ie_data _ie;
580 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
581 _ie.capabilities &
582 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
583 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
584 "MFP: require MFP");
585 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
586 }
587 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700588
589#ifdef CONFIG_P2P
590 if (wpa_s->global->p2p) {
591 u8 *pos;
592 size_t len;
593 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700594 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
595 len = sizeof(wpa_s->sme.assoc_req_ie) -
596 wpa_s->sme.assoc_req_ie_len;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800597 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
598 ssid->p2p_group);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700599 if (res >= 0)
600 wpa_s->sme.assoc_req_ie_len += res;
601 }
602#endif /* CONFIG_P2P */
603
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800604#ifdef CONFIG_FST
605 if (wpa_s->fst_ies) {
606 int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
607
608 if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <=
609 sizeof(wpa_s->sme.assoc_req_ie)) {
610 os_memcpy(wpa_s->sme.assoc_req_ie +
611 wpa_s->sme.assoc_req_ie_len,
612 wpabuf_head(wpa_s->fst_ies),
613 fst_ies_len);
614 wpa_s->sme.assoc_req_ie_len += fst_ies_len;
615 }
616 }
617#endif /* CONFIG_FST */
618
619 sme_auth_handle_rrm(wpa_s, bss);
620
Dmitry Shmidt29333592017-01-09 12:27:11 -0800621 wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
Hai Shalomfdcde762020-04-02 11:19:20 -0700622 wpa_s, ssid, bss,
Dmitry Shmidt29333592017-01-09 12:27:11 -0800623 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
624 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800625
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700626 if (params.p2p)
627 wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
628 else
629 wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
630
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800631 ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
632 sizeof(ext_capab));
633 if (ext_capab_len > 0) {
634 u8 *pos = wpa_s->sme.assoc_req_ie;
635 if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
636 pos += 2 + pos[1];
637 os_memmove(pos + ext_capab_len, pos,
638 wpa_s->sme.assoc_req_ie_len -
639 (pos - wpa_s->sme.assoc_req_ie));
640 wpa_s->sme.assoc_req_ie_len += ext_capab_len;
641 os_memcpy(pos, ext_capab, ext_capab_len);
642 }
643
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800644#ifdef CONFIG_TESTING_OPTIONS
645 if (wpa_s->rsnxe_override_assoc &&
646 wpabuf_len(wpa_s->rsnxe_override_assoc) <=
647 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
648 wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
649 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
650 wpabuf_head(wpa_s->rsnxe_override_assoc),
651 wpabuf_len(wpa_s->rsnxe_override_assoc));
652 wpa_s->sme.assoc_req_ie_len +=
653 wpabuf_len(wpa_s->rsnxe_override_assoc);
654 } else
655#endif /* CONFIG_TESTING_OPTIONS */
Hai Shalomc3565922019-10-28 11:58:20 -0700656 if (wpa_s->rsnxe_len > 0 &&
657 wpa_s->rsnxe_len <=
Hai Shalomfdcde762020-04-02 11:19:20 -0700658 sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len &&
659 !omit_rsnxe) {
Hai Shalomc3565922019-10-28 11:58:20 -0700660 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
661 wpa_s->rsnxe, wpa_s->rsnxe_len);
662 wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
663 }
664
Dmitry Shmidt04949592012-07-19 12:16:46 -0700665#ifdef CONFIG_HS20
Hai Shalomcded4e22022-01-28 15:29:52 -0800666 if (is_hs20_network(wpa_s, ssid, bss)
667#ifndef ANDROID /* Android does not use the native HS 2.0 config */
668 && is_hs20_config(wpa_s)
669#endif /* ANDROID */
670 ) {
Dmitry Shmidt04949592012-07-19 12:16:46 -0700671 struct wpabuf *hs20;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800672
Roshan Pius3a1667e2018-07-03 15:17:14 -0700673 hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700674 if (hs20) {
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800675 int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700676 size_t len;
677
Hai Shalom74f70d42019-02-11 14:42:39 -0800678 wpas_hs20_add_indication(hs20, pps_mo_id,
679 get_hs20_version(bss));
Roshan Pius3a1667e2018-07-03 15:17:14 -0700680 wpas_hs20_add_roam_cons_sel(hs20, ssid);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700681 len = sizeof(wpa_s->sme.assoc_req_ie) -
682 wpa_s->sme.assoc_req_ie_len;
683 if (wpabuf_len(hs20) <= len) {
684 os_memcpy(wpa_s->sme.assoc_req_ie +
685 wpa_s->sme.assoc_req_ie_len,
686 wpabuf_head(hs20), wpabuf_len(hs20));
687 wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
688 }
Dmitry Shmidt04949592012-07-19 12:16:46 -0700689 wpabuf_free(hs20);
690 }
691 }
692#endif /* CONFIG_HS20 */
693
Hai Shalom39ba6fc2019-01-22 12:40:38 -0800694 if (wpa_ie) {
695 size_t len;
696
697 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
698
699 len = sizeof(wpa_s->sme.assoc_req_ie) -
700 wpa_s->sme.assoc_req_ie_len;
701
702 if (len > wpa_ie_len) {
703 os_memcpy(wpa_s->sme.assoc_req_ie +
704 wpa_s->sme.assoc_req_ie_len,
705 wpa_ie, wpa_ie_len);
706 wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
707 } else {
708 wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
709 }
710
711 os_free(wpa_ie);
712 }
713
Dmitry Shmidt2f74e362015-01-21 13:19:05 -0800714 if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
715 struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
716 size_t len;
717
718 len = sizeof(wpa_s->sme.assoc_req_ie) -
719 wpa_s->sme.assoc_req_ie_len;
720 if (wpabuf_len(buf) <= len) {
721 os_memcpy(wpa_s->sme.assoc_req_ie +
722 wpa_s->sme.assoc_req_ie_len,
723 wpabuf_head(buf), wpabuf_len(buf));
724 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
725 }
726 }
727
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800728#ifdef CONFIG_MBO
Hai Shalomce48b4a2018-09-05 11:41:35 -0700729 mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
Hai Shalomc3565922019-10-28 11:58:20 -0700730 if (!wpa_s->disable_mbo_oce && mbo_ie) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800731 int len;
732
733 len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
734 wpa_s->sme.assoc_req_ie_len,
735 sizeof(wpa_s->sme.assoc_req_ie) -
Hai Shalomce48b4a2018-09-05 11:41:35 -0700736 wpa_s->sme.assoc_req_ie_len,
737 !!mbo_attr_from_mbo_ie(mbo_ie,
738 OCE_ATTR_ID_CAPA_IND));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800739 if (len >= 0)
740 wpa_s->sme.assoc_req_ie_len += len;
741 }
742#endif /* CONFIG_MBO */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800743
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800744#ifdef CONFIG_SAE
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800745 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700746 pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0,
Hai Shalom021b0b52019-04-10 11:17:58 -0700747 NULL,
748 wpa_s->key_mgmt == WPA_KEY_MGMT_FT_SAE ?
749 WPA_KEY_MGMT_FT_SAE :
750 WPA_KEY_MGMT_SAE) == 0) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800751 wpa_dbg(wpa_s, MSG_DEBUG,
752 "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
Roshan Pius3a1667e2018-07-03 15:17:14 -0700753 wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800754 params.auth_alg = WPA_AUTH_ALG_OPEN;
755 wpa_s->sme.sae_pmksa_caching = 1;
756 }
757
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800758 if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800759 if (start)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800760 resp = sme_auth_build_sae_commit(wpa_s, ssid,
Hai Shalom021b0b52019-04-10 11:17:58 -0700761 bss->bssid, 0,
Hai Shalom899fcc72020-10-19 14:38:18 -0700762 start == 2, NULL,
763 NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800764 else
Roshan Pius3a1667e2018-07-03 15:17:14 -0700765 resp = sme_auth_build_sae_confirm(wpa_s, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800766 if (resp == NULL) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800767 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800768 return;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800769 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800770 params.auth_data = wpabuf_head(resp);
771 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800772 wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800773 }
774#endif /* CONFIG_SAE */
775
Hai Shalomfdcde762020-04-02 11:19:20 -0700776 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
777 os_memset(wpa_s->bssid, 0, ETH_ALEN);
778 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
779 if (bssid_changed)
780 wpas_notify_bssid_changed(wpa_s);
781
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800782 old_ssid = wpa_s->current_ssid;
783 wpa_s->current_ssid = ssid;
784 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
785 wpa_supplicant_initiate_eapol(wpa_s);
786
787#ifdef CONFIG_FILS
788 /* TODO: FILS operations can in some cases be done between different
789 * network_ctx (i.e., same credentials can be used with multiple
790 * networks). */
791 if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
792 wpa_key_mgmt_fils(ssid->key_mgmt)) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700793 const u8 *indic;
794 u16 fils_info;
Hai Shalomce48b4a2018-09-05 11:41:35 -0700795 const u8 *realm, *username, *rrk;
796 size_t realm_len, username_len, rrk_len;
797 u16 next_seq_num;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700798
799 /*
800 * Check FILS Indication element (FILS Information field) bits
801 * indicating supported authentication algorithms against local
802 * configuration (ssid->fils_dh_group). Try to use FILS
803 * authentication only if the AP supports the combination in the
804 * network profile. */
805 indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
806 if (!indic || indic[1] < 2) {
807 wpa_printf(MSG_DEBUG, "SME: " MACSTR
808 " does not include FILS Indication element - cannot use FILS authentication with it",
809 MAC2STR(bss->bssid));
810 goto no_fils;
811 }
812
813 fils_info = WPA_GET_LE16(indic + 2);
814 if (ssid->fils_dh_group == 0 && !(fils_info & BIT(9))) {
815 wpa_printf(MSG_DEBUG, "SME: " MACSTR
816 " does not support FILS SK without PFS - cannot use FILS authentication with it",
817 MAC2STR(bss->bssid));
818 goto no_fils;
819 }
820 if (ssid->fils_dh_group != 0 && !(fils_info & BIT(10))) {
821 wpa_printf(MSG_DEBUG, "SME: " MACSTR
822 " does not support FILS SK with PFS - cannot use FILS authentication with it",
823 MAC2STR(bss->bssid));
824 goto no_fils;
825 }
826
Hai Shalomce48b4a2018-09-05 11:41:35 -0700827 if (wpa_s->last_con_fail_realm &&
828 eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
829 &username, &username_len,
830 &realm, &realm_len, &next_seq_num,
831 &rrk, &rrk_len) == 0 &&
832 realm && realm_len == wpa_s->last_con_fail_realm_len &&
833 os_memcmp(realm, wpa_s->last_con_fail_realm,
834 realm_len) == 0) {
835 wpa_printf(MSG_DEBUG,
836 "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
837 goto no_fils;
838 }
839
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800840 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700841 ssid, 0,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700842 wpa_bss_get_fils_cache_id(bss),
843 0) == 0)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800844 wpa_printf(MSG_DEBUG,
845 "SME: Try to use FILS with PMKSA caching");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700846 resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800847 if (resp) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700848 int auth_alg;
849
850 if (ssid->fils_dh_group)
851 wpa_printf(MSG_DEBUG,
852 "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
853 ssid->fils_dh_group);
854 else
855 wpa_printf(MSG_DEBUG,
856 "SME: Try to use FILS SK authentication without PFS");
857 auth_alg = ssid->fils_dh_group ?
858 WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
859 params.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800860 params.auth_data = wpabuf_head(resp);
861 params.auth_data_len = wpabuf_len(resp);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700862 wpa_s->sme.auth_alg = auth_alg;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800863 }
864 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700865no_fils:
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800866#endif /* CONFIG_FILS */
867
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800868 wpa_supplicant_cancel_sched_scan(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700869 wpa_supplicant_cancel_scan(wpa_s);
870
871 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
872 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
873 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
874
Hai Shalome21d4e82020-04-29 16:34:06 -0700875 eapol_sm_notify_portValid(wpa_s->eapol, false);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700876 wpa_clear_keys(wpa_s, bss->bssid);
877 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700878 if (old_ssid != wpa_s->current_ssid)
879 wpas_notify_network_changed(wpa_s);
880
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700881#ifdef CONFIG_HS20
882 hs20_configure_frame_filters(wpa_s);
883#endif /* CONFIG_HS20 */
884
Dmitry Shmidtf9bdef92014-04-25 10:46:36 -0700885#ifdef CONFIG_P2P
886 /*
887 * If multi-channel concurrency is not supported, check for any
888 * frequency conflict. In case of any frequency conflict, remove the
889 * least prioritized connection.
890 */
891 if (wpa_s->num_multichan_concurrent < 2) {
892 int freq, num;
893 num = get_shared_radio_freqs(wpa_s, &freq, 1);
894 if (num > 0 && freq > 0 && freq != params.freq) {
895 wpa_printf(MSG_DEBUG,
896 "Conflicting frequency found (%d != %d)",
897 freq, params.freq);
898 if (wpas_p2p_handle_frequency_conflicts(wpa_s,
899 params.freq,
900 ssid) < 0) {
901 wpas_connection_failed(wpa_s, bss->bssid);
902 wpa_supplicant_mark_disassoc(wpa_s);
903 wpabuf_free(resp);
904 wpas_connect_work_done(wpa_s);
905 return;
906 }
907 }
908 }
909#endif /* CONFIG_P2P */
910
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800911 if (skip_auth) {
912 wpa_msg(wpa_s, MSG_DEBUG,
913 "SME: Skip authentication step on reassoc-to-same-BSS");
914 wpabuf_free(resp);
915 sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN);
916 return;
917 }
918
919
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700920 wpa_s->sme.auth_alg = params.auth_alg;
921 if (wpa_drv_authenticate(wpa_s, &params) < 0) {
922 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
923 "driver failed");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800924 wpas_connection_failed(wpa_s, bss->bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800925 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800926 wpabuf_free(resp);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800927 wpas_connect_work_done(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700928 return;
929 }
930
931 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
932 NULL);
933
934 /*
935 * Association will be started based on the authentication event from
936 * the driver.
937 */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800938
939 wpabuf_free(resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700940}
941
942
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800943static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
944{
945 struct wpa_connect_work *cwork = work->ctx;
946 struct wpa_supplicant *wpa_s = work->wpa_s;
947
948 if (deinit) {
Dmitry Shmidtbd14a572014-02-18 10:33:49 -0800949 if (work->started)
950 wpa_s->connect_work = NULL;
951
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800952 wpas_connect_work_free(cwork);
953 return;
954 }
955
956 wpa_s->connect_work = work;
957
Dmitry Shmidt2e425d62014-11-10 11:18:27 -0800958 if (cwork->bss_removed ||
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800959 !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
960 wpas_network_disabled(wpa_s, cwork->ssid)) {
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800961 wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
962 wpas_connect_work_done(wpa_s);
963 return;
964 }
965
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800966 /* Starting new connection, so clear the possibly used WPA IE from the
967 * previous association. */
968 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -0700969 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
970 wpa_s->rsnxe_len = 0;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800971
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800972 sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
973}
974
975
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800976void sme_authenticate(struct wpa_supplicant *wpa_s,
977 struct wpa_bss *bss, struct wpa_ssid *ssid)
978{
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -0800979 struct wpa_connect_work *cwork;
980
981 if (bss == NULL || ssid == NULL)
982 return;
983 if (wpa_s->connect_work) {
984 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
985 return;
986 }
987
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800988 if (radio_work_pending(wpa_s, "sme-connect")) {
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700989 /*
990 * The previous sme-connect work might no longer be valid due to
991 * the fact that the BSS list was updated. In addition, it makes
992 * sense to adhere to the 'newer' decision.
993 */
994 wpa_dbg(wpa_s, MSG_DEBUG,
995 "SME: Remove previous pending sme-connect");
996 radio_remove_works(wpa_s, "sme-connect", 0);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800997 }
998
Dmitry Shmidtd7ff03d2015-12-04 14:49:35 -0800999 wpas_abort_ongoing_scan(wpa_s);
1000
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001001 cwork = os_zalloc(sizeof(*cwork));
1002 if (cwork == NULL)
1003 return;
1004 cwork->bss = bss;
1005 cwork->ssid = ssid;
1006 cwork->sme = 1;
1007
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001008#ifdef CONFIG_SAE
1009 wpa_s->sme.sae.state = SAE_NOTHING;
1010 wpa_s->sme.sae.send_confirm = 0;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001011 wpa_s->sme.sae_group_index = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001012#endif /* CONFIG_SAE */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001013
1014 if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
1015 sme_auth_start_cb, cwork) < 0)
1016 wpas_connect_work_free(cwork);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001017}
1018
1019
1020#ifdef CONFIG_SAE
1021
Roshan Pius3a1667e2018-07-03 15:17:14 -07001022static int sme_external_auth_build_buf(struct wpabuf *buf,
1023 struct wpabuf *params,
1024 const u8 *sa, const u8 *da,
Hai Shalomc3565922019-10-28 11:58:20 -07001025 u16 auth_transaction, u16 seq_num,
1026 u16 status_code)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001027{
1028 struct ieee80211_mgmt *resp;
1029
1030 resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
1031 u.auth.variable));
1032
1033 resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
1034 (WLAN_FC_STYPE_AUTH << 4));
1035 os_memcpy(resp->da, da, ETH_ALEN);
1036 os_memcpy(resp->sa, sa, ETH_ALEN);
1037 os_memcpy(resp->bssid, da, ETH_ALEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08001038 resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
1039 resp->seq_ctrl = host_to_le16(seq_num << 4);
1040 resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
Hai Shalomc3565922019-10-28 11:58:20 -07001041 resp->u.auth.status_code = host_to_le16(status_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001042 if (params)
1043 wpabuf_put_buf(buf, params);
1044
1045 return 0;
1046}
1047
1048
Hai Shalom81f62d82019-07-22 12:10:00 -07001049static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
1050 const u8 *bssid,
1051 struct wpa_ssid *ssid)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001052{
1053 struct wpabuf *resp, *buf;
Hai Shalomc3565922019-10-28 11:58:20 -07001054 int use_pt;
Hai Shalom899fcc72020-10-19 14:38:18 -07001055 bool use_pk;
1056 u16 status;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001057
Hai Shalom899fcc72020-10-19 14:38:18 -07001058 resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt,
1059 &use_pk);
Hai Shalom81f62d82019-07-22 12:10:00 -07001060 if (!resp) {
1061 wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
1062 return -1;
1063 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001064
1065 wpa_s->sme.sae.state = SAE_COMMITTED;
1066 buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp));
1067 if (!buf) {
1068 wpabuf_free(resp);
Hai Shalom81f62d82019-07-22 12:10:00 -07001069 return -1;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001070 }
1071
1072 wpa_s->sme.seq_num++;
Hai Shalom899fcc72020-10-19 14:38:18 -07001073 if (use_pk)
1074 status = WLAN_STATUS_SAE_PK;
1075 else if (use_pt)
1076 status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
1077 else
1078 status = WLAN_STATUS_SUCCESS;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001079 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Hai Shalom899fcc72020-10-19 14:38:18 -07001080 bssid, 1, wpa_s->sme.seq_num, status);
Hai Shalomfdcde762020-04-02 11:19:20 -07001081 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001082 wpabuf_free(resp);
1083 wpabuf_free(buf);
Hai Shalom81f62d82019-07-22 12:10:00 -07001084
1085 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001086}
1087
1088
1089static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
1090 u16 status)
1091{
1092 struct external_auth params;
1093
1094 os_memset(&params, 0, sizeof(params));
1095 params.status = status;
Hai Shalom66904732019-05-29 11:54:04 -07001096 params.ssid = wpa_s->sme.ext_auth_ssid;
1097 params.ssid_len = wpa_s->sme.ext_auth_ssid_len;
1098 params.bssid = wpa_s->sme.ext_auth_bssid;
Hai Shalomc3565922019-10-28 11:58:20 -07001099 if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
1100 params.pmkid = wpa_s->sme.sae.pmkid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001101 wpa_drv_send_external_auth_status(wpa_s, &params);
1102}
1103
1104
Hai Shalom81f62d82019-07-22 12:10:00 -07001105static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
1106 union wpa_event_data *data)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001107{
1108 struct wpa_ssid *ssid;
1109 size_t ssid_str_len = data->external_auth.ssid_len;
Hai Shalom5f92bc92019-04-18 11:54:11 -07001110 const u8 *ssid_str = data->external_auth.ssid;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001111
1112 /* Get the SSID conf from the ssid string obtained */
1113 for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1114 if (!wpas_network_disabled(wpa_s, ssid) &&
1115 ssid_str_len == ssid->ssid_len &&
Hai Shalom74f70d42019-02-11 14:42:39 -08001116 os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
Hai Shalom021b0b52019-04-10 11:17:58 -07001117 (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)))
Roshan Pius3a1667e2018-07-03 15:17:14 -07001118 break;
1119 }
Hai Shalom81f62d82019-07-22 12:10:00 -07001120 if (!ssid ||
1121 sme_external_auth_send_sae_commit(wpa_s, data->external_auth.bssid,
1122 ssid) < 0)
1123 return -1;
1124
1125 return 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001126}
1127
1128
1129static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
1130 const u8 *da)
1131{
1132 struct wpabuf *resp, *buf;
1133
1134 resp = sme_auth_build_sae_confirm(wpa_s, 1);
1135 if (!resp) {
1136 wpa_printf(MSG_DEBUG, "SAE: Confirm message buf alloc failure");
1137 return;
1138 }
1139
1140 wpa_s->sme.sae.state = SAE_CONFIRMED;
1141 buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp));
1142 if (!buf) {
1143 wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure");
1144 wpabuf_free(resp);
1145 return;
1146 }
1147 wpa_s->sme.seq_num++;
1148 sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
Hai Shalomc3565922019-10-28 11:58:20 -07001149 da, 2, wpa_s->sme.seq_num,
1150 WLAN_STATUS_SUCCESS);
Hai Shalomfdcde762020-04-02 11:19:20 -07001151 wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001152 wpabuf_free(resp);
1153 wpabuf_free(buf);
1154}
1155
1156
1157void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
1158 union wpa_event_data *data)
1159{
1160 if (RSN_SELECTOR_GET(&data->external_auth.key_mgmt_suite) !=
1161 RSN_AUTH_KEY_MGMT_SAE)
1162 return;
1163
1164 if (data->external_auth.action == EXT_AUTH_START) {
Hai Shalom66904732019-05-29 11:54:04 -07001165 if (!data->external_auth.bssid || !data->external_auth.ssid)
1166 return;
1167 os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid,
1168 ETH_ALEN);
1169 os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid,
1170 data->external_auth.ssid_len);
1171 wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001172 wpa_s->sme.seq_num = 0;
1173 wpa_s->sme.sae.state = SAE_NOTHING;
1174 wpa_s->sme.sae.send_confirm = 0;
1175 wpa_s->sme.sae_group_index = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001176 if (sme_handle_external_auth_start(wpa_s, data) < 0)
1177 sme_send_external_auth_status(wpa_s,
1178 WLAN_STATUS_UNSPECIFIED_FAILURE);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001179 } else if (data->external_auth.action == EXT_AUTH_ABORT) {
1180 /* Report failure to driver for the wrong trigger */
1181 sme_send_external_auth_status(wpa_s,
1182 WLAN_STATUS_UNSPECIFIED_FAILURE);
1183 }
1184}
1185
1186
Hai Shalomc3565922019-10-28 11:58:20 -07001187static int sme_sae_is_group_enabled(struct wpa_supplicant *wpa_s, int group)
1188{
1189 int *groups = wpa_s->conf->sae_groups;
1190 int default_groups[] = { 19, 20, 21, 0 };
1191 int i;
1192
1193 if (!groups)
1194 groups = default_groups;
1195
1196 for (i = 0; groups[i] > 0; i++) {
1197 if (groups[i] == group)
1198 return 1;
1199 }
1200
1201 return 0;
1202}
1203
1204
1205static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
1206 const struct wpabuf *groups)
1207{
1208 size_t i, count;
1209 const u8 *pos;
1210
1211 if (!groups)
1212 return 0;
1213
1214 pos = wpabuf_head(groups);
1215 count = wpabuf_len(groups) / 2;
1216 for (i = 0; i < count; i++) {
1217 int enabled;
1218 u16 group;
1219
1220 group = WPA_GET_LE16(pos);
1221 pos += 2;
1222 enabled = sme_sae_is_group_enabled(wpa_s, group);
1223 wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
1224 group, enabled ? "enabled" : "disabled");
1225 if (enabled)
1226 return 1;
1227 }
1228
1229 return 0;
1230}
1231
1232
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001233static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001234 u16 status_code, const u8 *data, size_t len,
1235 int external, const u8 *sa)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001236{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001237 int *groups;
1238
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001239 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
1240 "status code %u", auth_transaction, status_code);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001241
1242 if (auth_transaction == 1 &&
1243 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1244 wpa_s->sme.sae.state == SAE_COMMITTED &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001245 (external || wpa_s->current_bss) && wpa_s->current_ssid) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001246 int default_groups[] = { 19, 20, 21, 0 };
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001247 u16 group;
Hai Shalomfdcde762020-04-02 11:19:20 -07001248 const u8 *token_pos;
1249 size_t token_len;
1250 int h2e = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001251
1252 groups = wpa_s->conf->sae_groups;
1253 if (!groups || groups[0] <= 0)
1254 groups = default_groups;
1255
Hai Shalomfdcde762020-04-02 11:19:20 -07001256 wpa_hexdump(MSG_DEBUG, "SME: SAE anti-clogging token request",
1257 data, len);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001258 if (len < sizeof(le16)) {
1259 wpa_dbg(wpa_s, MSG_DEBUG,
1260 "SME: Too short SAE anti-clogging token request");
1261 return -1;
1262 }
1263 group = WPA_GET_LE16(data);
1264 wpa_dbg(wpa_s, MSG_DEBUG,
1265 "SME: SAE anti-clogging token requested (group %u)",
1266 group);
1267 if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
1268 WLAN_STATUS_SUCCESS) {
1269 wpa_dbg(wpa_s, MSG_ERROR,
1270 "SME: SAE group %u of anti-clogging request is invalid",
1271 group);
1272 return -1;
1273 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001274 wpabuf_free(wpa_s->sme.sae_token);
Hai Shalomfdcde762020-04-02 11:19:20 -07001275 token_pos = data + sizeof(le16);
1276 token_len = len - sizeof(le16);
Hai Shalom899fcc72020-10-19 14:38:18 -07001277 h2e = wpa_s->sme.sae.h2e;
Hai Shalomfdcde762020-04-02 11:19:20 -07001278 if (h2e) {
1279 if (token_len < 3) {
1280 wpa_dbg(wpa_s, MSG_DEBUG,
1281 "SME: Too short SAE anti-clogging token container");
1282 return -1;
1283 }
1284 if (token_pos[0] != WLAN_EID_EXTENSION ||
1285 token_pos[1] == 0 ||
1286 token_pos[1] > token_len - 2 ||
1287 token_pos[2] != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN) {
1288 wpa_dbg(wpa_s, MSG_DEBUG,
1289 "SME: Invalid SAE anti-clogging token container header");
1290 return -1;
1291 }
1292 token_len = token_pos[1] - 1;
1293 token_pos += 3;
1294 }
1295 wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
1296 wpa_hexdump_buf(MSG_DEBUG, "SME: Requested anti-clogging token",
1297 wpa_s->sme.sae_token);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001298 if (!external)
1299 sme_send_authentication(wpa_s, wpa_s->current_bss,
Hai Shalom021b0b52019-04-10 11:17:58 -07001300 wpa_s->current_ssid, 2);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001301 else
1302 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001303 wpa_s, wpa_s->sme.ext_auth_bssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001304 wpa_s->current_ssid);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001305 return 0;
1306 }
1307
1308 if (auth_transaction == 1 &&
1309 status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1310 wpa_s->sme.sae.state == SAE_COMMITTED &&
Roshan Pius3a1667e2018-07-03 15:17:14 -07001311 (external || wpa_s->current_bss) && wpa_s->current_ssid) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001312 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
Hai Shalomc3565922019-10-28 11:58:20 -07001313 int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1314 wpa_s->sme.sae.group);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001315 wpa_s->sme.sae_group_index++;
1316 if (sme_set_sae_group(wpa_s) < 0)
1317 return -1; /* no other groups enabled */
1318 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001319 if (!external)
1320 sme_send_authentication(wpa_s, wpa_s->current_bss,
1321 wpa_s->current_ssid, 1);
1322 else
1323 sme_external_auth_send_sae_commit(
Hai Shalom66904732019-05-29 11:54:04 -07001324 wpa_s, wpa_s->sme.ext_auth_bssid,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001325 wpa_s->current_ssid);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001326 return 0;
1327 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001328
Roshan Pius3a1667e2018-07-03 15:17:14 -07001329 if (auth_transaction == 1 &&
1330 status_code == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1331 const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1332
1333 wpa_msg(wpa_s, MSG_INFO,
1334 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR,
1335 MAC2STR(bssid));
1336 return -1;
1337 }
1338
Hai Shalomc3565922019-10-28 11:58:20 -07001339 if (status_code != WLAN_STATUS_SUCCESS &&
Hai Shalom899fcc72020-10-19 14:38:18 -07001340 status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
1341 status_code != WLAN_STATUS_SAE_PK)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001342 return -1;
1343
1344 if (auth_transaction == 1) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07001345 u16 res;
1346
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001347 groups = wpa_s->conf->sae_groups;
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001348
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001349 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
Roshan Pius3a1667e2018-07-03 15:17:14 -07001350 if ((!external && wpa_s->current_bss == NULL) ||
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001351 wpa_s->current_ssid == NULL)
1352 return -1;
Hai Shalomc3565922019-10-28 11:58:20 -07001353 if (wpa_s->sme.sae.state != SAE_COMMITTED) {
1354 wpa_printf(MSG_DEBUG,
1355 "SAE: Ignore commit message while waiting for confirm");
1356 return 0;
1357 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001358 if (wpa_s->sme.sae.h2e && status_code == WLAN_STATUS_SUCCESS) {
Hai Shalomfdcde762020-04-02 11:19:20 -07001359 wpa_printf(MSG_DEBUG,
1360 "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
1361 return -1;
1362 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001363 if ((!wpa_s->sme.sae.h2e || wpa_s->sme.sae.pk) &&
Hai Shalomfdcde762020-04-02 11:19:20 -07001364 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
1365 wpa_printf(MSG_DEBUG,
1366 "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
1367 return -1;
1368 }
Hai Shalom899fcc72020-10-19 14:38:18 -07001369 if (!wpa_s->sme.sae.pk &&
1370 status_code == WLAN_STATUS_SAE_PK) {
1371 wpa_printf(MSG_DEBUG,
1372 "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected");
1373 return -1;
1374 }
Hai Shalomfdcde762020-04-02 11:19:20 -07001375
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001376 if (groups && groups[0] <= 0)
1377 groups = NULL;
Dmitry Shmidt41712582015-06-29 11:02:15 -07001378 res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
Hai Shalomc3565922019-10-28 11:58:20 -07001379 groups, status_code ==
Hai Shalom899fcc72020-10-19 14:38:18 -07001380 WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
1381 status_code == WLAN_STATUS_SAE_PK);
Dmitry Shmidt41712582015-06-29 11:02:15 -07001382 if (res == SAE_SILENTLY_DISCARD) {
1383 wpa_printf(MSG_DEBUG,
1384 "SAE: Drop commit message due to reflection attack");
1385 return 0;
1386 }
1387 if (res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001388 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001389
Hai Shalomc3565922019-10-28 11:58:20 -07001390 if (wpa_s->sme.sae.tmp &&
1391 sme_check_sae_rejected_groups(
1392 wpa_s,
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001393 wpa_s->sme.sae.tmp->peer_rejected_groups))
Hai Shalomc3565922019-10-28 11:58:20 -07001394 return -1;
1395
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001396 if (sae_process_commit(&wpa_s->sme.sae) < 0) {
1397 wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
1398 "commit");
1399 return -1;
1400 }
1401
1402 wpabuf_free(wpa_s->sme.sae_token);
1403 wpa_s->sme.sae_token = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001404 if (!external)
1405 sme_send_authentication(wpa_s, wpa_s->current_bss,
1406 wpa_s->current_ssid, 0);
1407 else
1408 sme_external_auth_send_sae_confirm(wpa_s, sa);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001409 return 0;
1410 } else if (auth_transaction == 2) {
Hai Shalomc3565922019-10-28 11:58:20 -07001411 if (status_code != WLAN_STATUS_SUCCESS)
1412 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001413 wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001414 if (wpa_s->sme.sae.state != SAE_CONFIRMED)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001415 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001416 if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001417 return -1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001418 wpa_s->sme.sae.state = SAE_ACCEPTED;
1419 sae_clear_temp_data(&wpa_s->sme.sae);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001420
1421 if (external) {
1422 /* Report success to driver */
1423 sme_send_external_auth_status(wpa_s,
1424 WLAN_STATUS_SUCCESS);
1425 }
1426
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001427 return 1;
1428 }
1429
1430 return -1;
1431}
Roshan Pius3a1667e2018-07-03 15:17:14 -07001432
1433
Hai Shalomc3565922019-10-28 11:58:20 -07001434static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
1435{
1436 wpa_printf(MSG_DEBUG,
1437 "SME: SAE completed - setting PMK for 4-way handshake");
1438 wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN,
1439 wpa_s->sme.sae.pmkid, bssid);
1440 if (wpa_s->conf->sae_pmkid_in_assoc) {
1441 /* Update the own RSNE contents now that we have set the PMK
1442 * and added a PMKSA cache entry based on the successfully
1443 * completed SAE exchange. In practice, this will add the PMKID
1444 * into RSNE. */
1445 if (wpa_s->sme.assoc_req_ie_len + 2 + PMKID_LEN >
1446 sizeof(wpa_s->sme.assoc_req_ie)) {
1447 wpa_msg(wpa_s, MSG_WARNING,
1448 "RSN: Not enough room for inserting own PMKID into RSNE");
1449 return -1;
1450 }
1451 if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
1452 &wpa_s->sme.assoc_req_ie_len,
1453 wpa_s->sme.sae.pmkid) < 0)
1454 return -1;
1455 wpa_hexdump(MSG_DEBUG,
1456 "SME: Updated Association Request IEs",
1457 wpa_s->sme.assoc_req_ie,
1458 wpa_s->sme.assoc_req_ie_len);
1459 }
1460
1461 return 0;
1462}
1463
1464
Roshan Pius3a1667e2018-07-03 15:17:14 -07001465void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
1466 const u8 *auth_frame, size_t len)
1467{
1468 const struct ieee80211_mgmt *header;
1469 size_t auth_length;
1470
1471 header = (const struct ieee80211_mgmt *) auth_frame;
1472 auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);
1473
1474 if (len < auth_length) {
1475 /* Notify failure to the driver */
1476 sme_send_external_auth_status(wpa_s,
1477 WLAN_STATUS_UNSPECIFIED_FAILURE);
1478 return;
1479 }
1480
Hai Shalom74f70d42019-02-11 14:42:39 -08001481 if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001482 int res;
1483
Hai Shalom74f70d42019-02-11 14:42:39 -08001484 res = sme_sae_auth(
1485 wpa_s, le_to_host16(header->u.auth.auth_transaction),
1486 le_to_host16(header->u.auth.status_code),
1487 header->u.auth.variable,
1488 len - auth_length, 1, header->sa);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001489 if (res < 0) {
1490 /* Notify failure to the driver */
1491 sme_send_external_auth_status(
1492 wpa_s, WLAN_STATUS_UNSPECIFIED_FAILURE);
1493 return;
1494 }
1495 if (res != 1)
1496 return;
1497
Hai Shalomc3565922019-10-28 11:58:20 -07001498 if (sme_sae_set_pmk(wpa_s, wpa_s->sme.ext_auth_bssid) < 0)
1499 return;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001500 }
1501}
1502
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001503#endif /* CONFIG_SAE */
1504
1505
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001506void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
1507{
1508 struct wpa_ssid *ssid = wpa_s->current_ssid;
1509
1510 if (ssid == NULL) {
1511 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1512 "when network is not selected");
1513 return;
1514 }
1515
1516 if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
1517 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
1518 "when not in authenticating state");
1519 return;
1520 }
1521
1522 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) {
1523 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
1524 "unexpected peer " MACSTR,
1525 MAC2STR(data->auth.peer));
1526 return;
1527 }
1528
1529 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001530 " auth_type=%d auth_transaction=%d status_code=%d",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001531 MAC2STR(data->auth.peer), data->auth.auth_type,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001532 data->auth.auth_transaction, data->auth.status_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001533 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
1534 data->auth.ies, data->auth.ies_len);
1535
1536 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
1537
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001538#ifdef CONFIG_SAE
1539 if (data->auth.auth_type == WLAN_AUTH_SAE) {
1540 int res;
1541 res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
1542 data->auth.status_code, data->auth.ies,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001543 data->auth.ies_len, 0, NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001544 if (res < 0) {
1545 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1546 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
1547
1548 }
1549 if (res != 1)
1550 return;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001551
Hai Shalomc3565922019-10-28 11:58:20 -07001552 if (sme_sae_set_pmk(wpa_s, wpa_s->pending_bssid) < 0)
1553 return;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001554 }
1555#endif /* CONFIG_SAE */
1556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001557 if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001558 char *ie_txt = NULL;
1559
1560 if (data->auth.ies && data->auth.ies_len) {
1561 size_t buflen = 2 * data->auth.ies_len + 1;
1562 ie_txt = os_malloc(buflen);
1563 if (ie_txt) {
1564 wpa_snprintf_hex(ie_txt, buflen, data->auth.ies,
1565 data->auth.ies_len);
1566 }
1567 }
1568 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001569 " auth_type=%u auth_transaction=%u status_code=%u%s%s",
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001570 MAC2STR(data->auth.peer), data->auth.auth_type,
1571 data->auth.auth_transaction, data->auth.status_code,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001572 ie_txt ? " ie=" : "",
1573 ie_txt ? ie_txt : "");
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001574 os_free(ie_txt);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001575
Hai Shalomce48b4a2018-09-05 11:41:35 -07001576#ifdef CONFIG_FILS
1577 if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
1578 wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS)
1579 fils_connection_failure(wpa_s);
1580#endif /* CONFIG_FILS */
1581
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001582 if (data->auth.status_code !=
1583 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
1584 wpa_s->sme.auth_alg == data->auth.auth_type ||
1585 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
1586 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001587 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001588 return;
1589 }
1590
Dmitry Shmidt97672262014-02-03 13:02:54 -08001591 wpas_connect_work_done(wpa_s);
1592
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001593 switch (data->auth.auth_type) {
1594 case WLAN_AUTH_OPEN:
1595 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
1596
1597 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
1598 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
1599 wpa_s->current_ssid);
1600 return;
1601
1602 case WLAN_AUTH_SHARED_KEY:
1603 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
1604
1605 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
1606 wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
1607 wpa_s->current_ssid);
1608 return;
1609
1610 default:
1611 return;
1612 }
1613 }
1614
1615#ifdef CONFIG_IEEE80211R
1616 if (data->auth.auth_type == WLAN_AUTH_FT) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001617 const u8 *ric_ies = NULL;
1618 size_t ric_ies_len = 0;
1619
1620 if (wpa_s->ric_ies) {
1621 ric_ies = wpabuf_head(wpa_s->ric_ies);
1622 ric_ies_len = wpabuf_len(wpa_s->ric_ies);
1623 }
Dmitry Shmidt41712582015-06-29 11:02:15 -07001624 if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
1625 data->auth.ies_len, 0,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001626 data->auth.peer,
1627 ric_ies, ric_ies_len) < 0) {
Dmitry Shmidt41712582015-06-29 11:02:15 -07001628 wpa_dbg(wpa_s, MSG_DEBUG,
1629 "SME: FT Authentication response processing failed");
1630 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
1631 MACSTR
1632 " reason=%d locally_generated=1",
1633 MAC2STR(wpa_s->pending_bssid),
1634 WLAN_REASON_DEAUTH_LEAVING);
1635 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1636 wpa_supplicant_mark_disassoc(wpa_s);
1637 return;
1638 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001639 }
1640#endif /* CONFIG_IEEE80211R */
1641
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001642#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001643 if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
1644 data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
1645 u16 expect_auth_type;
1646
1647 expect_auth_type = wpa_s->sme.auth_alg ==
1648 WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
1649 WLAN_AUTH_FILS_SK;
1650 if (data->auth.auth_type != expect_auth_type) {
1651 wpa_dbg(wpa_s, MSG_DEBUG,
1652 "SME: FILS Authentication response used different auth alg (%u; expected %u)",
1653 data->auth.auth_type, expect_auth_type);
1654 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
1655 MACSTR
1656 " reason=%d locally_generated=1",
1657 MAC2STR(wpa_s->pending_bssid),
1658 WLAN_REASON_DEAUTH_LEAVING);
1659 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1660 wpa_supplicant_mark_disassoc(wpa_s);
1661 return;
1662 }
1663
1664 if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
1665 data->auth.ies, data->auth.ies_len) < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001666 wpa_dbg(wpa_s, MSG_DEBUG,
1667 "SME: FILS Authentication response processing failed");
1668 wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
1669 MACSTR
1670 " reason=%d locally_generated=1",
1671 MAC2STR(wpa_s->pending_bssid),
1672 WLAN_REASON_DEAUTH_LEAVING);
1673 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1674 wpa_supplicant_mark_disassoc(wpa_s);
1675 return;
1676 }
1677 }
1678#endif /* CONFIG_FILS */
1679
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001680 sme_associate(wpa_s, ssid->mode, data->auth.peer,
1681 data->auth.auth_type);
1682}
1683
1684
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001685#ifdef CONFIG_IEEE80211R
1686static void remove_ie(u8 *buf, size_t *len, u8 eid)
1687{
1688 u8 *pos, *next, *end;
1689
1690 pos = (u8 *) get_ie(buf, *len, eid);
1691 if (pos) {
1692 next = pos + 2 + pos[1];
1693 end = buf + *len;
1694 *len -= 2 + pos[1];
1695 os_memmove(pos, next, end - next);
1696 }
1697}
1698#endif /* CONFIG_IEEE80211R */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001699
1700
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001701void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
1702 const u8 *bssid, u16 auth_type)
1703{
1704 struct wpa_driver_associate_params params;
1705 struct ieee802_11_elems elems;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001706 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001707#ifdef CONFIG_FILS
1708 u8 nonces[2 * FILS_NONCE_LEN];
1709#endif /* CONFIG_FILS */
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001710#ifdef CONFIG_HT_OVERRIDES
1711 struct ieee80211_ht_capabilities htcaps;
1712 struct ieee80211_ht_capabilities htcaps_mask;
1713#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001714#ifdef CONFIG_VHT_OVERRIDES
1715 struct ieee80211_vht_capabilities vhtcaps;
1716 struct ieee80211_vht_capabilities vhtcaps_mask;
1717#endif /* CONFIG_VHT_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001718
1719 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001720
1721#ifdef CONFIG_FILS
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001722 if (auth_type == WLAN_AUTH_FILS_SK ||
1723 auth_type == WLAN_AUTH_FILS_SK_PFS) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001724 struct wpabuf *buf;
1725 const u8 *snonce, *anonce;
Paul Stewart092955c2017-02-06 09:13:09 -08001726 const unsigned int max_hlp = 20;
1727 struct wpabuf *hlp[max_hlp];
1728 unsigned int i, num_hlp = 0;
1729 struct fils_hlp_req *req;
1730
1731 dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
1732 list) {
1733 hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
1734 wpabuf_len(req->pkt));
1735 if (!hlp[num_hlp])
1736 break;
1737 wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
1738 wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
1739 ETH_ALEN);
1740 wpabuf_put_data(hlp[num_hlp],
1741 "\xaa\xaa\x03\x00\x00\x00", 6);
1742 wpabuf_put_buf(hlp[num_hlp], req->pkt);
1743 num_hlp++;
1744 if (num_hlp >= max_hlp)
1745 break;
1746 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001747
1748 buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
1749 &params.fils_kek_len, &snonce,
Paul Stewart092955c2017-02-06 09:13:09 -08001750 &anonce,
1751 (const struct wpabuf **) hlp,
1752 num_hlp);
1753 for (i = 0; i < num_hlp; i++)
1754 wpabuf_free(hlp[i]);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001755 if (!buf)
1756 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001757 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req before FILS elements",
1758 wpa_s->sme.assoc_req_ie,
1759 wpa_s->sme.assoc_req_ie_len);
1760#ifdef CONFIG_IEEE80211R
1761 if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
1762 /* Remove RSNE and MDE to allow them to be overridden
1763 * with FILS+FT specific values from
1764 * fils_build_assoc_req(). */
1765 remove_ie(wpa_s->sme.assoc_req_ie,
1766 &wpa_s->sme.assoc_req_ie_len,
1767 WLAN_EID_RSN);
1768 wpa_hexdump(MSG_DEBUG,
1769 "FILS: assoc_req after RSNE removal",
1770 wpa_s->sme.assoc_req_ie,
1771 wpa_s->sme.assoc_req_ie_len);
1772 remove_ie(wpa_s->sme.assoc_req_ie,
1773 &wpa_s->sme.assoc_req_ie_len,
1774 WLAN_EID_MOBILITY_DOMAIN);
1775 wpa_hexdump(MSG_DEBUG,
1776 "FILS: assoc_req after MDE removal",
1777 wpa_s->sme.assoc_req_ie,
1778 wpa_s->sme.assoc_req_ie_len);
1779 }
1780#endif /* CONFIG_IEEE80211R */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001781 /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
1782 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
1783 sizeof(wpa_s->sme.assoc_req_ie)) {
1784 wpa_printf(MSG_ERROR,
1785 "FILS: Not enough buffer room for own AssocReq elements");
1786 wpabuf_free(buf);
1787 return;
1788 }
1789 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1790 wpabuf_head(buf), wpabuf_len(buf));
1791 wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
1792 wpabuf_free(buf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001793 wpa_hexdump(MSG_DEBUG, "FILS: assoc_req after FILS elements",
1794 wpa_s->sme.assoc_req_ie,
1795 wpa_s->sme.assoc_req_ie_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001796
1797 os_memcpy(nonces, snonce, FILS_NONCE_LEN);
1798 os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
1799 params.fils_nonces = nonces;
1800 params.fils_nonces_len = sizeof(nonces);
1801 }
1802#endif /* CONFIG_FILS */
1803
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001804#ifdef CONFIG_OWE
1805#ifdef CONFIG_TESTING_OPTIONS
1806 if (get_ie_ext(wpa_s->sme.assoc_req_ie, wpa_s->sme.assoc_req_ie_len,
1807 WLAN_EID_EXT_OWE_DH_PARAM)) {
1808 wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
1809 } else
1810#endif /* CONFIG_TESTING_OPTIONS */
1811 if (auth_type == WLAN_AUTH_OPEN &&
1812 wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
1813 struct wpabuf *owe_ie;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001814 u16 group;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001815
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001816 if (ssid && ssid->owe_group) {
1817 group = ssid->owe_group;
Hai Shalom74f70d42019-02-11 14:42:39 -08001818 } else if (wpa_s->assoc_status_code ==
1819 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001820 if (wpa_s->last_owe_group == 19)
1821 group = 20;
1822 else if (wpa_s->last_owe_group == 20)
1823 group = 21;
1824 else
1825 group = OWE_DH_GROUP;
Hai Shalom74f70d42019-02-11 14:42:39 -08001826 } else {
1827 group = OWE_DH_GROUP;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001828 }
Hai Shalom74f70d42019-02-11 14:42:39 -08001829
Roshan Pius3a1667e2018-07-03 15:17:14 -07001830 wpa_s->last_owe_group = group;
1831 wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001832 owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
1833 if (!owe_ie) {
1834 wpa_printf(MSG_ERROR,
1835 "OWE: Failed to build IE for Association Request frame");
1836 return;
1837 }
1838 if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(owe_ie) >
1839 sizeof(wpa_s->sme.assoc_req_ie)) {
1840 wpa_printf(MSG_ERROR,
1841 "OWE: Not enough buffer room for own Association Request frame elements");
1842 wpabuf_free(owe_ie);
1843 return;
1844 }
1845 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1846 wpabuf_head(owe_ie), wpabuf_len(owe_ie));
1847 wpa_s->sme.assoc_req_ie_len += wpabuf_len(owe_ie);
1848 wpabuf_free(owe_ie);
1849 }
1850#endif /* CONFIG_OWE */
1851
Hai Shalom021b0b52019-04-10 11:17:58 -07001852#ifdef CONFIG_DPP2
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001853 if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid &&
1854 ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 &&
1855 !ssid->dpp_pfs_fallback) {
1856 struct rsn_pmksa_cache_entry *pmksa;
1857
1858 pmksa = pmksa_cache_get_current(wpa_s->wpa);
1859 if (!pmksa || !pmksa->dpp_pfs)
1860 goto pfs_fail;
Hai Shalom021b0b52019-04-10 11:17:58 -07001861
1862 dpp_pfs_free(wpa_s->dpp_pfs);
1863 wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
1864 ssid->dpp_netaccesskey_len);
1865 if (!wpa_s->dpp_pfs) {
1866 wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
1867 /* Try to continue without PFS */
1868 goto pfs_fail;
1869 }
1870 if (wpa_s->sme.assoc_req_ie_len +
1871 wpabuf_len(wpa_s->dpp_pfs->ie) >
1872 sizeof(wpa_s->sme.assoc_req_ie)) {
1873 wpa_printf(MSG_ERROR,
1874 "DPP: Not enough buffer room for own Association Request frame elements");
1875 dpp_pfs_free(wpa_s->dpp_pfs);
1876 wpa_s->dpp_pfs = NULL;
1877 goto pfs_fail;
1878 }
1879 os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1880 wpabuf_head(wpa_s->dpp_pfs->ie),
1881 wpabuf_len(wpa_s->dpp_pfs->ie));
1882 wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
1883 }
1884pfs_fail:
1885#endif /* CONFIG_DPP2 */
1886
Hai Shalom899fcc72020-10-19 14:38:18 -07001887 wpa_s->mscs_setup_done = false;
Hai Shalom60840252021-02-19 19:02:11 -08001888 if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
1889 wpa_s->robust_av.valid_config) {
Hai Shalom899fcc72020-10-19 14:38:18 -07001890 struct wpabuf *mscs_ie;
1891 size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len;
1892
Hai Shalom899fcc72020-10-19 14:38:18 -07001893 buf_len = 3 + /* MSCS descriptor IE header */
1894 1 + /* Request type */
1895 2 + /* User priority control */
1896 4 + /* Stream timeout */
1897 3 + /* TCLAS Mask IE header */
1898 wpa_s->robust_av.frame_classifier_len;
1899 mscs_ie = wpabuf_alloc(buf_len);
1900 if (!mscs_ie) {
1901 wpa_printf(MSG_INFO,
1902 "MSCS: Failed to allocate MSCS IE");
1903 goto mscs_fail;
1904 }
1905
1906 wpa_ie_len = &wpa_s->sme.assoc_req_ie_len;
1907 max_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
1908 wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
1909 if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) {
1910 wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
1911 mscs_ie_len = wpabuf_len(mscs_ie);
1912 os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len,
1913 wpabuf_head(mscs_ie), mscs_ie_len);
1914 *wpa_ie_len += mscs_ie_len;
1915 }
1916
1917 wpabuf_free(mscs_ie);
1918 }
1919mscs_fail:
1920
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001921 if (ssid && ssid->multi_ap_backhaul_sta) {
Hai Shalom74f70d42019-02-11 14:42:39 -08001922 size_t multi_ap_ie_len;
1923
1924 multi_ap_ie_len = add_multi_ap_ie(
1925 wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
1926 sizeof(wpa_s->sme.assoc_req_ie) -
1927 wpa_s->sme.assoc_req_ie_len,
1928 MULTI_AP_BACKHAUL_STA);
1929 if (multi_ap_ie_len == 0) {
1930 wpa_printf(MSG_ERROR,
1931 "Multi-AP: Failed to build Multi-AP IE");
1932 return;
1933 }
1934 wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
1935 }
1936
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001937 params.bssid = bssid;
1938 params.ssid = wpa_s->sme.ssid;
1939 params.ssid_len = wpa_s->sme.ssid_len;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001940 params.freq.freq = wpa_s->sme.freq;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001941 params.bg_scan_period = ssid ? ssid->bg_scan_period : -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001942 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
1943 wpa_s->sme.assoc_req_ie : NULL;
1944 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08001945 wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
1946 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001947 params.pairwise_suite = wpa_s->pairwise_cipher;
1948 params.group_suite = wpa_s->group_cipher;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001949 params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
Dmitry Shmidt15907092014-03-25 10:42:57 -07001950 params.key_mgmt_suite = wpa_s->key_mgmt;
1951 params.wpa_proto = wpa_s->wpa_proto;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001952#ifdef CONFIG_HT_OVERRIDES
1953 os_memset(&htcaps, 0, sizeof(htcaps));
1954 os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
1955 params.htcaps = (u8 *) &htcaps;
1956 params.htcaps_mask = (u8 *) &htcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001957 wpa_supplicant_apply_ht_overrides(wpa_s, ssid, &params);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08001958#endif /* CONFIG_HT_OVERRIDES */
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001959#ifdef CONFIG_VHT_OVERRIDES
1960 os_memset(&vhtcaps, 0, sizeof(vhtcaps));
1961 os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
1962 params.vhtcaps = &vhtcaps;
1963 params.vhtcaps_mask = &vhtcaps_mask;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001964 wpa_supplicant_apply_vht_overrides(wpa_s, ssid, &params);
Dmitry Shmidt2f023192013-03-12 12:44:17 -07001965#endif /* CONFIG_VHT_OVERRIDES */
Hai Shalomfdcde762020-04-02 11:19:20 -07001966#ifdef CONFIG_HE_OVERRIDES
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001967 wpa_supplicant_apply_he_overrides(wpa_s, ssid, &params);
Hai Shalomfdcde762020-04-02 11:19:20 -07001968#endif /* CONFIG_HE_OVERRIDES */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001969#ifdef CONFIG_IEEE80211R
Hai Shalom74f70d42019-02-11 14:42:39 -08001970 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
1971 get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
1972 WLAN_EID_RIC_DATA)) {
1973 /* There seems to be a pretty inconvenient bug in the Linux
1974 * kernel IE splitting functionality when RIC is used. For now,
1975 * skip correct behavior in IE construction here (i.e., drop the
1976 * additional non-FT-specific IEs) to avoid kernel issues. This
1977 * is fine since RIC is used only for testing purposes in the
1978 * current implementation. */
1979 wpa_printf(MSG_INFO,
1980 "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001981 params.wpa_ie = wpa_s->sme.ft_ies;
1982 params.wpa_ie_len = wpa_s->sme.ft_ies_len;
Hai Shalom74f70d42019-02-11 14:42:39 -08001983 } else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
1984 const u8 *rm_en, *pos, *end;
1985 size_t rm_en_len = 0;
1986 u8 *rm_en_dup = NULL, *wpos;
1987
1988 /* Remove RSNE, MDE, FTE to allow them to be overridden with
1989 * FT specific values */
1990 remove_ie(wpa_s->sme.assoc_req_ie,
1991 &wpa_s->sme.assoc_req_ie_len,
1992 WLAN_EID_RSN);
1993 remove_ie(wpa_s->sme.assoc_req_ie,
1994 &wpa_s->sme.assoc_req_ie_len,
1995 WLAN_EID_MOBILITY_DOMAIN);
1996 remove_ie(wpa_s->sme.assoc_req_ie,
1997 &wpa_s->sme.assoc_req_ie_len,
1998 WLAN_EID_FAST_BSS_TRANSITION);
1999 rm_en = get_ie(wpa_s->sme.assoc_req_ie,
2000 wpa_s->sme.assoc_req_ie_len,
2001 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2002 if (rm_en) {
2003 /* Need to remove RM Enabled Capabilities element as
2004 * well temporarily, so that it can be placed between
2005 * RSNE and MDE. */
2006 rm_en_len = 2 + rm_en[1];
2007 rm_en_dup = os_memdup(rm_en, rm_en_len);
2008 remove_ie(wpa_s->sme.assoc_req_ie,
2009 &wpa_s->sme.assoc_req_ie_len,
2010 WLAN_EID_RRM_ENABLED_CAPABILITIES);
2011 }
2012 wpa_hexdump(MSG_DEBUG,
2013 "SME: Association Request IEs after FT IE removal",
2014 wpa_s->sme.assoc_req_ie,
2015 wpa_s->sme.assoc_req_ie_len);
2016 if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
2017 rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
2018 wpa_printf(MSG_ERROR,
2019 "SME: Not enough buffer room for FT IEs in Association Request frame");
2020 os_free(rm_en_dup);
2021 return;
2022 }
2023
2024 os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
2025 rm_en_len,
2026 wpa_s->sme.assoc_req_ie,
2027 wpa_s->sme.assoc_req_ie_len);
2028 pos = wpa_s->sme.ft_ies;
2029 end = pos + wpa_s->sme.ft_ies_len;
2030 wpos = wpa_s->sme.assoc_req_ie;
2031 if (*pos == WLAN_EID_RSN) {
2032 os_memcpy(wpos, pos, 2 + pos[1]);
2033 wpos += 2 + pos[1];
2034 pos += 2 + pos[1];
2035 }
2036 if (rm_en_dup) {
2037 os_memcpy(wpos, rm_en_dup, rm_en_len);
2038 wpos += rm_en_len;
2039 os_free(rm_en_dup);
2040 }
2041 os_memcpy(wpos, pos, end - pos);
2042 wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
2043 rm_en_len;
2044 params.wpa_ie = wpa_s->sme.assoc_req_ie;
2045 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
2046 wpa_hexdump(MSG_DEBUG,
2047 "SME: Association Request IEs after FT override",
2048 params.wpa_ie, params.wpa_ie_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002049 }
2050#endif /* CONFIG_IEEE80211R */
2051 params.mode = mode;
2052 params.mgmt_frame_protection = wpa_s->sme.mfp;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002053 params.rrm_used = wpa_s->rrm.rrm_used;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054 if (wpa_s->sme.prev_bssid_set)
2055 params.prev_bssid = wpa_s->sme.prev_bssid;
2056
2057 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2058 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
2059 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002060 params.freq.freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002061
2062 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2063
2064 if (params.wpa_ie == NULL ||
2065 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
2066 < 0) {
2067 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
2068 os_memset(&elems, 0, sizeof(elems));
2069 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002070 if (elems.rsn_ie) {
2071 params.wpa_proto = WPA_PROTO_RSN;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002072 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
2073 elems.rsn_ie_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002074 } else if (elems.wpa_ie) {
2075 params.wpa_proto = WPA_PROTO_WPA;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002076 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
2077 elems.wpa_ie_len + 2);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002078 } else if (elems.osen) {
2079 params.wpa_proto = WPA_PROTO_OSEN;
2080 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
2081 elems.osen_len + 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002082 } else
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002083 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
Hai Shalomc3565922019-10-28 11:58:20 -07002084 if (elems.rsnxe)
2085 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, elems.rsnxe - 2,
2086 elems.rsnxe_len + 2);
2087 else
2088 wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002089 if (ssid && ssid->p2p_group)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002090 params.p2p = 1;
2091
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002092 if (wpa_s->p2pdev->set_sta_uapsd)
2093 params.uapsd = wpa_s->p2pdev->sta_uapsd;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002094 else
2095 params.uapsd = -1;
2096
2097 if (wpa_drv_associate(wpa_s, &params) < 0) {
2098 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
2099 "driver failed");
2100 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002101 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2103 return;
2104 }
2105
2106 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
2107 NULL);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002108
2109#ifdef CONFIG_TESTING_OPTIONS
2110 wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
2111 wpa_s->last_assoc_req_wpa_ie = NULL;
2112 if (params.wpa_ie)
2113 wpa_s->last_assoc_req_wpa_ie =
2114 wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len);
2115#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002116}
2117
2118
2119int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
2120 const u8 *ies, size_t ies_len)
2121{
2122 if (md == NULL || ies == NULL) {
2123 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
2124 os_free(wpa_s->sme.ft_ies);
2125 wpa_s->sme.ft_ies = NULL;
2126 wpa_s->sme.ft_ies_len = 0;
2127 wpa_s->sme.ft_used = 0;
2128 return 0;
2129 }
2130
2131 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
2132 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
2133 os_free(wpa_s->sme.ft_ies);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002134 wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002135 if (wpa_s->sme.ft_ies == NULL)
2136 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 wpa_s->sme.ft_ies_len = ies_len;
2138 return 0;
2139}
2140
2141
2142static void sme_deauth(struct wpa_supplicant *wpa_s)
2143{
2144 int bssid_changed;
2145
2146 bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2147
2148 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
2149 WLAN_REASON_DEAUTH_LEAVING) < 0) {
2150 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
2151 "failed");
2152 }
2153 wpa_s->sme.prev_bssid_set = 0;
2154
2155 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2156 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2157 os_memset(wpa_s->bssid, 0, ETH_ALEN);
2158 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2159 if (bssid_changed)
2160 wpas_notify_bssid_changed(wpa_s);
2161}
2162
2163
2164void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
2165 union wpa_event_data *data)
2166{
2167 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
2168 "status code %d", MAC2STR(wpa_s->pending_bssid),
2169 data->assoc_reject.status_code);
2170
2171 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2172
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002173#ifdef CONFIG_SAE
2174 if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
2175 wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
2176 wpa_dbg(wpa_s, MSG_DEBUG,
2177 "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
2178 wpa_sm_aborted_cached(wpa_s->wpa);
2179 wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
2180 if (wpa_s->current_bss) {
2181 struct wpa_bss *bss = wpa_s->current_bss;
2182 struct wpa_ssid *ssid = wpa_s->current_ssid;
2183
2184 wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
2185 WLAN_REASON_DEAUTH_LEAVING);
2186 wpas_connect_work_done(wpa_s);
2187 wpa_supplicant_mark_disassoc(wpa_s);
2188 wpa_supplicant_connect(wpa_s, bss, ssid);
2189 return;
2190 }
2191 }
2192#endif /* CONFIG_SAE */
2193
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002194 /*
2195 * For now, unconditionally terminate the previous authentication. In
2196 * theory, this should not be needed, but mac80211 gets quite confused
2197 * if the authentication is left pending.. Some roaming cases might
2198 * benefit from using the previous authentication, so this could be
2199 * optimized in the future.
2200 */
2201 sme_deauth(wpa_s);
2202}
2203
2204
2205void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
2206 union wpa_event_data *data)
2207{
2208 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
2209 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002210 wpa_supplicant_mark_disassoc(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002211}
2212
2213
2214void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
2215 union wpa_event_data *data)
2216{
2217 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
2218 wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
2219 wpa_supplicant_mark_disassoc(wpa_s);
2220}
2221
2222
2223void sme_event_disassoc(struct wpa_supplicant *wpa_s,
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07002224 struct disassoc_info *info)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002225{
2226 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002227 if (wpa_s->sme.prev_bssid_set) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002228 /*
2229 * cfg80211/mac80211 can get into somewhat confused state if
2230 * the AP only disassociates us and leaves us in authenticated
2231 * state. For now, force the state to be cleared to avoid
2232 * confusing errors if we try to associate with the AP again.
2233 */
2234 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
2235 "driver state");
2236 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
2237 WLAN_REASON_DEAUTH_LEAVING);
2238 }
2239}
2240
2241
2242static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
2243{
2244 struct wpa_supplicant *wpa_s = eloop_ctx;
2245 if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
2246 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
2247 sme_deauth(wpa_s);
2248 }
2249}
2250
2251
2252static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
2253{
2254 struct wpa_supplicant *wpa_s = eloop_ctx;
2255 if (wpa_s->wpa_state == WPA_ASSOCIATING) {
2256 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
2257 sme_deauth(wpa_s);
2258 }
2259}
2260
2261
2262void sme_state_changed(struct wpa_supplicant *wpa_s)
2263{
2264 /* Make sure timers are cleaned up appropriately. */
2265 if (wpa_s->wpa_state != WPA_ASSOCIATING)
2266 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2267 if (wpa_s->wpa_state != WPA_AUTHENTICATING)
2268 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2269}
2270
2271
2272void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
2273 const u8 *prev_pending_bssid)
2274{
2275 /*
2276 * mac80211-workaround to force deauth on failed auth cmd,
2277 * requires us to remain in authenticating state to allow the
2278 * second authentication attempt to be continued properly.
2279 */
2280 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
2281 "to proceed after disconnection event");
2282 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
2283 os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
2284
2285 /*
2286 * Re-arm authentication timer in case auth fails for whatever reason.
2287 */
2288 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2289 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
2290 NULL);
2291}
2292
2293
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002294void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
2295{
2296 wpa_s->sme.prev_bssid_set = 0;
2297#ifdef CONFIG_SAE
2298 wpabuf_free(wpa_s->sme.sae_token);
2299 wpa_s->sme.sae_token = NULL;
2300 sae_clear_data(&wpa_s->sme.sae);
2301#endif /* CONFIG_SAE */
2302#ifdef CONFIG_IEEE80211R
Roshan Pius3a1667e2018-07-03 15:17:14 -07002303 if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002304 sme_update_ft_ies(wpa_s, NULL, NULL, 0);
2305#endif /* CONFIG_IEEE80211R */
Hai Shalom5f92bc92019-04-18 11:54:11 -07002306 sme_stop_sa_query(wpa_s);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002307}
2308
2309
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002310void sme_deinit(struct wpa_supplicant *wpa_s)
2311{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002312 sme_clear_on_disassoc(wpa_s);
Hai Shalomc3565922019-10-28 11:58:20 -07002313#ifdef CONFIG_SAE
2314 os_free(wpa_s->sme.sae_rejected_groups);
2315 wpa_s->sme.sae_rejected_groups = NULL;
2316#endif /* CONFIG_SAE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002317
2318 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2319 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002320 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
2321}
2322
2323
2324static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
2325 const u8 *chan_list, u8 num_channels,
2326 u8 num_intol)
2327{
2328 struct ieee80211_2040_bss_coex_ie *bc_ie;
2329 struct ieee80211_2040_intol_chan_report *ic_report;
2330 struct wpabuf *buf;
2331
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002332 wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
2333 " (num_channels=%u num_intol=%u)",
2334 MAC2STR(wpa_s->bssid), num_channels, num_intol);
2335 wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
2336 chan_list, num_channels);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002337
2338 buf = wpabuf_alloc(2 + /* action.category + action_code */
2339 sizeof(struct ieee80211_2040_bss_coex_ie) +
2340 sizeof(struct ieee80211_2040_intol_chan_report) +
2341 num_channels);
2342 if (buf == NULL)
2343 return;
2344
2345 wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
2346 wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
2347
2348 bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
2349 bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
2350 bc_ie->length = 1;
2351 if (num_intol)
2352 bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
2353
2354 if (num_channels > 0) {
2355 ic_report = wpabuf_put(buf, sizeof(*ic_report));
2356 ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
2357 ic_report->length = num_channels + 1;
2358 ic_report->op_class = 0;
2359 os_memcpy(wpabuf_put(buf, num_channels), chan_list,
2360 num_channels);
2361 }
2362
2363 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
2364 wpa_s->own_addr, wpa_s->bssid,
2365 wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
2366 wpa_msg(wpa_s, MSG_INFO,
2367 "SME: Failed to send 20/40 BSS Coexistence frame");
2368 }
2369
2370 wpabuf_free(buf);
2371}
2372
2373
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002374int sme_proc_obss_scan(struct wpa_supplicant *wpa_s,
2375 struct wpa_scan_results *scan_res)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002376{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002377 const u8 *ie;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002378 u8 chan_list[P2P_MAX_CHANNELS], channel;
2379 u8 num_channels = 0, num_intol = 0, i;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002380 size_t j;
2381 int pri_freq, sec_freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002382
2383 if (!wpa_s->sme.sched_obss_scan)
2384 return 0;
2385
2386 wpa_s->sme.sched_obss_scan = 0;
2387 if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
2388 return 1;
2389
2390 /*
2391 * Check whether AP uses regulatory triplet or channel triplet in
2392 * country info. Right now the operating class of the BSS channel
2393 * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
2394 * based on the assumption that operating class triplet is not used in
2395 * beacon frame. If the First Channel Number/Operating Extension
2396 * Identifier octet has a positive integer value of 201 or greater,
2397 * then its operating class triplet.
2398 *
2399 * TODO: If Supported Operating Classes element is present in beacon
2400 * frame, have to lookup operating class in Annex E and fill them in
2401 * 2040 coex frame.
2402 */
2403 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
2404 if (ie && (ie[1] >= 6) && (ie[5] >= 201))
2405 return 1;
2406
2407 os_memset(chan_list, 0, sizeof(chan_list));
2408
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002409 pri_freq = wpa_s->assoc_freq;
2410
2411 switch (wpa_s->sme.ht_sec_chan) {
2412 case HT_SEC_CHAN_ABOVE:
2413 sec_freq = pri_freq + 20;
2414 break;
2415 case HT_SEC_CHAN_BELOW:
2416 sec_freq = pri_freq - 20;
2417 break;
2418 case HT_SEC_CHAN_UNKNOWN:
2419 default:
2420 wpa_msg(wpa_s, MSG_WARNING,
2421 "Undefined secondary channel: drop OBSS scan results");
2422 return 1;
2423 }
2424
2425 for (j = 0; j < scan_res->num; j++) {
2426 struct wpa_scan_res *bss = scan_res->res[j];
Dmitry Shmidt4b060592013-04-29 16:42:49 -07002427 enum hostapd_hw_mode mode;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002428 int res;
2429
2430 /* Skip other band bss */
Dmitry Shmidt4b060592013-04-29 16:42:49 -07002431 mode = ieee80211_freq_to_chan(bss->freq, &channel);
2432 if (mode != HOSTAPD_MODE_IEEE80211G &&
2433 mode != HOSTAPD_MODE_IEEE80211B)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002434 continue;
2435
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08002436 res = check_bss_coex_40mhz(bss, pri_freq, sec_freq);
2437 if (res) {
2438 if (res == 2)
Dmitry Shmidtd11f0192014-03-24 12:09:47 -07002439 num_intol++;
2440
Dmitry Shmidt04949592012-07-19 12:16:46 -07002441 /* Check whether the channel is already considered */
2442 for (i = 0; i < num_channels; i++) {
2443 if (channel == chan_list[i])
2444 break;
2445 }
2446 if (i != num_channels)
2447 continue;
2448
Dmitry Shmidt04949592012-07-19 12:16:46 -07002449 chan_list[num_channels++] = channel;
2450 }
2451 }
2452
2453 sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
2454 return 1;
2455}
2456
2457
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002458static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
2459 struct wpa_driver_scan_params *params)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002460{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002461 /* Include only affected channels */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002462 struct hostapd_hw_modes *mode;
2463 int count, i;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002464 int start, end;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002465
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002466 mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
Hai Shalom60840252021-02-19 19:02:11 -08002467 HOSTAPD_MODE_IEEE80211G, false);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002468 if (mode == NULL) {
2469 /* No channels supported in this band - use empty list */
2470 params->freqs = os_zalloc(sizeof(int));
2471 return;
2472 }
2473
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002474 if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
2475 wpa_s->current_bss) {
2476 const u8 *ie;
2477
2478 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
2479 if (ie && ie[1] >= 2) {
2480 u8 o;
2481
2482 o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
2483 if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
2484 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
2485 else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
2486 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
2487 }
2488 }
2489
2490 start = wpa_s->assoc_freq - 10;
2491 end = wpa_s->assoc_freq + 10;
2492 switch (wpa_s->sme.ht_sec_chan) {
2493 case HT_SEC_CHAN_UNKNOWN:
2494 /* HT40+ possible on channels 1..9 */
2495 if (wpa_s->assoc_freq <= 2452)
2496 start -= 20;
2497 /* HT40- possible on channels 5-13 */
2498 if (wpa_s->assoc_freq >= 2432)
2499 end += 20;
2500 break;
2501 case HT_SEC_CHAN_ABOVE:
2502 end += 20;
2503 break;
2504 case HT_SEC_CHAN_BELOW:
2505 start -= 20;
2506 break;
2507 }
2508 wpa_printf(MSG_DEBUG,
2509 "OBSS: assoc_freq %d possible affected range %d-%d",
2510 wpa_s->assoc_freq, start, end);
2511
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002512 params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
Dmitry Shmidt04949592012-07-19 12:16:46 -07002513 if (params->freqs == NULL)
2514 return;
2515 for (count = 0, i = 0; i < mode->num_channels; i++) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002516 int freq;
2517
Dmitry Shmidt04949592012-07-19 12:16:46 -07002518 if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
2519 continue;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002520 freq = mode->channels[i].freq;
2521 if (freq - 10 >= end || freq + 10 <= start)
2522 continue; /* not affected */
2523 params->freqs[count++] = freq;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002524 }
2525}
2526
2527
2528static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
2529{
2530 struct wpa_supplicant *wpa_s = eloop_ctx;
2531 struct wpa_driver_scan_params params;
2532
2533 if (!wpa_s->current_bss) {
2534 wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
2535 return;
2536 }
2537
2538 os_memset(&params, 0, sizeof(params));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002539 wpa_obss_scan_freqs_list(wpa_s, &params);
Dmitry Shmidt2271d3f2014-06-23 12:16:31 -07002540 params.low_priority = 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002541 wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
2542
2543 if (wpa_supplicant_trigger_scan(wpa_s, &params))
2544 wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
2545 else
2546 wpa_s->sme.sched_obss_scan = 1;
2547 os_free(params.freqs);
2548
2549 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
2550 sme_obss_scan_timeout, wpa_s, NULL);
2551}
2552
2553
2554void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
2555{
2556 const u8 *ie;
2557 struct wpa_bss *bss = wpa_s->current_bss;
2558 struct wpa_ssid *ssid = wpa_s->current_ssid;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002559 struct hostapd_hw_modes *hw_mode = NULL;
2560 int i;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002561
2562 eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
2563 wpa_s->sme.sched_obss_scan = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002564 wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002565 if (!enable)
2566 return;
2567
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002568 /*
2569 * Schedule OBSS scan if driver is using station SME in wpa_supplicant
2570 * or it expects OBSS scan to be performed by wpa_supplicant.
2571 */
2572 if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
2573 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
Hai Shalom81f62d82019-07-22 12:10:00 -07002574 ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002575 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002576
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002577 if (!wpa_s->hw.modes)
2578 return;
2579
2580 /* only HT caps in 11g mode are relevant */
2581 for (i = 0; i < wpa_s->hw.num_modes; i++) {
2582 hw_mode = &wpa_s->hw.modes[i];
2583 if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
2584 break;
2585 }
2586
2587 /* Driver does not support HT40 for 11g or doesn't have 11g. */
2588 if (i == wpa_s->hw.num_modes || !hw_mode ||
2589 !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
2590 return;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002591
2592 if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
2593 return; /* Not associated on 2.4 GHz band */
2594
2595 /* Check whether AP supports HT40 */
2596 ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
2597 if (!ie || ie[1] < 2 ||
2598 !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
2599 return; /* AP does not support HT40 */
2600
2601 ie = wpa_bss_get_ie(wpa_s->current_bss,
2602 WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
2603 if (!ie || ie[1] < 14)
2604 return; /* AP does not request OBSS scans */
2605
2606 wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
2607 if (wpa_s->sme.obss_scan_int < 10) {
2608 wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
2609 "replaced with the minimum 10 sec",
2610 wpa_s->sme.obss_scan_int);
2611 wpa_s->sme.obss_scan_int = 10;
2612 }
2613 wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
2614 wpa_s->sme.obss_scan_int);
2615 eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
2616 sme_obss_scan_timeout, wpa_s, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617}
2618
2619
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620static const unsigned int sa_query_max_timeout = 1000;
2621static const unsigned int sa_query_retry_timeout = 201;
Hai Shalom74f70d42019-02-11 14:42:39 -08002622static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002623
2624static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
2625{
2626 u32 tu;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002627 struct os_reltime now, passed;
2628 os_get_reltime(&now);
2629 os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002630 tu = (passed.sec * 1000000 + passed.usec) / 1024;
2631 if (sa_query_max_timeout < tu) {
2632 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
2633 sme_stop_sa_query(wpa_s);
2634 wpa_supplicant_deauthenticate(
2635 wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
2636 return 1;
2637 }
2638
2639 return 0;
2640}
2641
2642
2643static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
2644 const u8 *trans_id)
2645{
Hai Shalom74f70d42019-02-11 14:42:39 -08002646 u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
2647 u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
2648
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002649 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
2650 MACSTR, MAC2STR(wpa_s->bssid));
2651 wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
2652 trans_id, WLAN_SA_QUERY_TR_ID_LEN);
2653 req[0] = WLAN_ACTION_SA_QUERY;
2654 req[1] = WLAN_SA_QUERY_REQUEST;
2655 os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
Hai Shalom74f70d42019-02-11 14:42:39 -08002656
2657#ifdef CONFIG_OCV
2658 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
2659 struct wpa_channel_info ci;
2660
2661 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
2662 wpa_printf(MSG_WARNING,
2663 "Failed to get channel info for OCI element in SA Query Request frame");
2664 return;
2665 }
2666
Hai Shalom899fcc72020-10-19 14:38:18 -07002667#ifdef CONFIG_TESTING_OPTIONS
2668 if (wpa_s->oci_freq_override_saquery_req) {
2669 wpa_printf(MSG_INFO,
2670 "TEST: Override SA Query Request OCI frequency %d -> %d MHz",
2671 ci.frequency,
2672 wpa_s->oci_freq_override_saquery_req);
2673 ci.frequency = wpa_s->oci_freq_override_saquery_req;
2674 }
2675#endif /* CONFIG_TESTING_OPTIONS */
2676
Hai Shalom74f70d42019-02-11 14:42:39 -08002677 if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
2678 return;
2679
2680 req_len += OCV_OCI_EXTENDED_LEN;
2681 }
2682#endif /* CONFIG_OCV */
2683
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
2685 wpa_s->own_addr, wpa_s->bssid,
Hai Shalom74f70d42019-02-11 14:42:39 -08002686 req, req_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
2688 "Request");
2689}
2690
2691
2692static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
2693{
2694 struct wpa_supplicant *wpa_s = eloop_ctx;
2695 unsigned int timeout, sec, usec;
2696 u8 *trans_id, *nbuf;
2697
2698 if (wpa_s->sme.sa_query_count > 0 &&
2699 sme_check_sa_query_timeout(wpa_s))
2700 return;
2701
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002702 nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
2703 wpa_s->sme.sa_query_count + 1,
2704 WLAN_SA_QUERY_TR_ID_LEN);
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002705 if (nbuf == NULL) {
2706 sme_stop_sa_query(wpa_s);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002707 return;
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002708 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 if (wpa_s->sme.sa_query_count == 0) {
2710 /* Starting a new SA Query procedure */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002711 os_get_reltime(&wpa_s->sme.sa_query_start);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002712 }
2713 trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
2714 wpa_s->sme.sa_query_trans_id = nbuf;
2715 wpa_s->sme.sa_query_count++;
2716
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002717 if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
2718 wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002719 sme_stop_sa_query(wpa_s);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002720 return;
2721 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722
2723 timeout = sa_query_retry_timeout;
2724 sec = ((timeout / 1000) * 1024) / 1000;
2725 usec = (timeout % 1000) * 1024;
2726 eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
2727
2728 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
2729 wpa_s->sme.sa_query_count);
2730
2731 sme_send_sa_query_req(wpa_s, trans_id);
2732}
2733
2734
2735static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
2736{
2737 sme_sa_query_timer(wpa_s, NULL);
2738}
2739
2740
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002741static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742{
Hai Shalom5f92bc92019-04-18 11:54:11 -07002743 if (wpa_s->sme.sa_query_trans_id)
2744 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002745 eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
2746 os_free(wpa_s->sme.sa_query_trans_id);
2747 wpa_s->sme.sa_query_trans_id = NULL;
2748 wpa_s->sme.sa_query_count = 0;
2749}
2750
2751
2752void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
2753 const u8 *da, u16 reason_code)
2754{
2755 struct wpa_ssid *ssid;
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002756 struct os_reltime now;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002758 if (wpa_s->wpa_state != WPA_COMPLETED)
2759 return;
2760 ssid = wpa_s->current_ssid;
Dmitry Shmidt807291d2015-01-27 13:40:23 -08002761 if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002762 return;
2763 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
2764 return;
2765 if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
2766 reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
2767 return;
2768 if (wpa_s->sme.sa_query_count > 0)
2769 return;
Hai Shalomfdcde762020-04-02 11:19:20 -07002770#ifdef CONFIG_TESTING_OPTIONS
2771 if (wpa_s->disable_sa_query)
2772 return;
2773#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002774
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002775 os_get_reltime(&now);
2776 if (wpa_s->sme.last_unprot_disconnect.sec &&
2777 !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
2778 return; /* limit SA Query procedure frequency */
2779 wpa_s->sme.last_unprot_disconnect = now;
2780
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002781 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
2782 "possible AP/STA state mismatch - trigger SA Query");
2783 sme_start_sa_query(wpa_s);
2784}
2785
2786
Hai Shalom74f70d42019-02-11 14:42:39 -08002787void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
2788{
2789 unsigned int usec;
2790 u32 _rand;
2791
2792 if (wpa_s->wpa_state != WPA_COMPLETED ||
2793 !wpa_sm_ocv_enabled(wpa_s->wpa))
2794 return;
2795
2796 wpa_dbg(wpa_s, MSG_DEBUG,
2797 "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
2798 sme_stop_sa_query(wpa_s);
2799
2800 if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
2801 _rand = os_random();
2802 usec = _rand % (sa_query_ch_switch_max_delay + 1);
2803 eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
2804}
2805
2806
2807static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
2808 const u8 *sa, const u8 *data,
2809 size_t len)
2810{
2811 u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
2812 u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
2813
2814 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
2815 MACSTR, MAC2STR(wpa_s->bssid));
2816
2817 resp[0] = WLAN_ACTION_SA_QUERY;
2818 resp[1] = WLAN_SA_QUERY_RESPONSE;
2819 os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
2820
2821#ifdef CONFIG_OCV
2822 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
2823 struct wpa_channel_info ci;
2824
2825 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
2826 wpa_printf(MSG_WARNING,
2827 "Failed to get channel info for OCI element in SA Query Response frame");
2828 return;
2829 }
2830
Hai Shalom899fcc72020-10-19 14:38:18 -07002831#ifdef CONFIG_TESTING_OPTIONS
2832 if (wpa_s->oci_freq_override_saquery_resp) {
2833 wpa_printf(MSG_INFO,
2834 "TEST: Override SA Query Response OCI frequency %d -> %d MHz",
2835 ci.frequency,
2836 wpa_s->oci_freq_override_saquery_resp);
2837 ci.frequency = wpa_s->oci_freq_override_saquery_resp;
2838 }
2839#endif /* CONFIG_TESTING_OPTIONS */
2840
Hai Shalom74f70d42019-02-11 14:42:39 -08002841 if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
2842 return;
2843
2844 resp_len += OCV_OCI_EXTENDED_LEN;
2845 }
2846#endif /* CONFIG_OCV */
2847
2848 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
2849 wpa_s->own_addr, wpa_s->bssid,
2850 resp, resp_len, 0) < 0)
2851 wpa_msg(wpa_s, MSG_INFO,
2852 "SME: Failed to send SA Query Response");
2853}
2854
2855
2856static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
2857 const u8 *sa, const u8 *data,
2858 size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002859{
2860 int i;
2861
Hai Shalom74f70d42019-02-11 14:42:39 -08002862 if (!wpa_s->sme.sa_query_trans_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002863 return;
Hai Shalom74f70d42019-02-11 14:42:39 -08002864
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002865 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
2866 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
2867
2868 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
2869 return;
2870
2871 for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
2872 if (os_memcmp(wpa_s->sme.sa_query_trans_id +
2873 i * WLAN_SA_QUERY_TR_ID_LEN,
2874 data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
2875 break;
2876 }
2877
2878 if (i >= wpa_s->sme.sa_query_count) {
2879 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
2880 "transaction identifier found");
2881 return;
2882 }
2883
2884 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
2885 "from " MACSTR, MAC2STR(sa));
2886 sme_stop_sa_query(wpa_s);
2887}
2888
Hai Shalom74f70d42019-02-11 14:42:39 -08002889
2890void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
2891 const u8 *data, size_t len)
2892{
2893 if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
2894 return;
2895
2896 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
2897 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
2898
2899#ifdef CONFIG_OCV
2900 if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
2901 struct ieee802_11_elems elems;
2902 struct wpa_channel_info ci;
2903
2904 if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
2905 len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
2906 &elems, 1) == ParseFailed) {
2907 wpa_printf(MSG_DEBUG,
2908 "SA Query: Failed to parse elements");
2909 return;
2910 }
2911
2912 if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
2913 wpa_printf(MSG_WARNING,
2914 "Failed to get channel info to validate received OCI in SA Query Action frame");
2915 return;
2916 }
2917
2918 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
2919 channel_width_to_int(ci.chanwidth),
Hai Shalom899fcc72020-10-19 14:38:18 -07002920 ci.seg1_idx) != OCI_SUCCESS) {
2921 wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR
2922 " frame=saquery%s error=%s",
2923 MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ?
2924 "req" : "resp", ocv_errorstr);
Hai Shalom74f70d42019-02-11 14:42:39 -08002925 return;
2926 }
2927 }
2928#endif /* CONFIG_OCV */
2929
2930 if (data[0] == WLAN_SA_QUERY_REQUEST)
2931 sme_process_sa_query_request(wpa_s, sa, data, len);
2932 else if (data[0] == WLAN_SA_QUERY_RESPONSE)
2933 sme_process_sa_query_response(wpa_s, sa, data, len);
2934}