1*03f9172cSAndroid Build Coastguard Worker /*
2*03f9172cSAndroid Build Coastguard Worker * wpa_supplicant - SME
3*03f9172cSAndroid Build Coastguard Worker * Copyright (c) 2009-2024, Jouni Malinen <[email protected]>
4*03f9172cSAndroid Build Coastguard Worker *
5*03f9172cSAndroid Build Coastguard Worker * This software may be distributed under the terms of the BSD license.
6*03f9172cSAndroid Build Coastguard Worker * See README for more details.
7*03f9172cSAndroid Build Coastguard Worker */
8*03f9172cSAndroid Build Coastguard Worker
9*03f9172cSAndroid Build Coastguard Worker #include "includes.h"
10*03f9172cSAndroid Build Coastguard Worker
11*03f9172cSAndroid Build Coastguard Worker #include "common.h"
12*03f9172cSAndroid Build Coastguard Worker #include "utils/eloop.h"
13*03f9172cSAndroid Build Coastguard Worker #include "utils/ext_password.h"
14*03f9172cSAndroid Build Coastguard Worker #include "common/ieee802_11_defs.h"
15*03f9172cSAndroid Build Coastguard Worker #include "common/ieee802_11_common.h"
16*03f9172cSAndroid Build Coastguard Worker #include "common/ocv.h"
17*03f9172cSAndroid Build Coastguard Worker #include "eapol_supp/eapol_supp_sm.h"
18*03f9172cSAndroid Build Coastguard Worker #include "common/wpa_common.h"
19*03f9172cSAndroid Build Coastguard Worker #include "common/sae.h"
20*03f9172cSAndroid Build Coastguard Worker #include "common/dpp.h"
21*03f9172cSAndroid Build Coastguard Worker #include "rsn_supp/wpa.h"
22*03f9172cSAndroid Build Coastguard Worker #include "rsn_supp/pmksa_cache.h"
23*03f9172cSAndroid Build Coastguard Worker #include "config.h"
24*03f9172cSAndroid Build Coastguard Worker #include "wpa_supplicant_i.h"
25*03f9172cSAndroid Build Coastguard Worker #include "driver_i.h"
26*03f9172cSAndroid Build Coastguard Worker #include "wpas_glue.h"
27*03f9172cSAndroid Build Coastguard Worker #include "wps_supplicant.h"
28*03f9172cSAndroid Build Coastguard Worker #include "p2p_supplicant.h"
29*03f9172cSAndroid Build Coastguard Worker #include "notify.h"
30*03f9172cSAndroid Build Coastguard Worker #include "bss.h"
31*03f9172cSAndroid Build Coastguard Worker #include "bssid_ignore.h"
32*03f9172cSAndroid Build Coastguard Worker #include "scan.h"
33*03f9172cSAndroid Build Coastguard Worker #include "sme.h"
34*03f9172cSAndroid Build Coastguard Worker #include "hs20_supplicant.h"
35*03f9172cSAndroid Build Coastguard Worker
36*03f9172cSAndroid Build Coastguard Worker #define SME_AUTH_TIMEOUT 5
37*03f9172cSAndroid Build Coastguard Worker #define SME_ASSOC_TIMEOUT 5
38*03f9172cSAndroid Build Coastguard Worker
39*03f9172cSAndroid Build Coastguard Worker static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
40*03f9172cSAndroid Build Coastguard Worker static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
41*03f9172cSAndroid Build Coastguard Worker static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
42*03f9172cSAndroid Build Coastguard Worker static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
43*03f9172cSAndroid Build Coastguard Worker
44*03f9172cSAndroid Build Coastguard Worker
45*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
46*03f9172cSAndroid Build Coastguard Worker
index_within_array(const int * array,int idx)47*03f9172cSAndroid Build Coastguard Worker static int index_within_array(const int *array, int idx)
48*03f9172cSAndroid Build Coastguard Worker {
49*03f9172cSAndroid Build Coastguard Worker int i;
50*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < idx; i++) {
51*03f9172cSAndroid Build Coastguard Worker if (array[i] <= 0)
52*03f9172cSAndroid Build Coastguard Worker return 0;
53*03f9172cSAndroid Build Coastguard Worker }
54*03f9172cSAndroid Build Coastguard Worker return 1;
55*03f9172cSAndroid Build Coastguard Worker }
56*03f9172cSAndroid Build Coastguard Worker
57*03f9172cSAndroid Build Coastguard Worker
sme_set_sae_group(struct wpa_supplicant * wpa_s,bool external)58*03f9172cSAndroid Build Coastguard Worker static int sme_set_sae_group(struct wpa_supplicant *wpa_s, bool external)
59*03f9172cSAndroid Build Coastguard Worker {
60*03f9172cSAndroid Build Coastguard Worker int *groups = wpa_s->conf->sae_groups;
61*03f9172cSAndroid Build Coastguard Worker int default_groups[] = { 19, 20, 21, 0 };
62*03f9172cSAndroid Build Coastguard Worker
63*03f9172cSAndroid Build Coastguard Worker if (!groups || groups[0] <= 0)
64*03f9172cSAndroid Build Coastguard Worker groups = default_groups;
65*03f9172cSAndroid Build Coastguard Worker
66*03f9172cSAndroid Build Coastguard Worker /* Configuration may have changed, so validate current index */
67*03f9172cSAndroid Build Coastguard Worker if (!index_within_array(groups, wpa_s->sme.sae_group_index))
68*03f9172cSAndroid Build Coastguard Worker return -1;
69*03f9172cSAndroid Build Coastguard Worker
70*03f9172cSAndroid Build Coastguard Worker for (;;) {
71*03f9172cSAndroid Build Coastguard Worker int group = groups[wpa_s->sme.sae_group_index];
72*03f9172cSAndroid Build Coastguard Worker if (group <= 0)
73*03f9172cSAndroid Build Coastguard Worker break;
74*03f9172cSAndroid Build Coastguard Worker if (!int_array_includes(wpa_s->sme.sae_rejected_groups,
75*03f9172cSAndroid Build Coastguard Worker group) &&
76*03f9172cSAndroid Build Coastguard Worker sae_set_group(&wpa_s->sme.sae, group) == 0) {
77*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
78*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.group);
79*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.akmp = external ?
80*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_key_mgmt : wpa_s->key_mgmt;
81*03f9172cSAndroid Build Coastguard Worker return 0;
82*03f9172cSAndroid Build Coastguard Worker }
83*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_group_index++;
84*03f9172cSAndroid Build Coastguard Worker }
85*03f9172cSAndroid Build Coastguard Worker
86*03f9172cSAndroid Build Coastguard Worker return -1;
87*03f9172cSAndroid Build Coastguard Worker }
88*03f9172cSAndroid Build Coastguard Worker
89*03f9172cSAndroid Build Coastguard Worker
sme_auth_build_sae_commit(struct wpa_supplicant * wpa_s,struct wpa_ssid * ssid,const u8 * bssid,const u8 * mld_addr,int external,int reuse,int * ret_use_pt,bool * ret_use_pk)90*03f9172cSAndroid Build Coastguard Worker static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
91*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid,
92*03f9172cSAndroid Build Coastguard Worker const u8 *bssid,
93*03f9172cSAndroid Build Coastguard Worker const u8 *mld_addr,
94*03f9172cSAndroid Build Coastguard Worker int external,
95*03f9172cSAndroid Build Coastguard Worker int reuse, int *ret_use_pt,
96*03f9172cSAndroid Build Coastguard Worker bool *ret_use_pk)
97*03f9172cSAndroid Build Coastguard Worker {
98*03f9172cSAndroid Build Coastguard Worker struct wpabuf *buf;
99*03f9172cSAndroid Build Coastguard Worker size_t len;
100*03f9172cSAndroid Build Coastguard Worker char *password = NULL;
101*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss;
102*03f9172cSAndroid Build Coastguard Worker int use_pt = 0;
103*03f9172cSAndroid Build Coastguard Worker bool use_pk = false;
104*03f9172cSAndroid Build Coastguard Worker u8 rsnxe_capa = 0;
105*03f9172cSAndroid Build Coastguard Worker int key_mgmt = external ? wpa_s->sme.ext_auth_key_mgmt :
106*03f9172cSAndroid Build Coastguard Worker wpa_s->key_mgmt;
107*03f9172cSAndroid Build Coastguard Worker const u8 *addr = mld_addr ? mld_addr : bssid;
108*03f9172cSAndroid Build Coastguard Worker
109*03f9172cSAndroid Build Coastguard Worker if (ret_use_pt)
110*03f9172cSAndroid Build Coastguard Worker *ret_use_pt = 0;
111*03f9172cSAndroid Build Coastguard Worker if (ret_use_pk)
112*03f9172cSAndroid Build Coastguard Worker *ret_use_pk = false;
113*03f9172cSAndroid Build Coastguard Worker
114*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
115*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sae_commit_override) {
116*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
117*03f9172cSAndroid Build Coastguard Worker buf = wpabuf_alloc(4 + wpabuf_len(wpa_s->sae_commit_override));
118*03f9172cSAndroid Build Coastguard Worker if (!buf)
119*03f9172cSAndroid Build Coastguard Worker goto fail;
120*03f9172cSAndroid Build Coastguard Worker if (!external) {
121*03f9172cSAndroid Build Coastguard Worker wpabuf_put_le16(buf, 1); /* Transaction seq# */
122*03f9172cSAndroid Build Coastguard Worker wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
123*03f9172cSAndroid Build Coastguard Worker }
124*03f9172cSAndroid Build Coastguard Worker wpabuf_put_buf(buf, wpa_s->sae_commit_override);
125*03f9172cSAndroid Build Coastguard Worker return buf;
126*03f9172cSAndroid Build Coastguard Worker }
127*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
128*03f9172cSAndroid Build Coastguard Worker
129*03f9172cSAndroid Build Coastguard Worker if (ssid->sae_password) {
130*03f9172cSAndroid Build Coastguard Worker password = os_strdup(ssid->sae_password);
131*03f9172cSAndroid Build Coastguard Worker if (!password) {
132*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_INFO,
133*03f9172cSAndroid Build Coastguard Worker "SAE: Failed to allocate password");
134*03f9172cSAndroid Build Coastguard Worker goto fail;
135*03f9172cSAndroid Build Coastguard Worker }
136*03f9172cSAndroid Build Coastguard Worker }
137*03f9172cSAndroid Build Coastguard Worker if (!password && ssid->passphrase) {
138*03f9172cSAndroid Build Coastguard Worker password = os_strdup(ssid->passphrase);
139*03f9172cSAndroid Build Coastguard Worker if (!password) {
140*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_INFO,
141*03f9172cSAndroid Build Coastguard Worker "SAE: Failed to allocate password");
142*03f9172cSAndroid Build Coastguard Worker goto fail;
143*03f9172cSAndroid Build Coastguard Worker }
144*03f9172cSAndroid Build Coastguard Worker }
145*03f9172cSAndroid Build Coastguard Worker if (!password && ssid->ext_psk) {
146*03f9172cSAndroid Build Coastguard Worker struct wpabuf *pw = ext_password_get(wpa_s->ext_pw,
147*03f9172cSAndroid Build Coastguard Worker ssid->ext_psk);
148*03f9172cSAndroid Build Coastguard Worker
149*03f9172cSAndroid Build Coastguard Worker if (!pw) {
150*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO,
151*03f9172cSAndroid Build Coastguard Worker "SAE: No password found from external storage");
152*03f9172cSAndroid Build Coastguard Worker goto fail;
153*03f9172cSAndroid Build Coastguard Worker }
154*03f9172cSAndroid Build Coastguard Worker
155*03f9172cSAndroid Build Coastguard Worker password = os_malloc(wpabuf_len(pw) + 1);
156*03f9172cSAndroid Build Coastguard Worker if (!password) {
157*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_INFO,
158*03f9172cSAndroid Build Coastguard Worker "SAE: Failed to allocate password");
159*03f9172cSAndroid Build Coastguard Worker goto fail;
160*03f9172cSAndroid Build Coastguard Worker }
161*03f9172cSAndroid Build Coastguard Worker os_memcpy(password, wpabuf_head(pw), wpabuf_len(pw));
162*03f9172cSAndroid Build Coastguard Worker password[wpabuf_len(pw)] = '\0';
163*03f9172cSAndroid Build Coastguard Worker ext_password_free(pw);
164*03f9172cSAndroid Build Coastguard Worker }
165*03f9172cSAndroid Build Coastguard Worker if (!password) {
166*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SAE: No password available");
167*03f9172cSAndroid Build Coastguard Worker goto fail;
168*03f9172cSAndroid Build Coastguard Worker }
169*03f9172cSAndroid Build Coastguard Worker
170*03f9172cSAndroid Build Coastguard Worker if (reuse && wpa_s->sme.sae.tmp &&
171*03f9172cSAndroid Build Coastguard Worker ether_addr_equal(addr, wpa_s->sme.sae.tmp->bssid)) {
172*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
173*03f9172cSAndroid Build Coastguard Worker "SAE: Reuse previously generated PWE on a retry with the same AP");
174*03f9172cSAndroid Build Coastguard Worker use_pt = wpa_s->sme.sae.h2e;
175*03f9172cSAndroid Build Coastguard Worker use_pk = wpa_s->sme.sae.pk;
176*03f9172cSAndroid Build Coastguard Worker goto reuse_data;
177*03f9172cSAndroid Build Coastguard Worker }
178*03f9172cSAndroid Build Coastguard Worker if (sme_set_sae_group(wpa_s, external) < 0) {
179*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
180*03f9172cSAndroid Build Coastguard Worker goto fail;
181*03f9172cSAndroid Build Coastguard Worker }
182*03f9172cSAndroid Build Coastguard Worker
183*03f9172cSAndroid Build Coastguard Worker bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
184*03f9172cSAndroid Build Coastguard Worker if (!bss) {
185*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
186*03f9172cSAndroid Build Coastguard Worker "SAE: BSS not available, update scan result to get BSS");
187*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_update_scan_results(wpa_s, bssid);
188*03f9172cSAndroid Build Coastguard Worker bss = wpa_bss_get_bssid_latest(wpa_s, bssid);
189*03f9172cSAndroid Build Coastguard Worker }
190*03f9172cSAndroid Build Coastguard Worker if (bss) {
191*03f9172cSAndroid Build Coastguard Worker const u8 *rsnxe;
192*03f9172cSAndroid Build Coastguard Worker
193*03f9172cSAndroid Build Coastguard Worker rsnxe = wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
194*03f9172cSAndroid Build Coastguard Worker if (rsnxe && rsnxe[0] == WLAN_EID_VENDOR_SPECIFIC &&
195*03f9172cSAndroid Build Coastguard Worker rsnxe[1] >= 1 + 4)
196*03f9172cSAndroid Build Coastguard Worker rsnxe_capa = rsnxe[2 + 4];
197*03f9172cSAndroid Build Coastguard Worker else if (rsnxe && rsnxe[1] >= 1)
198*03f9172cSAndroid Build Coastguard Worker rsnxe_capa = rsnxe[2];
199*03f9172cSAndroid Build Coastguard Worker }
200*03f9172cSAndroid Build Coastguard Worker
201*03f9172cSAndroid Build Coastguard Worker if (ssid->sae_password_id &&
202*03f9172cSAndroid Build Coastguard Worker wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
203*03f9172cSAndroid Build Coastguard Worker use_pt = 1;
204*03f9172cSAndroid Build Coastguard Worker if (wpa_key_mgmt_sae_ext_key(key_mgmt) &&
205*03f9172cSAndroid Build Coastguard Worker wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
206*03f9172cSAndroid Build Coastguard Worker use_pt = 1;
207*03f9172cSAndroid Build Coastguard Worker if (bss && is_6ghz_freq(bss->freq) &&
208*03f9172cSAndroid Build Coastguard Worker wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK)
209*03f9172cSAndroid Build Coastguard Worker use_pt = 1;
210*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE_PK
211*03f9172cSAndroid Build Coastguard Worker if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
212*03f9172cSAndroid Build Coastguard Worker ssid->sae_pk != SAE_PK_MODE_DISABLED &&
213*03f9172cSAndroid Build Coastguard Worker ((ssid->sae_password &&
214*03f9172cSAndroid Build Coastguard Worker sae_pk_valid_password(ssid->sae_password)) ||
215*03f9172cSAndroid Build Coastguard Worker (!ssid->sae_password && ssid->passphrase &&
216*03f9172cSAndroid Build Coastguard Worker sae_pk_valid_password(ssid->passphrase)))) {
217*03f9172cSAndroid Build Coastguard Worker use_pt = 1;
218*03f9172cSAndroid Build Coastguard Worker use_pk = true;
219*03f9172cSAndroid Build Coastguard Worker }
220*03f9172cSAndroid Build Coastguard Worker
221*03f9172cSAndroid Build Coastguard Worker if (ssid->sae_pk == SAE_PK_MODE_ONLY && !use_pk) {
222*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
223*03f9172cSAndroid Build Coastguard Worker "SAE: Cannot use PK with the selected AP");
224*03f9172cSAndroid Build Coastguard Worker goto fail;
225*03f9172cSAndroid Build Coastguard Worker }
226*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE_PK */
227*03f9172cSAndroid Build Coastguard Worker
228*03f9172cSAndroid Build Coastguard Worker if (use_pt || wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
229*03f9172cSAndroid Build Coastguard Worker wpa_s->conf->sae_pwe == SAE_PWE_BOTH) {
230*03f9172cSAndroid Build Coastguard Worker use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
231*03f9172cSAndroid Build Coastguard Worker
232*03f9172cSAndroid Build Coastguard Worker if ((wpa_s->conf->sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
233*03f9172cSAndroid Build Coastguard Worker ssid->sae_password_id ||
234*03f9172cSAndroid Build Coastguard Worker wpa_key_mgmt_sae_ext_key(key_mgmt)) &&
235*03f9172cSAndroid Build Coastguard Worker wpa_s->conf->sae_pwe != SAE_PWE_FORCE_HUNT_AND_PECK &&
236*03f9172cSAndroid Build Coastguard Worker !use_pt) {
237*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
238*03f9172cSAndroid Build Coastguard Worker "SAE: Cannot use H2E with the selected AP");
239*03f9172cSAndroid Build Coastguard Worker goto fail;
240*03f9172cSAndroid Build Coastguard Worker }
241*03f9172cSAndroid Build Coastguard Worker }
242*03f9172cSAndroid Build Coastguard Worker
243*03f9172cSAndroid Build Coastguard Worker if (use_pt && !ssid->pt)
244*03f9172cSAndroid Build Coastguard Worker wpa_s_setup_sae_pt(wpa_s->conf, ssid, true);
245*03f9172cSAndroid Build Coastguard Worker if (use_pt &&
246*03f9172cSAndroid Build Coastguard Worker sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt,
247*03f9172cSAndroid Build Coastguard Worker wpa_s->own_addr, addr,
248*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_rejected_groups, NULL) < 0)
249*03f9172cSAndroid Build Coastguard Worker goto fail;
250*03f9172cSAndroid Build Coastguard Worker if (!use_pt &&
251*03f9172cSAndroid Build Coastguard Worker sae_prepare_commit(wpa_s->own_addr, addr,
252*03f9172cSAndroid Build Coastguard Worker (u8 *) password, os_strlen(password),
253*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.sae) < 0) {
254*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
255*03f9172cSAndroid Build Coastguard Worker goto fail;
256*03f9172cSAndroid Build Coastguard Worker }
257*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sae.tmp) {
258*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.sae.tmp->bssid, addr, ETH_ALEN);
259*03f9172cSAndroid Build Coastguard Worker if (use_pt && use_pk)
260*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.pk = 1;
261*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE_PK
262*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr,
263*03f9172cSAndroid Build Coastguard Worker ETH_ALEN);
264*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.sae.tmp->peer_addr, addr, ETH_ALEN);
265*03f9172cSAndroid Build Coastguard Worker sae_pk_set_password(&wpa_s->sme.sae, password);
266*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE_PK */
267*03f9172cSAndroid Build Coastguard Worker }
268*03f9172cSAndroid Build Coastguard Worker
269*03f9172cSAndroid Build Coastguard Worker reuse_data:
270*03f9172cSAndroid Build Coastguard Worker len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0;
271*03f9172cSAndroid Build Coastguard Worker if (ssid->sae_password_id)
272*03f9172cSAndroid Build Coastguard Worker len += 4 + os_strlen(ssid->sae_password_id);
273*03f9172cSAndroid Build Coastguard Worker buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
274*03f9172cSAndroid Build Coastguard Worker if (buf == NULL)
275*03f9172cSAndroid Build Coastguard Worker goto fail;
276*03f9172cSAndroid Build Coastguard Worker if (!external) {
277*03f9172cSAndroid Build Coastguard Worker wpabuf_put_le16(buf, 1); /* Transaction seq# */
278*03f9172cSAndroid Build Coastguard Worker if (use_pk)
279*03f9172cSAndroid Build Coastguard Worker wpabuf_put_le16(buf, WLAN_STATUS_SAE_PK);
280*03f9172cSAndroid Build Coastguard Worker else if (use_pt)
281*03f9172cSAndroid Build Coastguard Worker wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT);
282*03f9172cSAndroid Build Coastguard Worker else
283*03f9172cSAndroid Build Coastguard Worker wpabuf_put_le16(buf,WLAN_STATUS_SUCCESS);
284*03f9172cSAndroid Build Coastguard Worker }
285*03f9172cSAndroid Build Coastguard Worker if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token,
286*03f9172cSAndroid Build Coastguard Worker ssid->sae_password_id) < 0) {
287*03f9172cSAndroid Build Coastguard Worker wpabuf_free(buf);
288*03f9172cSAndroid Build Coastguard Worker goto fail;
289*03f9172cSAndroid Build Coastguard Worker }
290*03f9172cSAndroid Build Coastguard Worker if (ret_use_pt)
291*03f9172cSAndroid Build Coastguard Worker *ret_use_pt = use_pt;
292*03f9172cSAndroid Build Coastguard Worker if (ret_use_pk)
293*03f9172cSAndroid Build Coastguard Worker *ret_use_pk = use_pk;
294*03f9172cSAndroid Build Coastguard Worker
295*03f9172cSAndroid Build Coastguard Worker str_clear_free(password);
296*03f9172cSAndroid Build Coastguard Worker return buf;
297*03f9172cSAndroid Build Coastguard Worker
298*03f9172cSAndroid Build Coastguard Worker fail:
299*03f9172cSAndroid Build Coastguard Worker str_clear_free(password);
300*03f9172cSAndroid Build Coastguard Worker return NULL;
301*03f9172cSAndroid Build Coastguard Worker }
302*03f9172cSAndroid Build Coastguard Worker
303*03f9172cSAndroid Build Coastguard Worker
sme_auth_build_sae_confirm(struct wpa_supplicant * wpa_s,int external)304*03f9172cSAndroid Build Coastguard Worker static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s,
305*03f9172cSAndroid Build Coastguard Worker int external)
306*03f9172cSAndroid Build Coastguard Worker {
307*03f9172cSAndroid Build Coastguard Worker struct wpabuf *buf;
308*03f9172cSAndroid Build Coastguard Worker
309*03f9172cSAndroid Build Coastguard Worker buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN);
310*03f9172cSAndroid Build Coastguard Worker if (buf == NULL)
311*03f9172cSAndroid Build Coastguard Worker return NULL;
312*03f9172cSAndroid Build Coastguard Worker
313*03f9172cSAndroid Build Coastguard Worker if (!external) {
314*03f9172cSAndroid Build Coastguard Worker wpabuf_put_le16(buf, 2); /* Transaction seq# */
315*03f9172cSAndroid Build Coastguard Worker wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
316*03f9172cSAndroid Build Coastguard Worker }
317*03f9172cSAndroid Build Coastguard Worker sae_write_confirm(&wpa_s->sme.sae, buf);
318*03f9172cSAndroid Build Coastguard Worker
319*03f9172cSAndroid Build Coastguard Worker return buf;
320*03f9172cSAndroid Build Coastguard Worker }
321*03f9172cSAndroid Build Coastguard Worker
322*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
323*03f9172cSAndroid Build Coastguard Worker
324*03f9172cSAndroid Build Coastguard Worker
325*03f9172cSAndroid Build Coastguard Worker /**
326*03f9172cSAndroid Build Coastguard Worker * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt
327*03f9172cSAndroid Build Coastguard Worker * @wpa_s: Pointer to wpa_supplicant data
328*03f9172cSAndroid Build Coastguard Worker * @bss: Pointer to the bss which is the target of authentication attempt
329*03f9172cSAndroid Build Coastguard Worker */
sme_auth_handle_rrm(struct wpa_supplicant * wpa_s,struct wpa_bss * bss)330*03f9172cSAndroid Build Coastguard Worker static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
331*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss)
332*03f9172cSAndroid Build Coastguard Worker {
333*03f9172cSAndroid Build Coastguard Worker const u8 rrm_ie_len = 5;
334*03f9172cSAndroid Build Coastguard Worker u8 *pos;
335*03f9172cSAndroid Build Coastguard Worker const u8 *rrm_ie;
336*03f9172cSAndroid Build Coastguard Worker
337*03f9172cSAndroid Build Coastguard Worker wpa_s->rrm.rrm_used = 0;
338*03f9172cSAndroid Build Coastguard Worker
339*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
340*03f9172cSAndroid Build Coastguard Worker "RRM: Determining whether RRM can be used - device support: 0x%x",
341*03f9172cSAndroid Build Coastguard Worker wpa_s->drv_rrm_flags);
342*03f9172cSAndroid Build Coastguard Worker
343*03f9172cSAndroid Build Coastguard Worker rrm_ie = wpa_bss_get_ie(bss, WLAN_EID_RRM_ENABLED_CAPABILITIES);
344*03f9172cSAndroid Build Coastguard Worker if (!rrm_ie || !(bss->caps & IEEE80211_CAP_RRM)) {
345*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "RRM: No RRM in network");
346*03f9172cSAndroid Build Coastguard Worker return;
347*03f9172cSAndroid Build Coastguard Worker }
348*03f9172cSAndroid Build Coastguard Worker
349*03f9172cSAndroid Build Coastguard Worker if (!((wpa_s->drv_rrm_flags &
350*03f9172cSAndroid Build Coastguard Worker WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) &&
351*03f9172cSAndroid Build Coastguard Worker (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) &&
352*03f9172cSAndroid Build Coastguard Worker !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_SUPPORT_RRM)) {
353*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
354*03f9172cSAndroid Build Coastguard Worker "RRM: Insufficient RRM support in driver - do not use RRM");
355*03f9172cSAndroid Build Coastguard Worker return;
356*03f9172cSAndroid Build Coastguard Worker }
357*03f9172cSAndroid Build Coastguard Worker
358*03f9172cSAndroid Build Coastguard Worker if (sizeof(wpa_s->sme.assoc_req_ie) <
359*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) {
360*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO,
361*03f9172cSAndroid Build Coastguard Worker "RRM: Unable to use RRM, no room for RRM IE");
362*03f9172cSAndroid Build Coastguard Worker return;
363*03f9172cSAndroid Build Coastguard Worker }
364*03f9172cSAndroid Build Coastguard Worker
365*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to Association Request");
366*03f9172cSAndroid Build Coastguard Worker pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
367*03f9172cSAndroid Build Coastguard Worker os_memset(pos, 0, 2 + rrm_ie_len);
368*03f9172cSAndroid Build Coastguard Worker *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
369*03f9172cSAndroid Build Coastguard Worker *pos++ = rrm_ie_len;
370*03f9172cSAndroid Build Coastguard Worker
371*03f9172cSAndroid Build Coastguard Worker /* Set supported capabilities flags */
372*03f9172cSAndroid Build Coastguard Worker if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
373*03f9172cSAndroid Build Coastguard Worker *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
374*03f9172cSAndroid Build Coastguard Worker
375*03f9172cSAndroid Build Coastguard Worker *pos |= WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
376*03f9172cSAndroid Build Coastguard Worker WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
377*03f9172cSAndroid Build Coastguard Worker WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
378*03f9172cSAndroid Build Coastguard Worker
379*03f9172cSAndroid Build Coastguard Worker if (wpa_s->lci)
380*03f9172cSAndroid Build Coastguard Worker pos[1] |= WLAN_RRM_CAPS_LCI_MEASUREMENT;
381*03f9172cSAndroid Build Coastguard Worker
382*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
383*03f9172cSAndroid Build Coastguard Worker wpa_s->rrm.rrm_used = 1;
384*03f9172cSAndroid Build Coastguard Worker }
385*03f9172cSAndroid Build Coastguard Worker
386*03f9172cSAndroid Build Coastguard Worker
wpas_ml_handle_removed_links(struct wpa_supplicant * wpa_s,struct wpa_bss * bss)387*03f9172cSAndroid Build Coastguard Worker static void wpas_ml_handle_removed_links(struct wpa_supplicant *wpa_s,
388*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss)
389*03f9172cSAndroid Build Coastguard Worker {
390*03f9172cSAndroid Build Coastguard Worker u16 removed_links = wpa_bss_parse_reconf_ml_element(wpa_s, bss);
391*03f9172cSAndroid Build Coastguard Worker
392*03f9172cSAndroid Build Coastguard Worker wpa_s->valid_links &= ~removed_links;
393*03f9172cSAndroid Build Coastguard Worker }
394*03f9172cSAndroid Build Coastguard Worker
395*03f9172cSAndroid Build Coastguard Worker
396*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
wpas_ml_connect_pref(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,struct wpa_ssid * ssid)397*03f9172cSAndroid Build Coastguard Worker static struct wpa_bss * wpas_ml_connect_pref(struct wpa_supplicant *wpa_s,
398*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss,
399*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid)
400*03f9172cSAndroid Build Coastguard Worker {
401*03f9172cSAndroid Build Coastguard Worker unsigned int low, high, i;
402*03f9172cSAndroid Build Coastguard Worker
403*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
404*03f9172cSAndroid Build Coastguard Worker "MLD: valid_links=%d, band_pref=%u, bssid_pref=" MACSTR,
405*03f9172cSAndroid Build Coastguard Worker wpa_s->valid_links,
406*03f9172cSAndroid Build Coastguard Worker wpa_s->conf->mld_connect_band_pref,
407*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->conf->mld_connect_bssid_pref));
408*03f9172cSAndroid Build Coastguard Worker
409*03f9172cSAndroid Build Coastguard Worker /* Check if there are more than one link */
410*03f9172cSAndroid Build Coastguard Worker if (!(wpa_s->valid_links & (wpa_s->valid_links - 1)))
411*03f9172cSAndroid Build Coastguard Worker return bss;
412*03f9172cSAndroid Build Coastguard Worker
413*03f9172cSAndroid Build Coastguard Worker if (!is_zero_ether_addr(wpa_s->conf->mld_connect_bssid_pref)) {
414*03f9172cSAndroid Build Coastguard Worker for_each_link(wpa_s->valid_links, i) {
415*03f9172cSAndroid Build Coastguard Worker if (wpa_s->mlo_assoc_link_id == i)
416*03f9172cSAndroid Build Coastguard Worker continue;
417*03f9172cSAndroid Build Coastguard Worker
418*03f9172cSAndroid Build Coastguard Worker if (ether_addr_equal(
419*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].bssid,
420*03f9172cSAndroid Build Coastguard Worker wpa_s->conf->mld_connect_bssid_pref))
421*03f9172cSAndroid Build Coastguard Worker goto found;
422*03f9172cSAndroid Build Coastguard Worker }
423*03f9172cSAndroid Build Coastguard Worker }
424*03f9172cSAndroid Build Coastguard Worker
425*03f9172cSAndroid Build Coastguard Worker if (wpa_s->conf->mld_connect_band_pref == MLD_CONNECT_BAND_PREF_AUTO)
426*03f9172cSAndroid Build Coastguard Worker return bss;
427*03f9172cSAndroid Build Coastguard Worker
428*03f9172cSAndroid Build Coastguard Worker switch (wpa_s->conf->mld_connect_band_pref) {
429*03f9172cSAndroid Build Coastguard Worker case MLD_CONNECT_BAND_PREF_2GHZ:
430*03f9172cSAndroid Build Coastguard Worker low = 2412;
431*03f9172cSAndroid Build Coastguard Worker high = 2472;
432*03f9172cSAndroid Build Coastguard Worker break;
433*03f9172cSAndroid Build Coastguard Worker case MLD_CONNECT_BAND_PREF_5GHZ:
434*03f9172cSAndroid Build Coastguard Worker low = 5180;
435*03f9172cSAndroid Build Coastguard Worker high = 5985;
436*03f9172cSAndroid Build Coastguard Worker break;
437*03f9172cSAndroid Build Coastguard Worker case MLD_CONNECT_BAND_PREF_6GHZ:
438*03f9172cSAndroid Build Coastguard Worker low = 5955;
439*03f9172cSAndroid Build Coastguard Worker high = 7125;
440*03f9172cSAndroid Build Coastguard Worker break;
441*03f9172cSAndroid Build Coastguard Worker default:
442*03f9172cSAndroid Build Coastguard Worker return bss;
443*03f9172cSAndroid Build Coastguard Worker }
444*03f9172cSAndroid Build Coastguard Worker
445*03f9172cSAndroid Build Coastguard Worker for_each_link(wpa_s->valid_links, i) {
446*03f9172cSAndroid Build Coastguard Worker if (wpa_s->mlo_assoc_link_id == i)
447*03f9172cSAndroid Build Coastguard Worker continue;
448*03f9172cSAndroid Build Coastguard Worker
449*03f9172cSAndroid Build Coastguard Worker if (wpa_s->links[i].freq >= low && wpa_s->links[i].freq <= high)
450*03f9172cSAndroid Build Coastguard Worker goto found;
451*03f9172cSAndroid Build Coastguard Worker }
452*03f9172cSAndroid Build Coastguard Worker
453*03f9172cSAndroid Build Coastguard Worker found:
454*03f9172cSAndroid Build Coastguard Worker if (i == MAX_NUM_MLD_LINKS) {
455*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: No match for connect/band pref");
456*03f9172cSAndroid Build Coastguard Worker return bss;
457*03f9172cSAndroid Build Coastguard Worker }
458*03f9172cSAndroid Build Coastguard Worker
459*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
460*03f9172cSAndroid Build Coastguard Worker "MLD: Change BSS for connect: " MACSTR " -> " MACSTR,
461*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->links[wpa_s->mlo_assoc_link_id].bssid),
462*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->links[i].bssid));
463*03f9172cSAndroid Build Coastguard Worker
464*03f9172cSAndroid Build Coastguard Worker /* Get the BSS entry and do the switch */
465*03f9172cSAndroid Build Coastguard Worker if (ssid && ssid->ssid_len)
466*03f9172cSAndroid Build Coastguard Worker bss = wpa_bss_get(wpa_s, wpa_s->links[i].bssid, ssid->ssid,
467*03f9172cSAndroid Build Coastguard Worker ssid->ssid_len);
468*03f9172cSAndroid Build Coastguard Worker else
469*03f9172cSAndroid Build Coastguard Worker bss = wpa_bss_get_bssid(wpa_s, wpa_s->links[i].bssid);
470*03f9172cSAndroid Build Coastguard Worker wpa_s->mlo_assoc_link_id = i;
471*03f9172cSAndroid Build Coastguard Worker
472*03f9172cSAndroid Build Coastguard Worker return bss;
473*03f9172cSAndroid Build Coastguard Worker }
474*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
475*03f9172cSAndroid Build Coastguard Worker
476*03f9172cSAndroid Build Coastguard Worker
wpas_sme_ml_auth(struct wpa_supplicant * wpa_s,union wpa_event_data * data,int ie_offset)477*03f9172cSAndroid Build Coastguard Worker static int wpas_sme_ml_auth(struct wpa_supplicant *wpa_s,
478*03f9172cSAndroid Build Coastguard Worker union wpa_event_data *data,
479*03f9172cSAndroid Build Coastguard Worker int ie_offset)
480*03f9172cSAndroid Build Coastguard Worker {
481*03f9172cSAndroid Build Coastguard Worker struct ieee802_11_elems elems;
482*03f9172cSAndroid Build Coastguard Worker const u8 *mld_addr;
483*03f9172cSAndroid Build Coastguard Worker u16 status_code = data->auth.status_code;
484*03f9172cSAndroid Build Coastguard Worker
485*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->valid_links)
486*03f9172cSAndroid Build Coastguard Worker return 0;
487*03f9172cSAndroid Build Coastguard Worker
488*03f9172cSAndroid Build Coastguard Worker if (ieee802_11_parse_elems(data->auth.ies + ie_offset,
489*03f9172cSAndroid Build Coastguard Worker data->auth.ies_len - ie_offset,
490*03f9172cSAndroid Build Coastguard Worker &elems, 0) == ParseFailed) {
491*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
492*03f9172cSAndroid Build Coastguard Worker return -1;
493*03f9172cSAndroid Build Coastguard Worker }
494*03f9172cSAndroid Build Coastguard Worker
495*03f9172cSAndroid Build Coastguard Worker if (!elems.basic_mle || !elems.basic_mle_len) {
496*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
497*03f9172cSAndroid Build Coastguard Worker if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
498*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_SUCCESS ||
499*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
500*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_SAE_PK)
501*03f9172cSAndroid Build Coastguard Worker return -1;
502*03f9172cSAndroid Build Coastguard Worker /* Accept missing Multi-Link element in failed authentication
503*03f9172cSAndroid Build Coastguard Worker * cases. */
504*03f9172cSAndroid Build Coastguard Worker return 0;
505*03f9172cSAndroid Build Coastguard Worker }
506*03f9172cSAndroid Build Coastguard Worker
507*03f9172cSAndroid Build Coastguard Worker mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
508*03f9172cSAndroid Build Coastguard Worker if (!mld_addr)
509*03f9172cSAndroid Build Coastguard Worker return -1;
510*03f9172cSAndroid Build Coastguard Worker
511*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
512*03f9172cSAndroid Build Coastguard Worker
513*03f9172cSAndroid Build Coastguard Worker if (!ether_addr_equal(wpa_s->ap_mld_addr, mld_addr)) {
514*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
515*03f9172cSAndroid Build Coastguard Worker MACSTR ")", MAC2STR(wpa_s->ap_mld_addr));
516*03f9172cSAndroid Build Coastguard Worker return -1;
517*03f9172cSAndroid Build Coastguard Worker }
518*03f9172cSAndroid Build Coastguard Worker
519*03f9172cSAndroid Build Coastguard Worker return 0;
520*03f9172cSAndroid Build Coastguard Worker }
521*03f9172cSAndroid Build Coastguard Worker
522*03f9172cSAndroid Build Coastguard Worker
wpas_sme_set_mlo_links(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,struct wpa_ssid * ssid)523*03f9172cSAndroid Build Coastguard Worker static void wpas_sme_set_mlo_links(struct wpa_supplicant *wpa_s,
524*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss, struct wpa_ssid *ssid)
525*03f9172cSAndroid Build Coastguard Worker {
526*03f9172cSAndroid Build Coastguard Worker u8 i;
527*03f9172cSAndroid Build Coastguard Worker
528*03f9172cSAndroid Build Coastguard Worker wpa_s->valid_links = 0;
529*03f9172cSAndroid Build Coastguard Worker wpa_s->mlo_assoc_link_id = bss->mld_link_id;
530*03f9172cSAndroid Build Coastguard Worker
531*03f9172cSAndroid Build Coastguard Worker for_each_link(bss->valid_links, i) {
532*03f9172cSAndroid Build Coastguard Worker const u8 *bssid = bss->mld_links[i].bssid;
533*03f9172cSAndroid Build Coastguard Worker
534*03f9172cSAndroid Build Coastguard Worker wpa_s->valid_links |= BIT(i);
535*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->links[i].bssid, bssid, ETH_ALEN);
536*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].freq = bss->mld_links[i].freq;
537*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].disabled = bss->mld_links[i].disabled;
538*03f9172cSAndroid Build Coastguard Worker
539*03f9172cSAndroid Build Coastguard Worker if (bss->mld_link_id == i)
540*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].bss = bss;
541*03f9172cSAndroid Build Coastguard Worker else if (ssid && ssid->ssid_len)
542*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].bss = wpa_bss_get(wpa_s, bssid,
543*03f9172cSAndroid Build Coastguard Worker ssid->ssid,
544*03f9172cSAndroid Build Coastguard Worker ssid->ssid_len);
545*03f9172cSAndroid Build Coastguard Worker else
546*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].bss = wpa_bss_get_bssid(wpa_s, bssid);
547*03f9172cSAndroid Build Coastguard Worker }
548*03f9172cSAndroid Build Coastguard Worker }
549*03f9172cSAndroid Build Coastguard Worker
550*03f9172cSAndroid Build Coastguard Worker
sme_send_authentication(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,struct wpa_ssid * ssid,int start)551*03f9172cSAndroid Build Coastguard Worker static void sme_send_authentication(struct wpa_supplicant *wpa_s,
552*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss, struct wpa_ssid *ssid,
553*03f9172cSAndroid Build Coastguard Worker int start)
554*03f9172cSAndroid Build Coastguard Worker {
555*03f9172cSAndroid Build Coastguard Worker struct wpa_driver_auth_params params;
556*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *old_ssid;
557*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R
558*03f9172cSAndroid Build Coastguard Worker const u8 *ie;
559*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R */
560*03f9172cSAndroid Build Coastguard Worker #if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS)
561*03f9172cSAndroid Build Coastguard Worker const u8 *md = NULL;
562*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R || CONFIG_FILS */
563*03f9172cSAndroid Build Coastguard Worker int bssid_changed;
564*03f9172cSAndroid Build Coastguard Worker struct wpabuf *resp = NULL;
565*03f9172cSAndroid Build Coastguard Worker u8 ext_capab[18];
566*03f9172cSAndroid Build Coastguard Worker int ext_capab_len;
567*03f9172cSAndroid Build Coastguard Worker int skip_auth;
568*03f9172cSAndroid Build Coastguard Worker u8 *wpa_ie;
569*03f9172cSAndroid Build Coastguard Worker size_t wpa_ie_len;
570*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_MBO
571*03f9172cSAndroid Build Coastguard Worker const u8 *mbo_ie;
572*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_MBO */
573*03f9172cSAndroid Build Coastguard Worker int omit_rsnxe = 0;
574*03f9172cSAndroid Build Coastguard Worker
575*03f9172cSAndroid Build Coastguard Worker if (bss == NULL) {
576*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
577*03f9172cSAndroid Build Coastguard Worker "the network");
578*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
579*03f9172cSAndroid Build Coastguard Worker return;
580*03f9172cSAndroid Build Coastguard Worker }
581*03f9172cSAndroid Build Coastguard Worker
582*03f9172cSAndroid Build Coastguard Worker os_memset(¶ms, 0, sizeof(params));
583*03f9172cSAndroid Build Coastguard Worker
584*03f9172cSAndroid Build Coastguard Worker if ((wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_MLO) &&
585*03f9172cSAndroid Build Coastguard Worker !wpa_bss_parse_basic_ml_element(wpa_s, bss, wpa_s->ap_mld_addr,
586*03f9172cSAndroid Build Coastguard Worker NULL, ssid, NULL) &&
587*03f9172cSAndroid Build Coastguard Worker bss->valid_links) {
588*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: In authentication");
589*03f9172cSAndroid Build Coastguard Worker wpas_sme_set_mlo_links(wpa_s, bss, ssid);
590*03f9172cSAndroid Build Coastguard Worker
591*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
592*03f9172cSAndroid Build Coastguard Worker bss = wpas_ml_connect_pref(wpa_s, bss, ssid);
593*03f9172cSAndroid Build Coastguard Worker
594*03f9172cSAndroid Build Coastguard Worker if (wpa_s->conf->mld_force_single_link) {
595*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: Force single link");
596*03f9172cSAndroid Build Coastguard Worker wpa_s->valid_links = BIT(wpa_s->mlo_assoc_link_id);
597*03f9172cSAndroid Build Coastguard Worker }
598*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
599*03f9172cSAndroid Build Coastguard Worker params.mld = true;
600*03f9172cSAndroid Build Coastguard Worker params.mld_link_id = wpa_s->mlo_assoc_link_id;
601*03f9172cSAndroid Build Coastguard Worker params.ap_mld_addr = wpa_s->ap_mld_addr;
602*03f9172cSAndroid Build Coastguard Worker wpas_ml_handle_removed_links(wpa_s, bss);
603*03f9172cSAndroid Build Coastguard Worker }
604*03f9172cSAndroid Build Coastguard Worker
605*03f9172cSAndroid Build Coastguard Worker skip_auth = wpa_s->conf->reassoc_same_bss_optim &&
606*03f9172cSAndroid Build Coastguard Worker wpa_s->reassoc_same_bss;
607*03f9172cSAndroid Build Coastguard Worker wpa_s->current_bss = bss;
608*03f9172cSAndroid Build Coastguard Worker
609*03f9172cSAndroid Build Coastguard Worker wpa_s->reassociate = 0;
610*03f9172cSAndroid Build Coastguard Worker
611*03f9172cSAndroid Build Coastguard Worker params.freq = bss->freq;
612*03f9172cSAndroid Build Coastguard Worker params.bssid = bss->bssid;
613*03f9172cSAndroid Build Coastguard Worker params.ssid = bss->ssid;
614*03f9172cSAndroid Build Coastguard Worker params.ssid_len = bss->ssid_len;
615*03f9172cSAndroid Build Coastguard Worker params.p2p = ssid->p2p_group;
616*03f9172cSAndroid Build Coastguard Worker
617*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.ssid_len != params.ssid_len ||
618*03f9172cSAndroid Build Coastguard Worker os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
619*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.prev_bssid_set = 0;
620*03f9172cSAndroid Build Coastguard Worker
621*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.freq = params.freq;
622*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
623*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ssid_len = params.ssid_len;
624*03f9172cSAndroid Build Coastguard Worker
625*03f9172cSAndroid Build Coastguard Worker params.auth_alg = WPA_AUTH_ALG_OPEN;
626*03f9172cSAndroid Build Coastguard Worker #ifdef IEEE8021X_EAPOL
627*03f9172cSAndroid Build Coastguard Worker if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
628*03f9172cSAndroid Build Coastguard Worker if (ssid->leap) {
629*03f9172cSAndroid Build Coastguard Worker if (ssid->non_leap == 0)
630*03f9172cSAndroid Build Coastguard Worker params.auth_alg = WPA_AUTH_ALG_LEAP;
631*03f9172cSAndroid Build Coastguard Worker else
632*03f9172cSAndroid Build Coastguard Worker params.auth_alg |= WPA_AUTH_ALG_LEAP;
633*03f9172cSAndroid Build Coastguard Worker }
634*03f9172cSAndroid Build Coastguard Worker }
635*03f9172cSAndroid Build Coastguard Worker #endif /* IEEE8021X_EAPOL */
636*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
637*03f9172cSAndroid Build Coastguard Worker params.auth_alg);
638*03f9172cSAndroid Build Coastguard Worker if (ssid->auth_alg) {
639*03f9172cSAndroid Build Coastguard Worker params.auth_alg = ssid->auth_alg;
640*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
641*03f9172cSAndroid Build Coastguard Worker "0x%x", params.auth_alg);
642*03f9172cSAndroid Build Coastguard Worker }
643*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
644*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_pmksa_caching = 0;
645*03f9172cSAndroid Build Coastguard Worker if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
646*03f9172cSAndroid Build Coastguard Worker const u8 *rsn;
647*03f9172cSAndroid Build Coastguard Worker struct wpa_ie_data ied;
648*03f9172cSAndroid Build Coastguard Worker
649*03f9172cSAndroid Build Coastguard Worker rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
650*03f9172cSAndroid Build Coastguard Worker if (!rsn) {
651*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
652*03f9172cSAndroid Build Coastguard Worker "SAE enabled, but target BSS does not advertise RSN");
653*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
654*03f9172cSAndroid Build Coastguard Worker } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
655*03f9172cSAndroid Build Coastguard Worker (ssid->key_mgmt & WPA_KEY_MGMT_DPP) &&
656*03f9172cSAndroid Build Coastguard Worker (ied.key_mgmt & WPA_KEY_MGMT_DPP)) {
657*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "Prefer DPP over SAE when both are enabled");
658*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
659*03f9172cSAndroid Build Coastguard Worker } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
660*03f9172cSAndroid Build Coastguard Worker wpa_key_mgmt_sae(ied.key_mgmt)) {
661*03f9172cSAndroid Build Coastguard Worker if (wpas_is_sae_avoided(wpa_s, ssid, &ied)) {
662*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
663*03f9172cSAndroid Build Coastguard Worker "SAE enabled, but disallowing SAE auth_alg without PMF");
664*03f9172cSAndroid Build Coastguard Worker } else {
665*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
666*03f9172cSAndroid Build Coastguard Worker params.auth_alg = WPA_AUTH_ALG_SAE;
667*03f9172cSAndroid Build Coastguard Worker }
668*03f9172cSAndroid Build Coastguard Worker } else {
669*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
670*03f9172cSAndroid Build Coastguard Worker "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
671*03f9172cSAndroid Build Coastguard Worker }
672*03f9172cSAndroid Build Coastguard Worker }
673*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
674*03f9172cSAndroid Build Coastguard Worker
675*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WEP
676*03f9172cSAndroid Build Coastguard Worker {
677*03f9172cSAndroid Build Coastguard Worker int i;
678*03f9172cSAndroid Build Coastguard Worker
679*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < NUM_WEP_KEYS; i++) {
680*03f9172cSAndroid Build Coastguard Worker if (ssid->wep_key_len[i])
681*03f9172cSAndroid Build Coastguard Worker params.wep_key[i] = ssid->wep_key[i];
682*03f9172cSAndroid Build Coastguard Worker params.wep_key_len[i] = ssid->wep_key_len[i];
683*03f9172cSAndroid Build Coastguard Worker }
684*03f9172cSAndroid Build Coastguard Worker params.wep_tx_keyidx = ssid->wep_tx_keyidx;
685*03f9172cSAndroid Build Coastguard Worker }
686*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WEP */
687*03f9172cSAndroid Build Coastguard Worker
688*03f9172cSAndroid Build Coastguard Worker if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
689*03f9172cSAndroid Build Coastguard Worker wpa_bss_get_rsne(wpa_s, bss, ssid, false)) &&
690*03f9172cSAndroid Build Coastguard Worker wpa_key_mgmt_wpa(ssid->key_mgmt)) {
691*03f9172cSAndroid Build Coastguard Worker int try_opportunistic;
692*03f9172cSAndroid Build Coastguard Worker const u8 *cache_id = NULL;
693*03f9172cSAndroid Build Coastguard Worker
694*03f9172cSAndroid Build Coastguard Worker try_opportunistic = (ssid->proactive_key_caching < 0 ?
695*03f9172cSAndroid Build Coastguard Worker wpa_s->conf->okc :
696*03f9172cSAndroid Build Coastguard Worker ssid->proactive_key_caching) &&
697*03f9172cSAndroid Build Coastguard Worker (ssid->proto & WPA_PROTO_RSN);
698*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FILS
699*03f9172cSAndroid Build Coastguard Worker if (wpa_key_mgmt_fils(ssid->key_mgmt))
700*03f9172cSAndroid Build Coastguard Worker cache_id = wpa_bss_get_fils_cache_id(bss);
701*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FILS */
702*03f9172cSAndroid Build Coastguard Worker if (pmksa_cache_set_current(wpa_s->wpa, NULL,
703*03f9172cSAndroid Build Coastguard Worker params.mld ? params.ap_mld_addr :
704*03f9172cSAndroid Build Coastguard Worker bss->bssid,
705*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid,
706*03f9172cSAndroid Build Coastguard Worker try_opportunistic, cache_id,
707*03f9172cSAndroid Build Coastguard Worker 0, false) == 0)
708*03f9172cSAndroid Build Coastguard Worker eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
709*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
710*03f9172cSAndroid Build Coastguard Worker if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
711*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
712*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
713*03f9172cSAndroid Build Coastguard Worker false)) {
714*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
715*03f9172cSAndroid Build Coastguard Worker "key management and encryption suites");
716*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
717*03f9172cSAndroid Build Coastguard Worker return;
718*03f9172cSAndroid Build Coastguard Worker }
719*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_HS20
720*03f9172cSAndroid Build Coastguard Worker } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
721*03f9172cSAndroid Build Coastguard Worker (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
722*03f9172cSAndroid Build Coastguard Worker /* No PMKSA caching, but otherwise similar to RSN/WPA */
723*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
724*03f9172cSAndroid Build Coastguard Worker if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
725*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
726*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
727*03f9172cSAndroid Build Coastguard Worker false)) {
728*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
729*03f9172cSAndroid Build Coastguard Worker "key management and encryption suites");
730*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
731*03f9172cSAndroid Build Coastguard Worker return;
732*03f9172cSAndroid Build Coastguard Worker }
733*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_HS20 */
734*03f9172cSAndroid Build Coastguard Worker } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
735*03f9172cSAndroid Build Coastguard Worker wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
736*03f9172cSAndroid Build Coastguard Worker /*
737*03f9172cSAndroid Build Coastguard Worker * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
738*03f9172cSAndroid Build Coastguard Worker * use non-WPA since the scan results did not indicate that the
739*03f9172cSAndroid Build Coastguard Worker * AP is using WPA or WPA2.
740*03f9172cSAndroid Build Coastguard Worker */
741*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
742*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len = 0;
743*03f9172cSAndroid Build Coastguard Worker } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
744*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
745*03f9172cSAndroid Build Coastguard Worker if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
746*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
747*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
748*03f9172cSAndroid Build Coastguard Worker false)) {
749*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
750*03f9172cSAndroid Build Coastguard Worker "key management and encryption suites (no "
751*03f9172cSAndroid Build Coastguard Worker "scan results)");
752*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
753*03f9172cSAndroid Build Coastguard Worker return;
754*03f9172cSAndroid Build Coastguard Worker }
755*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WPS
756*03f9172cSAndroid Build Coastguard Worker } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
757*03f9172cSAndroid Build Coastguard Worker struct wpabuf *wps_ie;
758*03f9172cSAndroid Build Coastguard Worker wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
759*03f9172cSAndroid Build Coastguard Worker if (wps_ie && wpabuf_len(wps_ie) <=
760*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie)) {
761*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
762*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
763*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len);
764*03f9172cSAndroid Build Coastguard Worker } else
765*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len = 0;
766*03f9172cSAndroid Build Coastguard Worker wpabuf_free(wps_ie);
767*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
768*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WPS */
769*03f9172cSAndroid Build Coastguard Worker } else {
770*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
771*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len = 0;
772*03f9172cSAndroid Build Coastguard Worker }
773*03f9172cSAndroid Build Coastguard Worker
774*03f9172cSAndroid Build Coastguard Worker /* In case the WPA vendor IE is used, it should be placed after all the
775*03f9172cSAndroid Build Coastguard Worker * non-vendor IEs, as the lower layer expects the IEs to be ordered as
776*03f9172cSAndroid Build Coastguard Worker * defined in the standard. Store the WPA IE so it can later be
777*03f9172cSAndroid Build Coastguard Worker * inserted at the correct location.
778*03f9172cSAndroid Build Coastguard Worker */
779*03f9172cSAndroid Build Coastguard Worker wpa_ie = NULL;
780*03f9172cSAndroid Build Coastguard Worker wpa_ie_len = 0;
781*03f9172cSAndroid Build Coastguard Worker if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
782*03f9172cSAndroid Build Coastguard Worker wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
783*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len);
784*03f9172cSAndroid Build Coastguard Worker if (wpa_ie) {
785*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
786*03f9172cSAndroid Build Coastguard Worker
787*03f9172cSAndroid Build Coastguard Worker wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
788*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len = 0;
789*03f9172cSAndroid Build Coastguard Worker } else {
790*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
791*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
792*03f9172cSAndroid Build Coastguard Worker return;
793*03f9172cSAndroid Build Coastguard Worker }
794*03f9172cSAndroid Build Coastguard Worker }
795*03f9172cSAndroid Build Coastguard Worker
796*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R
797*03f9172cSAndroid Build Coastguard Worker ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
798*03f9172cSAndroid Build Coastguard Worker if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
799*03f9172cSAndroid Build Coastguard Worker md = ie + 2;
800*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
801*03f9172cSAndroid Build Coastguard Worker if (md && (!wpa_key_mgmt_ft(ssid->key_mgmt) ||
802*03f9172cSAndroid Build Coastguard Worker !wpa_key_mgmt_ft(wpa_s->key_mgmt)))
803*03f9172cSAndroid Build Coastguard Worker md = NULL;
804*03f9172cSAndroid Build Coastguard Worker if (md) {
805*03f9172cSAndroid Build Coastguard Worker /* Prepare for the next transition */
806*03f9172cSAndroid Build Coastguard Worker wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
807*03f9172cSAndroid Build Coastguard Worker }
808*03f9172cSAndroid Build Coastguard Worker
809*03f9172cSAndroid Build Coastguard Worker if (md) {
810*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x",
811*03f9172cSAndroid Build Coastguard Worker md[0], md[1]);
812*03f9172cSAndroid Build Coastguard Worker
813*03f9172cSAndroid Build Coastguard Worker omit_rsnxe = !wpa_bss_get_rsnxe(wpa_s, bss, ssid, false);
814*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.assoc_req_ie_len + 5 <
815*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie)) {
816*03f9172cSAndroid Build Coastguard Worker struct rsn_mdie *mdie;
817*03f9172cSAndroid Build Coastguard Worker u8 *pos = wpa_s->sme.assoc_req_ie +
818*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len;
819*03f9172cSAndroid Build Coastguard Worker *pos++ = WLAN_EID_MOBILITY_DOMAIN;
820*03f9172cSAndroid Build Coastguard Worker *pos++ = sizeof(*mdie);
821*03f9172cSAndroid Build Coastguard Worker mdie = (struct rsn_mdie *) pos;
822*03f9172cSAndroid Build Coastguard Worker os_memcpy(mdie->mobility_domain, md,
823*03f9172cSAndroid Build Coastguard Worker MOBILITY_DOMAIN_ID_LEN);
824*03f9172cSAndroid Build Coastguard Worker mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
825*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += 5;
826*03f9172cSAndroid Build Coastguard Worker }
827*03f9172cSAndroid Build Coastguard Worker
828*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.prev_bssid_set && wpa_s->sme.ft_used &&
829*03f9172cSAndroid Build Coastguard Worker os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
830*03f9172cSAndroid Build Coastguard Worker wpa_sm_has_ft_keys(wpa_s->wpa, md)) {
831*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
832*03f9172cSAndroid Build Coastguard Worker "over-the-air");
833*03f9172cSAndroid Build Coastguard Worker params.auth_alg = WPA_AUTH_ALG_FT;
834*03f9172cSAndroid Build Coastguard Worker params.ie = wpa_s->sme.ft_ies;
835*03f9172cSAndroid Build Coastguard Worker params.ie_len = wpa_s->sme.ft_ies_len;
836*03f9172cSAndroid Build Coastguard Worker }
837*03f9172cSAndroid Build Coastguard Worker }
838*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R */
839*03f9172cSAndroid Build Coastguard Worker
840*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
841*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
842*03f9172cSAndroid Build Coastguard Worker const u8 *rsn = wpa_bss_get_rsne(wpa_s, bss, ssid, false);
843*03f9172cSAndroid Build Coastguard Worker struct wpa_ie_data _ie;
844*03f9172cSAndroid Build Coastguard Worker if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
845*03f9172cSAndroid Build Coastguard Worker _ie.capabilities &
846*03f9172cSAndroid Build Coastguard Worker (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
847*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
848*03f9172cSAndroid Build Coastguard Worker "MFP: require MFP");
849*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
850*03f9172cSAndroid Build Coastguard Worker }
851*03f9172cSAndroid Build Coastguard Worker }
852*03f9172cSAndroid Build Coastguard Worker
853*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_P2P
854*03f9172cSAndroid Build Coastguard Worker if (wpa_s->global->p2p) {
855*03f9172cSAndroid Build Coastguard Worker u8 *pos;
856*03f9172cSAndroid Build Coastguard Worker size_t len;
857*03f9172cSAndroid Build Coastguard Worker int res;
858*03f9172cSAndroid Build Coastguard Worker pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
859*03f9172cSAndroid Build Coastguard Worker len = sizeof(wpa_s->sme.assoc_req_ie) -
860*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len;
861*03f9172cSAndroid Build Coastguard Worker res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
862*03f9172cSAndroid Build Coastguard Worker ssid->p2p_group);
863*03f9172cSAndroid Build Coastguard Worker if (res >= 0)
864*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += res;
865*03f9172cSAndroid Build Coastguard Worker }
866*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_P2P */
867*03f9172cSAndroid Build Coastguard Worker
868*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FST
869*03f9172cSAndroid Build Coastguard Worker if (wpa_s->fst_ies) {
870*03f9172cSAndroid Build Coastguard Worker int fst_ies_len = wpabuf_len(wpa_s->fst_ies);
871*03f9172cSAndroid Build Coastguard Worker
872*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.assoc_req_ie_len + fst_ies_len <=
873*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie)) {
874*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie +
875*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len,
876*03f9172cSAndroid Build Coastguard Worker wpabuf_head(wpa_s->fst_ies),
877*03f9172cSAndroid Build Coastguard Worker fst_ies_len);
878*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += fst_ies_len;
879*03f9172cSAndroid Build Coastguard Worker }
880*03f9172cSAndroid Build Coastguard Worker }
881*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FST */
882*03f9172cSAndroid Build Coastguard Worker
883*03f9172cSAndroid Build Coastguard Worker sme_auth_handle_rrm(wpa_s, bss);
884*03f9172cSAndroid Build Coastguard Worker
885*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_NO_RRM
886*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie(
887*03f9172cSAndroid Build Coastguard Worker wpa_s, ssid, bss,
888*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
889*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len);
890*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NO_RRM */
891*03f9172cSAndroid Build Coastguard Worker
892*03f9172cSAndroid Build Coastguard Worker if (params.p2p)
893*03f9172cSAndroid Build Coastguard Worker wpa_drv_get_ext_capa(wpa_s, WPA_IF_P2P_CLIENT);
894*03f9172cSAndroid Build Coastguard Worker else
895*03f9172cSAndroid Build Coastguard Worker wpa_drv_get_ext_capa(wpa_s, WPA_IF_STATION);
896*03f9172cSAndroid Build Coastguard Worker
897*03f9172cSAndroid Build Coastguard Worker ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
898*03f9172cSAndroid Build Coastguard Worker sizeof(ext_capab), bss);
899*03f9172cSAndroid Build Coastguard Worker if (ext_capab_len > 0) {
900*03f9172cSAndroid Build Coastguard Worker u8 *pos = wpa_s->sme.assoc_req_ie;
901*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
902*03f9172cSAndroid Build Coastguard Worker pos += 2 + pos[1];
903*03f9172cSAndroid Build Coastguard Worker os_memmove(pos + ext_capab_len, pos,
904*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len -
905*03f9172cSAndroid Build Coastguard Worker (pos - wpa_s->sme.assoc_req_ie));
906*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += ext_capab_len;
907*03f9172cSAndroid Build Coastguard Worker os_memcpy(pos, ext_capab, ext_capab_len);
908*03f9172cSAndroid Build Coastguard Worker }
909*03f9172cSAndroid Build Coastguard Worker
910*03f9172cSAndroid Build Coastguard Worker if (ssid->max_idle && wpa_s->sme.assoc_req_ie_len + 5 <=
911*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie)) {
912*03f9172cSAndroid Build Coastguard Worker u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
913*03f9172cSAndroid Build Coastguard Worker
914*03f9172cSAndroid Build Coastguard Worker *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
915*03f9172cSAndroid Build Coastguard Worker *pos++ = 3;
916*03f9172cSAndroid Build Coastguard Worker WPA_PUT_LE16(pos, ssid->max_idle);
917*03f9172cSAndroid Build Coastguard Worker pos += 2;
918*03f9172cSAndroid Build Coastguard Worker *pos = 0; /* Idle Options */
919*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += 5;
920*03f9172cSAndroid Build Coastguard Worker }
921*03f9172cSAndroid Build Coastguard Worker
922*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
923*03f9172cSAndroid Build Coastguard Worker if (wpa_s->rsnxe_override_assoc &&
924*03f9172cSAndroid Build Coastguard Worker wpabuf_len(wpa_s->rsnxe_override_assoc) <=
925*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) {
926*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "TESTING: RSNXE AssocReq override");
927*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
928*03f9172cSAndroid Build Coastguard Worker wpabuf_head(wpa_s->rsnxe_override_assoc),
929*03f9172cSAndroid Build Coastguard Worker wpabuf_len(wpa_s->rsnxe_override_assoc));
930*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len +=
931*03f9172cSAndroid Build Coastguard Worker wpabuf_len(wpa_s->rsnxe_override_assoc);
932*03f9172cSAndroid Build Coastguard Worker } else
933*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
934*03f9172cSAndroid Build Coastguard Worker if (wpa_s->rsnxe_len > 0 &&
935*03f9172cSAndroid Build Coastguard Worker wpa_s->rsnxe_len <=
936*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len &&
937*03f9172cSAndroid Build Coastguard Worker !omit_rsnxe) {
938*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
939*03f9172cSAndroid Build Coastguard Worker wpa_s->rsnxe, wpa_s->rsnxe_len);
940*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len;
941*03f9172cSAndroid Build Coastguard Worker }
942*03f9172cSAndroid Build Coastguard Worker
943*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_HS20
944*03f9172cSAndroid Build Coastguard Worker if (is_hs20_network(wpa_s, ssid, bss)
945*03f9172cSAndroid Build Coastguard Worker #ifndef ANDROID /* Android does not use the native HS 2.0 config */
946*03f9172cSAndroid Build Coastguard Worker && is_hs20_config(wpa_s)
947*03f9172cSAndroid Build Coastguard Worker #endif /* ANDROID */
948*03f9172cSAndroid Build Coastguard Worker ) {
949*03f9172cSAndroid Build Coastguard Worker struct wpabuf *hs20;
950*03f9172cSAndroid Build Coastguard Worker
951*03f9172cSAndroid Build Coastguard Worker hs20 = wpabuf_alloc(20 + MAX_ROAMING_CONS_OI_LEN);
952*03f9172cSAndroid Build Coastguard Worker if (hs20) {
953*03f9172cSAndroid Build Coastguard Worker int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
954*03f9172cSAndroid Build Coastguard Worker size_t len;
955*03f9172cSAndroid Build Coastguard Worker
956*03f9172cSAndroid Build Coastguard Worker wpas_hs20_add_indication(hs20, pps_mo_id,
957*03f9172cSAndroid Build Coastguard Worker get_hs20_version(bss));
958*03f9172cSAndroid Build Coastguard Worker wpas_hs20_add_roam_cons_sel(hs20, ssid);
959*03f9172cSAndroid Build Coastguard Worker len = sizeof(wpa_s->sme.assoc_req_ie) -
960*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len;
961*03f9172cSAndroid Build Coastguard Worker if (wpabuf_len(hs20) <= len) {
962*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie +
963*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len,
964*03f9172cSAndroid Build Coastguard Worker wpabuf_head(hs20), wpabuf_len(hs20));
965*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
966*03f9172cSAndroid Build Coastguard Worker }
967*03f9172cSAndroid Build Coastguard Worker wpabuf_free(hs20);
968*03f9172cSAndroid Build Coastguard Worker }
969*03f9172cSAndroid Build Coastguard Worker }
970*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_HS20 */
971*03f9172cSAndroid Build Coastguard Worker
972*03f9172cSAndroid Build Coastguard Worker if (wpa_ie) {
973*03f9172cSAndroid Build Coastguard Worker size_t len;
974*03f9172cSAndroid Build Coastguard Worker
975*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
976*03f9172cSAndroid Build Coastguard Worker
977*03f9172cSAndroid Build Coastguard Worker len = sizeof(wpa_s->sme.assoc_req_ie) -
978*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len;
979*03f9172cSAndroid Build Coastguard Worker
980*03f9172cSAndroid Build Coastguard Worker if (len > wpa_ie_len) {
981*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie +
982*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len,
983*03f9172cSAndroid Build Coastguard Worker wpa_ie, wpa_ie_len);
984*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
985*03f9172cSAndroid Build Coastguard Worker } else {
986*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
987*03f9172cSAndroid Build Coastguard Worker }
988*03f9172cSAndroid Build Coastguard Worker
989*03f9172cSAndroid Build Coastguard Worker os_free(wpa_ie);
990*03f9172cSAndroid Build Coastguard Worker }
991*03f9172cSAndroid Build Coastguard Worker
992*03f9172cSAndroid Build Coastguard Worker if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
993*03f9172cSAndroid Build Coastguard Worker struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
994*03f9172cSAndroid Build Coastguard Worker size_t len;
995*03f9172cSAndroid Build Coastguard Worker
996*03f9172cSAndroid Build Coastguard Worker len = sizeof(wpa_s->sme.assoc_req_ie) -
997*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len;
998*03f9172cSAndroid Build Coastguard Worker if (wpabuf_len(buf) <= len) {
999*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie +
1000*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len,
1001*03f9172cSAndroid Build Coastguard Worker wpabuf_head(buf), wpabuf_len(buf));
1002*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
1003*03f9172cSAndroid Build Coastguard Worker }
1004*03f9172cSAndroid Build Coastguard Worker }
1005*03f9172cSAndroid Build Coastguard Worker
1006*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_MBO
1007*03f9172cSAndroid Build Coastguard Worker mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
1008*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->disable_mbo_oce && mbo_ie) {
1009*03f9172cSAndroid Build Coastguard Worker int len;
1010*03f9172cSAndroid Build Coastguard Worker
1011*03f9172cSAndroid Build Coastguard Worker len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
1012*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len,
1013*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie) -
1014*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len,
1015*03f9172cSAndroid Build Coastguard Worker !!mbo_attr_from_mbo_ie(mbo_ie,
1016*03f9172cSAndroid Build Coastguard Worker OCE_ATTR_ID_CAPA_IND));
1017*03f9172cSAndroid Build Coastguard Worker if (len >= 0)
1018*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += len;
1019*03f9172cSAndroid Build Coastguard Worker }
1020*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_MBO */
1021*03f9172cSAndroid Build Coastguard Worker
1022*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
1023*03f9172cSAndroid Build Coastguard Worker if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
1024*03f9172cSAndroid Build Coastguard Worker pmksa_cache_set_current(wpa_s->wpa, NULL,
1025*03f9172cSAndroid Build Coastguard Worker params.mld ? params.ap_mld_addr :
1026*03f9172cSAndroid Build Coastguard Worker bss->bssid,
1027*03f9172cSAndroid Build Coastguard Worker ssid, 0,
1028*03f9172cSAndroid Build Coastguard Worker NULL,
1029*03f9172cSAndroid Build Coastguard Worker wpa_key_mgmt_sae(wpa_s->key_mgmt) ?
1030*03f9172cSAndroid Build Coastguard Worker wpa_s->key_mgmt :
1031*03f9172cSAndroid Build Coastguard Worker (int) WPA_KEY_MGMT_SAE, false) == 0) {
1032*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
1033*03f9172cSAndroid Build Coastguard Worker "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
1034*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
1035*03f9172cSAndroid Build Coastguard Worker params.auth_alg = WPA_AUTH_ALG_OPEN;
1036*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_pmksa_caching = 1;
1037*03f9172cSAndroid Build Coastguard Worker }
1038*03f9172cSAndroid Build Coastguard Worker
1039*03f9172cSAndroid Build Coastguard Worker if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE) {
1040*03f9172cSAndroid Build Coastguard Worker if (start)
1041*03f9172cSAndroid Build Coastguard Worker resp = sme_auth_build_sae_commit(wpa_s, ssid,
1042*03f9172cSAndroid Build Coastguard Worker bss->bssid,
1043*03f9172cSAndroid Build Coastguard Worker params.mld ?
1044*03f9172cSAndroid Build Coastguard Worker params.ap_mld_addr :
1045*03f9172cSAndroid Build Coastguard Worker NULL, 0,
1046*03f9172cSAndroid Build Coastguard Worker start == 2, NULL,
1047*03f9172cSAndroid Build Coastguard Worker NULL);
1048*03f9172cSAndroid Build Coastguard Worker else
1049*03f9172cSAndroid Build Coastguard Worker resp = sme_auth_build_sae_confirm(wpa_s, 0);
1050*03f9172cSAndroid Build Coastguard Worker if (resp == NULL) {
1051*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, bss->bssid, NULL);
1052*03f9172cSAndroid Build Coastguard Worker return;
1053*03f9172cSAndroid Build Coastguard Worker }
1054*03f9172cSAndroid Build Coastguard Worker params.auth_data = wpabuf_head(resp);
1055*03f9172cSAndroid Build Coastguard Worker params.auth_data_len = wpabuf_len(resp);
1056*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
1057*03f9172cSAndroid Build Coastguard Worker }
1058*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
1059*03f9172cSAndroid Build Coastguard Worker
1060*03f9172cSAndroid Build Coastguard Worker bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
1061*03f9172cSAndroid Build Coastguard Worker os_memset(wpa_s->bssid, 0, ETH_ALEN);
1062*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
1063*03f9172cSAndroid Build Coastguard Worker if (bssid_changed)
1064*03f9172cSAndroid Build Coastguard Worker wpas_notify_bssid_changed(wpa_s);
1065*03f9172cSAndroid Build Coastguard Worker
1066*03f9172cSAndroid Build Coastguard Worker old_ssid = wpa_s->current_ssid;
1067*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid = ssid;
1068*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
1069*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_ssid(wpa_s->wpa, bss->ssid, bss->ssid_len);
1070*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_initiate_eapol(wpa_s);
1071*03f9172cSAndroid Build Coastguard Worker
1072*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FILS
1073*03f9172cSAndroid Build Coastguard Worker /* TODO: FILS operations can in some cases be done between different
1074*03f9172cSAndroid Build Coastguard Worker * network_ctx (i.e., same credentials can be used with multiple
1075*03f9172cSAndroid Build Coastguard Worker * networks). */
1076*03f9172cSAndroid Build Coastguard Worker if (params.auth_alg == WPA_AUTH_ALG_OPEN &&
1077*03f9172cSAndroid Build Coastguard Worker wpa_key_mgmt_fils(ssid->key_mgmt)) {
1078*03f9172cSAndroid Build Coastguard Worker const u8 *indic;
1079*03f9172cSAndroid Build Coastguard Worker u16 fils_info;
1080*03f9172cSAndroid Build Coastguard Worker const u8 *realm, *username, *rrk;
1081*03f9172cSAndroid Build Coastguard Worker size_t realm_len, username_len, rrk_len;
1082*03f9172cSAndroid Build Coastguard Worker u16 next_seq_num;
1083*03f9172cSAndroid Build Coastguard Worker
1084*03f9172cSAndroid Build Coastguard Worker /*
1085*03f9172cSAndroid Build Coastguard Worker * Check FILS Indication element (FILS Information field) bits
1086*03f9172cSAndroid Build Coastguard Worker * indicating supported authentication algorithms against local
1087*03f9172cSAndroid Build Coastguard Worker * configuration (ssid->fils_dh_group). Try to use FILS
1088*03f9172cSAndroid Build Coastguard Worker * authentication only if the AP supports the combination in the
1089*03f9172cSAndroid Build Coastguard Worker * network profile. */
1090*03f9172cSAndroid Build Coastguard Worker indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
1091*03f9172cSAndroid Build Coastguard Worker if (!indic || indic[1] < 2) {
1092*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME: " MACSTR
1093*03f9172cSAndroid Build Coastguard Worker " does not include FILS Indication element - cannot use FILS authentication with it",
1094*03f9172cSAndroid Build Coastguard Worker MAC2STR(bss->bssid));
1095*03f9172cSAndroid Build Coastguard Worker goto no_fils;
1096*03f9172cSAndroid Build Coastguard Worker }
1097*03f9172cSAndroid Build Coastguard Worker
1098*03f9172cSAndroid Build Coastguard Worker fils_info = WPA_GET_LE16(indic + 2);
1099*03f9172cSAndroid Build Coastguard Worker if (ssid->fils_dh_group == 0 && !(fils_info & BIT(9))) {
1100*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME: " MACSTR
1101*03f9172cSAndroid Build Coastguard Worker " does not support FILS SK without PFS - cannot use FILS authentication with it",
1102*03f9172cSAndroid Build Coastguard Worker MAC2STR(bss->bssid));
1103*03f9172cSAndroid Build Coastguard Worker goto no_fils;
1104*03f9172cSAndroid Build Coastguard Worker }
1105*03f9172cSAndroid Build Coastguard Worker if (ssid->fils_dh_group != 0 && !(fils_info & BIT(10))) {
1106*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME: " MACSTR
1107*03f9172cSAndroid Build Coastguard Worker " does not support FILS SK with PFS - cannot use FILS authentication with it",
1108*03f9172cSAndroid Build Coastguard Worker MAC2STR(bss->bssid));
1109*03f9172cSAndroid Build Coastguard Worker goto no_fils;
1110*03f9172cSAndroid Build Coastguard Worker }
1111*03f9172cSAndroid Build Coastguard Worker
1112*03f9172cSAndroid Build Coastguard Worker if (wpa_s->last_con_fail_realm &&
1113*03f9172cSAndroid Build Coastguard Worker eapol_sm_get_erp_info(wpa_s->eapol, &ssid->eap,
1114*03f9172cSAndroid Build Coastguard Worker &username, &username_len,
1115*03f9172cSAndroid Build Coastguard Worker &realm, &realm_len, &next_seq_num,
1116*03f9172cSAndroid Build Coastguard Worker &rrk, &rrk_len) == 0 &&
1117*03f9172cSAndroid Build Coastguard Worker realm && realm_len == wpa_s->last_con_fail_realm_len &&
1118*03f9172cSAndroid Build Coastguard Worker os_memcmp(realm, wpa_s->last_con_fail_realm,
1119*03f9172cSAndroid Build Coastguard Worker realm_len) == 0) {
1120*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1121*03f9172cSAndroid Build Coastguard Worker "SME: FILS authentication for this realm failed last time - try to regenerate ERP key hierarchy");
1122*03f9172cSAndroid Build Coastguard Worker goto no_fils;
1123*03f9172cSAndroid Build Coastguard Worker }
1124*03f9172cSAndroid Build Coastguard Worker
1125*03f9172cSAndroid Build Coastguard Worker if (pmksa_cache_set_current(wpa_s->wpa, NULL,
1126*03f9172cSAndroid Build Coastguard Worker params.mld ? params.ap_mld_addr :
1127*03f9172cSAndroid Build Coastguard Worker bss->bssid,
1128*03f9172cSAndroid Build Coastguard Worker ssid, 0,
1129*03f9172cSAndroid Build Coastguard Worker wpa_bss_get_fils_cache_id(bss),
1130*03f9172cSAndroid Build Coastguard Worker 0, false) == 0)
1131*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1132*03f9172cSAndroid Build Coastguard Worker "SME: Try to use FILS with PMKSA caching");
1133*03f9172cSAndroid Build Coastguard Worker resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
1134*03f9172cSAndroid Build Coastguard Worker if (resp) {
1135*03f9172cSAndroid Build Coastguard Worker int auth_alg;
1136*03f9172cSAndroid Build Coastguard Worker
1137*03f9172cSAndroid Build Coastguard Worker if (ssid->fils_dh_group)
1138*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1139*03f9172cSAndroid Build Coastguard Worker "SME: Try to use FILS SK authentication with PFS (DH Group %u)",
1140*03f9172cSAndroid Build Coastguard Worker ssid->fils_dh_group);
1141*03f9172cSAndroid Build Coastguard Worker else
1142*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1143*03f9172cSAndroid Build Coastguard Worker "SME: Try to use FILS SK authentication without PFS");
1144*03f9172cSAndroid Build Coastguard Worker auth_alg = ssid->fils_dh_group ?
1145*03f9172cSAndroid Build Coastguard Worker WPA_AUTH_ALG_FILS_SK_PFS : WPA_AUTH_ALG_FILS;
1146*03f9172cSAndroid Build Coastguard Worker params.auth_alg = auth_alg;
1147*03f9172cSAndroid Build Coastguard Worker params.auth_data = wpabuf_head(resp);
1148*03f9172cSAndroid Build Coastguard Worker params.auth_data_len = wpabuf_len(resp);
1149*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.auth_alg = auth_alg;
1150*03f9172cSAndroid Build Coastguard Worker }
1151*03f9172cSAndroid Build Coastguard Worker }
1152*03f9172cSAndroid Build Coastguard Worker no_fils:
1153*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FILS */
1154*03f9172cSAndroid Build Coastguard Worker
1155*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_cancel_sched_scan(wpa_s);
1156*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_cancel_scan(wpa_s);
1157*03f9172cSAndroid Build Coastguard Worker
1158*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
1159*03f9172cSAndroid Build Coastguard Worker " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
1160*03f9172cSAndroid Build Coastguard Worker wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
1161*03f9172cSAndroid Build Coastguard Worker
1162*03f9172cSAndroid Build Coastguard Worker eapol_sm_notify_portValid(wpa_s->eapol, false);
1163*03f9172cSAndroid Build Coastguard Worker wpa_clear_keys(wpa_s, bss->bssid);
1164*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
1165*03f9172cSAndroid Build Coastguard Worker if (old_ssid != wpa_s->current_ssid)
1166*03f9172cSAndroid Build Coastguard Worker wpas_notify_network_changed(wpa_s);
1167*03f9172cSAndroid Build Coastguard Worker
1168*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_HS20
1169*03f9172cSAndroid Build Coastguard Worker hs20_configure_frame_filters(wpa_s);
1170*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_HS20 */
1171*03f9172cSAndroid Build Coastguard Worker
1172*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_P2P
1173*03f9172cSAndroid Build Coastguard Worker /*
1174*03f9172cSAndroid Build Coastguard Worker * If multi-channel concurrency is not supported, check for any
1175*03f9172cSAndroid Build Coastguard Worker * frequency conflict. In case of any frequency conflict, remove the
1176*03f9172cSAndroid Build Coastguard Worker * least prioritized connection.
1177*03f9172cSAndroid Build Coastguard Worker */
1178*03f9172cSAndroid Build Coastguard Worker if (wpa_s->num_multichan_concurrent < 2) {
1179*03f9172cSAndroid Build Coastguard Worker int freq, num;
1180*03f9172cSAndroid Build Coastguard Worker num = get_shared_radio_freqs(wpa_s, &freq, 1, false);
1181*03f9172cSAndroid Build Coastguard Worker if (num > 0 && freq > 0 && freq != params.freq) {
1182*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1183*03f9172cSAndroid Build Coastguard Worker "Conflicting frequency found (%d != %d)",
1184*03f9172cSAndroid Build Coastguard Worker freq, params.freq);
1185*03f9172cSAndroid Build Coastguard Worker if (wpas_p2p_handle_frequency_conflicts(wpa_s,
1186*03f9172cSAndroid Build Coastguard Worker params.freq,
1187*03f9172cSAndroid Build Coastguard Worker ssid) < 0) {
1188*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, bss->bssid, NULL);
1189*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
1190*03f9172cSAndroid Build Coastguard Worker wpabuf_free(resp);
1191*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
1192*03f9172cSAndroid Build Coastguard Worker return;
1193*03f9172cSAndroid Build Coastguard Worker }
1194*03f9172cSAndroid Build Coastguard Worker }
1195*03f9172cSAndroid Build Coastguard Worker }
1196*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_P2P */
1197*03f9172cSAndroid Build Coastguard Worker
1198*03f9172cSAndroid Build Coastguard Worker if (skip_auth) {
1199*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_DEBUG,
1200*03f9172cSAndroid Build Coastguard Worker "SME: Skip authentication step on reassoc-to-same-BSS");
1201*03f9172cSAndroid Build Coastguard Worker wpabuf_free(resp);
1202*03f9172cSAndroid Build Coastguard Worker sme_associate(wpa_s, ssid->mode, bss->bssid, WLAN_AUTH_OPEN);
1203*03f9172cSAndroid Build Coastguard Worker return;
1204*03f9172cSAndroid Build Coastguard Worker }
1205*03f9172cSAndroid Build Coastguard Worker
1206*03f9172cSAndroid Build Coastguard Worker
1207*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.auth_alg = params.auth_alg;
1208*03f9172cSAndroid Build Coastguard Worker if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) {
1209*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
1210*03f9172cSAndroid Build Coastguard Worker "driver failed");
1211*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, bss->bssid, NULL);
1212*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
1213*03f9172cSAndroid Build Coastguard Worker wpabuf_free(resp);
1214*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
1215*03f9172cSAndroid Build Coastguard Worker return;
1216*03f9172cSAndroid Build Coastguard Worker }
1217*03f9172cSAndroid Build Coastguard Worker
1218*03f9172cSAndroid Build Coastguard Worker eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
1219*03f9172cSAndroid Build Coastguard Worker NULL);
1220*03f9172cSAndroid Build Coastguard Worker
1221*03f9172cSAndroid Build Coastguard Worker /*
1222*03f9172cSAndroid Build Coastguard Worker * Association will be started based on the authentication event from
1223*03f9172cSAndroid Build Coastguard Worker * the driver.
1224*03f9172cSAndroid Build Coastguard Worker */
1225*03f9172cSAndroid Build Coastguard Worker
1226*03f9172cSAndroid Build Coastguard Worker wpabuf_free(resp);
1227*03f9172cSAndroid Build Coastguard Worker }
1228*03f9172cSAndroid Build Coastguard Worker
1229*03f9172cSAndroid Build Coastguard Worker
sme_auth_start_cb(struct wpa_radio_work * work,int deinit)1230*03f9172cSAndroid Build Coastguard Worker static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
1231*03f9172cSAndroid Build Coastguard Worker {
1232*03f9172cSAndroid Build Coastguard Worker struct wpa_connect_work *cwork = work->ctx;
1233*03f9172cSAndroid Build Coastguard Worker struct wpa_supplicant *wpa_s = work->wpa_s;
1234*03f9172cSAndroid Build Coastguard Worker
1235*03f9172cSAndroid Build Coastguard Worker wpa_s->roam_in_progress = false;
1236*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WNM
1237*03f9172cSAndroid Build Coastguard Worker wpa_s->bss_trans_mgmt_in_progress = false;
1238*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WNM */
1239*03f9172cSAndroid Build Coastguard Worker
1240*03f9172cSAndroid Build Coastguard Worker if (deinit) {
1241*03f9172cSAndroid Build Coastguard Worker if (work->started)
1242*03f9172cSAndroid Build Coastguard Worker wpa_s->connect_work = NULL;
1243*03f9172cSAndroid Build Coastguard Worker
1244*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_free(cwork);
1245*03f9172cSAndroid Build Coastguard Worker return;
1246*03f9172cSAndroid Build Coastguard Worker }
1247*03f9172cSAndroid Build Coastguard Worker
1248*03f9172cSAndroid Build Coastguard Worker wpa_s->connect_work = work;
1249*03f9172cSAndroid Build Coastguard Worker
1250*03f9172cSAndroid Build Coastguard Worker if (cwork->bss_removed ||
1251*03f9172cSAndroid Build Coastguard Worker !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid) ||
1252*03f9172cSAndroid Build Coastguard Worker wpas_network_disabled(wpa_s, cwork->ssid)) {
1253*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
1254*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
1255*03f9172cSAndroid Build Coastguard Worker return;
1256*03f9172cSAndroid Build Coastguard Worker }
1257*03f9172cSAndroid Build Coastguard Worker
1258*03f9172cSAndroid Build Coastguard Worker /* Starting new connection, so clear the possibly used WPA IE from the
1259*03f9172cSAndroid Build Coastguard Worker * previous association. */
1260*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
1261*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
1262*03f9172cSAndroid Build Coastguard Worker wpa_s->rsnxe_len = 0;
1263*03f9172cSAndroid Build Coastguard Worker
1264*03f9172cSAndroid Build Coastguard Worker sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
1265*03f9172cSAndroid Build Coastguard Worker wpas_notify_auth_changed(wpa_s);
1266*03f9172cSAndroid Build Coastguard Worker }
1267*03f9172cSAndroid Build Coastguard Worker
1268*03f9172cSAndroid Build Coastguard Worker
sme_authenticate(struct wpa_supplicant * wpa_s,struct wpa_bss * bss,struct wpa_ssid * ssid)1269*03f9172cSAndroid Build Coastguard Worker void sme_authenticate(struct wpa_supplicant *wpa_s,
1270*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss, struct wpa_ssid *ssid)
1271*03f9172cSAndroid Build Coastguard Worker {
1272*03f9172cSAndroid Build Coastguard Worker struct wpa_connect_work *cwork;
1273*03f9172cSAndroid Build Coastguard Worker
1274*03f9172cSAndroid Build Coastguard Worker if (bss == NULL || ssid == NULL)
1275*03f9172cSAndroid Build Coastguard Worker return;
1276*03f9172cSAndroid Build Coastguard Worker if (wpa_s->connect_work) {
1277*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
1278*03f9172cSAndroid Build Coastguard Worker return;
1279*03f9172cSAndroid Build Coastguard Worker }
1280*03f9172cSAndroid Build Coastguard Worker
1281*03f9172cSAndroid Build Coastguard Worker if (wpa_s->roam_in_progress) {
1282*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
1283*03f9172cSAndroid Build Coastguard Worker "SME: Reject sme_authenticate() in favor of explicit roam request");
1284*03f9172cSAndroid Build Coastguard Worker return;
1285*03f9172cSAndroid Build Coastguard Worker }
1286*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_WNM
1287*03f9172cSAndroid Build Coastguard Worker if (wpa_s->bss_trans_mgmt_in_progress) {
1288*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
1289*03f9172cSAndroid Build Coastguard Worker "SME: Reject sme_authenticate() in favor of BSS transition management request");
1290*03f9172cSAndroid Build Coastguard Worker return;
1291*03f9172cSAndroid Build Coastguard Worker }
1292*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_WNM */
1293*03f9172cSAndroid Build Coastguard Worker if (radio_work_pending(wpa_s, "sme-connect")) {
1294*03f9172cSAndroid Build Coastguard Worker /*
1295*03f9172cSAndroid Build Coastguard Worker * The previous sme-connect work might no longer be valid due to
1296*03f9172cSAndroid Build Coastguard Worker * the fact that the BSS list was updated. In addition, it makes
1297*03f9172cSAndroid Build Coastguard Worker * sense to adhere to the 'newer' decision.
1298*03f9172cSAndroid Build Coastguard Worker */
1299*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
1300*03f9172cSAndroid Build Coastguard Worker "SME: Remove previous pending sme-connect");
1301*03f9172cSAndroid Build Coastguard Worker radio_remove_works(wpa_s, "sme-connect", 0);
1302*03f9172cSAndroid Build Coastguard Worker }
1303*03f9172cSAndroid Build Coastguard Worker
1304*03f9172cSAndroid Build Coastguard Worker wpas_abort_ongoing_scan(wpa_s);
1305*03f9172cSAndroid Build Coastguard Worker
1306*03f9172cSAndroid Build Coastguard Worker cwork = os_zalloc(sizeof(*cwork));
1307*03f9172cSAndroid Build Coastguard Worker if (cwork == NULL)
1308*03f9172cSAndroid Build Coastguard Worker return;
1309*03f9172cSAndroid Build Coastguard Worker cwork->bss = bss;
1310*03f9172cSAndroid Build Coastguard Worker cwork->ssid = ssid;
1311*03f9172cSAndroid Build Coastguard Worker cwork->sme = 1;
1312*03f9172cSAndroid Build Coastguard Worker
1313*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
1314*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.state = SAE_NOTHING;
1315*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.send_confirm = 0;
1316*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_group_index = 0;
1317*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
1318*03f9172cSAndroid Build Coastguard Worker
1319*03f9172cSAndroid Build Coastguard Worker if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
1320*03f9172cSAndroid Build Coastguard Worker sme_auth_start_cb, cwork) < 0)
1321*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_free(cwork);
1322*03f9172cSAndroid Build Coastguard Worker }
1323*03f9172cSAndroid Build Coastguard Worker
1324*03f9172cSAndroid Build Coastguard Worker
1325*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
1326*03f9172cSAndroid Build Coastguard Worker
1327*03f9172cSAndroid Build Coastguard Worker #define WPA_AUTH_FRAME_ML_IE_LEN (6 + ETH_ALEN)
1328*03f9172cSAndroid Build Coastguard Worker
wpa_auth_ml_ie(struct wpabuf * buf,const u8 * mld_addr)1329*03f9172cSAndroid Build Coastguard Worker static void wpa_auth_ml_ie(struct wpabuf *buf, const u8 *mld_addr)
1330*03f9172cSAndroid Build Coastguard Worker {
1331*03f9172cSAndroid Build Coastguard Worker
1332*03f9172cSAndroid Build Coastguard Worker wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
1333*03f9172cSAndroid Build Coastguard Worker wpabuf_put_u8(buf, 4 + ETH_ALEN);
1334*03f9172cSAndroid Build Coastguard Worker wpabuf_put_u8(buf, WLAN_EID_EXT_MULTI_LINK);
1335*03f9172cSAndroid Build Coastguard Worker
1336*03f9172cSAndroid Build Coastguard Worker /* Basic Multi-Link element Control field */
1337*03f9172cSAndroid Build Coastguard Worker wpabuf_put_u8(buf, 0x0);
1338*03f9172cSAndroid Build Coastguard Worker wpabuf_put_u8(buf, 0x0);
1339*03f9172cSAndroid Build Coastguard Worker
1340*03f9172cSAndroid Build Coastguard Worker /* Common Info */
1341*03f9172cSAndroid Build Coastguard Worker wpabuf_put_u8(buf, 0x7); /* length = Length field + MLD MAC address */
1342*03f9172cSAndroid Build Coastguard Worker wpabuf_put_data(buf, mld_addr, ETH_ALEN);
1343*03f9172cSAndroid Build Coastguard Worker }
1344*03f9172cSAndroid Build Coastguard Worker
1345*03f9172cSAndroid Build Coastguard Worker
sme_external_auth_build_buf(struct wpabuf * buf,struct wpabuf * params,const u8 * sa,const u8 * da,u16 auth_transaction,u16 seq_num,u16 status_code,const u8 * mld_addr)1346*03f9172cSAndroid Build Coastguard Worker static int sme_external_auth_build_buf(struct wpabuf *buf,
1347*03f9172cSAndroid Build Coastguard Worker struct wpabuf *params,
1348*03f9172cSAndroid Build Coastguard Worker const u8 *sa, const u8 *da,
1349*03f9172cSAndroid Build Coastguard Worker u16 auth_transaction, u16 seq_num,
1350*03f9172cSAndroid Build Coastguard Worker u16 status_code, const u8 *mld_addr)
1351*03f9172cSAndroid Build Coastguard Worker {
1352*03f9172cSAndroid Build Coastguard Worker struct ieee80211_mgmt *resp;
1353*03f9172cSAndroid Build Coastguard Worker
1354*03f9172cSAndroid Build Coastguard Worker resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
1355*03f9172cSAndroid Build Coastguard Worker u.auth.variable));
1356*03f9172cSAndroid Build Coastguard Worker
1357*03f9172cSAndroid Build Coastguard Worker resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
1358*03f9172cSAndroid Build Coastguard Worker (WLAN_FC_STYPE_AUTH << 4));
1359*03f9172cSAndroid Build Coastguard Worker os_memcpy(resp->da, da, ETH_ALEN);
1360*03f9172cSAndroid Build Coastguard Worker os_memcpy(resp->sa, sa, ETH_ALEN);
1361*03f9172cSAndroid Build Coastguard Worker os_memcpy(resp->bssid, da, ETH_ALEN);
1362*03f9172cSAndroid Build Coastguard Worker resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
1363*03f9172cSAndroid Build Coastguard Worker resp->seq_ctrl = host_to_le16(seq_num << 4);
1364*03f9172cSAndroid Build Coastguard Worker resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
1365*03f9172cSAndroid Build Coastguard Worker resp->u.auth.status_code = host_to_le16(status_code);
1366*03f9172cSAndroid Build Coastguard Worker if (params)
1367*03f9172cSAndroid Build Coastguard Worker wpabuf_put_buf(buf, params);
1368*03f9172cSAndroid Build Coastguard Worker
1369*03f9172cSAndroid Build Coastguard Worker if (mld_addr)
1370*03f9172cSAndroid Build Coastguard Worker wpa_auth_ml_ie(buf, mld_addr);
1371*03f9172cSAndroid Build Coastguard Worker
1372*03f9172cSAndroid Build Coastguard Worker return 0;
1373*03f9172cSAndroid Build Coastguard Worker }
1374*03f9172cSAndroid Build Coastguard Worker
1375*03f9172cSAndroid Build Coastguard Worker
sme_external_auth_send_sae_commit(struct wpa_supplicant * wpa_s,const u8 * bssid,struct wpa_ssid * ssid)1376*03f9172cSAndroid Build Coastguard Worker static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
1377*03f9172cSAndroid Build Coastguard Worker const u8 *bssid,
1378*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid)
1379*03f9172cSAndroid Build Coastguard Worker {
1380*03f9172cSAndroid Build Coastguard Worker struct wpabuf *resp, *buf;
1381*03f9172cSAndroid Build Coastguard Worker int use_pt;
1382*03f9172cSAndroid Build Coastguard Worker bool use_pk;
1383*03f9172cSAndroid Build Coastguard Worker u16 status;
1384*03f9172cSAndroid Build Coastguard Worker
1385*03f9172cSAndroid Build Coastguard Worker resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid,
1386*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_ml_auth ?
1387*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_ap_mld_addr : NULL,
1388*03f9172cSAndroid Build Coastguard Worker 1, 0, &use_pt, &use_pk);
1389*03f9172cSAndroid Build Coastguard Worker if (!resp) {
1390*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
1391*03f9172cSAndroid Build Coastguard Worker return -1;
1392*03f9172cSAndroid Build Coastguard Worker }
1393*03f9172cSAndroid Build Coastguard Worker
1394*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.state = SAE_COMMITTED;
1395*03f9172cSAndroid Build Coastguard Worker buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp) +
1396*03f9172cSAndroid Build Coastguard Worker (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1397*03f9172cSAndroid Build Coastguard Worker 0));
1398*03f9172cSAndroid Build Coastguard Worker if (!buf) {
1399*03f9172cSAndroid Build Coastguard Worker wpabuf_free(resp);
1400*03f9172cSAndroid Build Coastguard Worker return -1;
1401*03f9172cSAndroid Build Coastguard Worker }
1402*03f9172cSAndroid Build Coastguard Worker
1403*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.seq_num++;
1404*03f9172cSAndroid Build Coastguard Worker if (use_pk)
1405*03f9172cSAndroid Build Coastguard Worker status = WLAN_STATUS_SAE_PK;
1406*03f9172cSAndroid Build Coastguard Worker else if (use_pt)
1407*03f9172cSAndroid Build Coastguard Worker status = WLAN_STATUS_SAE_HASH_TO_ELEMENT;
1408*03f9172cSAndroid Build Coastguard Worker else
1409*03f9172cSAndroid Build Coastguard Worker status = WLAN_STATUS_SUCCESS;
1410*03f9172cSAndroid Build Coastguard Worker sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
1411*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_ml_auth ?
1412*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_ap_mld_addr : bssid, 1,
1413*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.seq_num, status,
1414*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_ml_auth ?
1415*03f9172cSAndroid Build Coastguard Worker wpa_s->own_addr : NULL);
1416*03f9172cSAndroid Build Coastguard Worker wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
1417*03f9172cSAndroid Build Coastguard Worker wpabuf_free(resp);
1418*03f9172cSAndroid Build Coastguard Worker wpabuf_free(buf);
1419*03f9172cSAndroid Build Coastguard Worker
1420*03f9172cSAndroid Build Coastguard Worker return 0;
1421*03f9172cSAndroid Build Coastguard Worker }
1422*03f9172cSAndroid Build Coastguard Worker
1423*03f9172cSAndroid Build Coastguard Worker
sme_send_external_auth_status(struct wpa_supplicant * wpa_s,u16 status)1424*03f9172cSAndroid Build Coastguard Worker static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
1425*03f9172cSAndroid Build Coastguard Worker u16 status)
1426*03f9172cSAndroid Build Coastguard Worker {
1427*03f9172cSAndroid Build Coastguard Worker struct external_auth params;
1428*03f9172cSAndroid Build Coastguard Worker
1429*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_wpa_ssid = NULL;
1430*03f9172cSAndroid Build Coastguard Worker os_memset(¶ms, 0, sizeof(params));
1431*03f9172cSAndroid Build Coastguard Worker params.status = status;
1432*03f9172cSAndroid Build Coastguard Worker params.ssid = wpa_s->sme.ext_auth_ssid;
1433*03f9172cSAndroid Build Coastguard Worker params.ssid_len = wpa_s->sme.ext_auth_ssid_len;
1434*03f9172cSAndroid Build Coastguard Worker params.bssid = wpa_s->sme.ext_auth_bssid;
1435*03f9172cSAndroid Build Coastguard Worker if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
1436*03f9172cSAndroid Build Coastguard Worker params.pmkid = wpa_s->sme.sae.pmkid;
1437*03f9172cSAndroid Build Coastguard Worker wpa_drv_send_external_auth_status(wpa_s, ¶ms);
1438*03f9172cSAndroid Build Coastguard Worker }
1439*03f9172cSAndroid Build Coastguard Worker
1440*03f9172cSAndroid Build Coastguard Worker
sme_handle_external_auth_start(struct wpa_supplicant * wpa_s,union wpa_event_data * data)1441*03f9172cSAndroid Build Coastguard Worker static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
1442*03f9172cSAndroid Build Coastguard Worker union wpa_event_data *data)
1443*03f9172cSAndroid Build Coastguard Worker {
1444*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid;
1445*03f9172cSAndroid Build Coastguard Worker size_t ssid_str_len = data->external_auth.ssid_len;
1446*03f9172cSAndroid Build Coastguard Worker const u8 *ssid_str = data->external_auth.ssid;
1447*03f9172cSAndroid Build Coastguard Worker
1448*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_wpa_ssid = NULL;
1449*03f9172cSAndroid Build Coastguard Worker /* Get the SSID conf from the ssid string obtained */
1450*03f9172cSAndroid Build Coastguard Worker for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
1451*03f9172cSAndroid Build Coastguard Worker if (!wpas_network_disabled(wpa_s, ssid) &&
1452*03f9172cSAndroid Build Coastguard Worker ssid_str_len == ssid->ssid_len &&
1453*03f9172cSAndroid Build Coastguard Worker os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
1454*03f9172cSAndroid Build Coastguard Worker wpa_key_mgmt_sae(ssid->key_mgmt)) {
1455*03f9172cSAndroid Build Coastguard Worker /* Make sure PT is derived */
1456*03f9172cSAndroid Build Coastguard Worker wpa_s_setup_sae_pt(wpa_s->conf, ssid, false);
1457*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_wpa_ssid = ssid;
1458*03f9172cSAndroid Build Coastguard Worker break;
1459*03f9172cSAndroid Build Coastguard Worker }
1460*03f9172cSAndroid Build Coastguard Worker }
1461*03f9172cSAndroid Build Coastguard Worker if (!ssid ||
1462*03f9172cSAndroid Build Coastguard Worker sme_external_auth_send_sae_commit(wpa_s, data->external_auth.bssid,
1463*03f9172cSAndroid Build Coastguard Worker ssid) < 0)
1464*03f9172cSAndroid Build Coastguard Worker return -1;
1465*03f9172cSAndroid Build Coastguard Worker
1466*03f9172cSAndroid Build Coastguard Worker return 0;
1467*03f9172cSAndroid Build Coastguard Worker }
1468*03f9172cSAndroid Build Coastguard Worker
1469*03f9172cSAndroid Build Coastguard Worker
sme_external_auth_send_sae_confirm(struct wpa_supplicant * wpa_s,const u8 * da)1470*03f9172cSAndroid Build Coastguard Worker static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s,
1471*03f9172cSAndroid Build Coastguard Worker const u8 *da)
1472*03f9172cSAndroid Build Coastguard Worker {
1473*03f9172cSAndroid Build Coastguard Worker struct wpabuf *resp, *buf;
1474*03f9172cSAndroid Build Coastguard Worker
1475*03f9172cSAndroid Build Coastguard Worker resp = sme_auth_build_sae_confirm(wpa_s, 1);
1476*03f9172cSAndroid Build Coastguard Worker if (!resp) {
1477*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SAE: Confirm message buf alloc failure");
1478*03f9172cSAndroid Build Coastguard Worker return;
1479*03f9172cSAndroid Build Coastguard Worker }
1480*03f9172cSAndroid Build Coastguard Worker
1481*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.state = SAE_CONFIRMED;
1482*03f9172cSAndroid Build Coastguard Worker buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN + wpabuf_len(resp) +
1483*03f9172cSAndroid Build Coastguard Worker (wpa_s->sme.ext_ml_auth ? WPA_AUTH_FRAME_ML_IE_LEN :
1484*03f9172cSAndroid Build Coastguard Worker 0));
1485*03f9172cSAndroid Build Coastguard Worker if (!buf) {
1486*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SAE: Auth Confirm buf alloc failure");
1487*03f9172cSAndroid Build Coastguard Worker wpabuf_free(resp);
1488*03f9172cSAndroid Build Coastguard Worker return;
1489*03f9172cSAndroid Build Coastguard Worker }
1490*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.seq_num++;
1491*03f9172cSAndroid Build Coastguard Worker sme_external_auth_build_buf(buf, resp, wpa_s->own_addr,
1492*03f9172cSAndroid Build Coastguard Worker da, 2, wpa_s->sme.seq_num,
1493*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_SUCCESS,
1494*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_ml_auth ?
1495*03f9172cSAndroid Build Coastguard Worker wpa_s->own_addr : NULL);
1496*03f9172cSAndroid Build Coastguard Worker
1497*03f9172cSAndroid Build Coastguard Worker wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0);
1498*03f9172cSAndroid Build Coastguard Worker wpabuf_free(resp);
1499*03f9172cSAndroid Build Coastguard Worker wpabuf_free(buf);
1500*03f9172cSAndroid Build Coastguard Worker }
1501*03f9172cSAndroid Build Coastguard Worker
1502*03f9172cSAndroid Build Coastguard Worker
is_sae_key_mgmt_suite(struct wpa_supplicant * wpa_s,u32 suite)1503*03f9172cSAndroid Build Coastguard Worker static bool is_sae_key_mgmt_suite(struct wpa_supplicant *wpa_s, u32 suite)
1504*03f9172cSAndroid Build Coastguard Worker {
1505*03f9172cSAndroid Build Coastguard Worker /* suite is supposed to be the selector value in host byte order with
1506*03f9172cSAndroid Build Coastguard Worker * the OUI in three most significant octets. However, the initial
1507*03f9172cSAndroid Build Coastguard Worker * implementation swapped that byte order and did not work with drivers
1508*03f9172cSAndroid Build Coastguard Worker * that followed the expected byte order. Keep a workaround here to
1509*03f9172cSAndroid Build Coastguard Worker * match that initial implementation so that already deployed use cases
1510*03f9172cSAndroid Build Coastguard Worker * remain functional. */
1511*03f9172cSAndroid Build Coastguard Worker if (RSN_SELECTOR_GET(&suite) == RSN_AUTH_KEY_MGMT_SAE) {
1512*03f9172cSAndroid Build Coastguard Worker /* Old drivers which follow initial implementation send SAE AKM
1513*03f9172cSAndroid Build Coastguard Worker * for both SAE and FT-SAE connections. In that case, determine
1514*03f9172cSAndroid Build Coastguard Worker * the actual AKM from wpa_s->key_mgmt. */
1515*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_key_mgmt = wpa_s->key_mgmt;
1516*03f9172cSAndroid Build Coastguard Worker return true;
1517*03f9172cSAndroid Build Coastguard Worker }
1518*03f9172cSAndroid Build Coastguard Worker
1519*03f9172cSAndroid Build Coastguard Worker if (suite == RSN_AUTH_KEY_MGMT_SAE)
1520*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE;
1521*03f9172cSAndroid Build Coastguard Worker else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE)
1522*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE;
1523*03f9172cSAndroid Build Coastguard Worker else if (suite == RSN_AUTH_KEY_MGMT_SAE_EXT_KEY)
1524*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_SAE_EXT_KEY;
1525*03f9172cSAndroid Build Coastguard Worker else if (suite == RSN_AUTH_KEY_MGMT_FT_SAE_EXT_KEY)
1526*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_key_mgmt = WPA_KEY_MGMT_FT_SAE_EXT_KEY;
1527*03f9172cSAndroid Build Coastguard Worker else
1528*03f9172cSAndroid Build Coastguard Worker return false;
1529*03f9172cSAndroid Build Coastguard Worker
1530*03f9172cSAndroid Build Coastguard Worker return true;
1531*03f9172cSAndroid Build Coastguard Worker }
1532*03f9172cSAndroid Build Coastguard Worker
1533*03f9172cSAndroid Build Coastguard Worker
sme_external_auth_trigger(struct wpa_supplicant * wpa_s,union wpa_event_data * data)1534*03f9172cSAndroid Build Coastguard Worker void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
1535*03f9172cSAndroid Build Coastguard Worker union wpa_event_data *data)
1536*03f9172cSAndroid Build Coastguard Worker {
1537*03f9172cSAndroid Build Coastguard Worker if (!is_sae_key_mgmt_suite(wpa_s, data->external_auth.key_mgmt_suite))
1538*03f9172cSAndroid Build Coastguard Worker return;
1539*03f9172cSAndroid Build Coastguard Worker
1540*03f9172cSAndroid Build Coastguard Worker if (data->external_auth.action == EXT_AUTH_START) {
1541*03f9172cSAndroid Build Coastguard Worker if (!data->external_auth.bssid || !data->external_auth.ssid)
1542*03f9172cSAndroid Build Coastguard Worker return;
1543*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid,
1544*03f9172cSAndroid Build Coastguard Worker ETH_ALEN);
1545*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid,
1546*03f9172cSAndroid Build Coastguard Worker data->external_auth.ssid_len);
1547*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len;
1548*03f9172cSAndroid Build Coastguard Worker if (data->external_auth.mld_addr) {
1549*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_ml_auth = true;
1550*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.ext_auth_ap_mld_addr,
1551*03f9172cSAndroid Build Coastguard Worker data->external_auth.mld_addr, ETH_ALEN);
1552*03f9172cSAndroid Build Coastguard Worker } else {
1553*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_ml_auth = false;
1554*03f9172cSAndroid Build Coastguard Worker }
1555*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.seq_num = 0;
1556*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.state = SAE_NOTHING;
1557*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.send_confirm = 0;
1558*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_group_index = 0;
1559*03f9172cSAndroid Build Coastguard Worker if (sme_handle_external_auth_start(wpa_s, data) < 0)
1560*03f9172cSAndroid Build Coastguard Worker sme_send_external_auth_status(wpa_s,
1561*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_UNSPECIFIED_FAILURE);
1562*03f9172cSAndroid Build Coastguard Worker } else if (data->external_auth.action == EXT_AUTH_ABORT) {
1563*03f9172cSAndroid Build Coastguard Worker /* Report failure to driver for the wrong trigger */
1564*03f9172cSAndroid Build Coastguard Worker sme_send_external_auth_status(wpa_s,
1565*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_UNSPECIFIED_FAILURE);
1566*03f9172cSAndroid Build Coastguard Worker }
1567*03f9172cSAndroid Build Coastguard Worker }
1568*03f9172cSAndroid Build Coastguard Worker
1569*03f9172cSAndroid Build Coastguard Worker
sme_sae_is_group_enabled(struct wpa_supplicant * wpa_s,int group)1570*03f9172cSAndroid Build Coastguard Worker static int sme_sae_is_group_enabled(struct wpa_supplicant *wpa_s, int group)
1571*03f9172cSAndroid Build Coastguard Worker {
1572*03f9172cSAndroid Build Coastguard Worker int *groups = wpa_s->conf->sae_groups;
1573*03f9172cSAndroid Build Coastguard Worker int default_groups[] = { 19, 20, 21, 0 };
1574*03f9172cSAndroid Build Coastguard Worker int i;
1575*03f9172cSAndroid Build Coastguard Worker
1576*03f9172cSAndroid Build Coastguard Worker if (!groups)
1577*03f9172cSAndroid Build Coastguard Worker groups = default_groups;
1578*03f9172cSAndroid Build Coastguard Worker
1579*03f9172cSAndroid Build Coastguard Worker for (i = 0; groups[i] > 0; i++) {
1580*03f9172cSAndroid Build Coastguard Worker if (groups[i] == group)
1581*03f9172cSAndroid Build Coastguard Worker return 1;
1582*03f9172cSAndroid Build Coastguard Worker }
1583*03f9172cSAndroid Build Coastguard Worker
1584*03f9172cSAndroid Build Coastguard Worker return 0;
1585*03f9172cSAndroid Build Coastguard Worker }
1586*03f9172cSAndroid Build Coastguard Worker
1587*03f9172cSAndroid Build Coastguard Worker
sme_check_sae_rejected_groups(struct wpa_supplicant * wpa_s,const struct wpabuf * groups)1588*03f9172cSAndroid Build Coastguard Worker static int sme_check_sae_rejected_groups(struct wpa_supplicant *wpa_s,
1589*03f9172cSAndroid Build Coastguard Worker const struct wpabuf *groups)
1590*03f9172cSAndroid Build Coastguard Worker {
1591*03f9172cSAndroid Build Coastguard Worker size_t i, count, len;
1592*03f9172cSAndroid Build Coastguard Worker const u8 *pos;
1593*03f9172cSAndroid Build Coastguard Worker
1594*03f9172cSAndroid Build Coastguard Worker if (!groups)
1595*03f9172cSAndroid Build Coastguard Worker return 0;
1596*03f9172cSAndroid Build Coastguard Worker
1597*03f9172cSAndroid Build Coastguard Worker pos = wpabuf_head(groups);
1598*03f9172cSAndroid Build Coastguard Worker len = wpabuf_len(groups);
1599*03f9172cSAndroid Build Coastguard Worker if (len & 1) {
1600*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1601*03f9172cSAndroid Build Coastguard Worker "SAE: Invalid length of the Rejected Groups element payload: %zu",
1602*03f9172cSAndroid Build Coastguard Worker len);
1603*03f9172cSAndroid Build Coastguard Worker return 1;
1604*03f9172cSAndroid Build Coastguard Worker }
1605*03f9172cSAndroid Build Coastguard Worker count = len / 2;
1606*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < count; i++) {
1607*03f9172cSAndroid Build Coastguard Worker int enabled;
1608*03f9172cSAndroid Build Coastguard Worker u16 group;
1609*03f9172cSAndroid Build Coastguard Worker
1610*03f9172cSAndroid Build Coastguard Worker group = WPA_GET_LE16(pos);
1611*03f9172cSAndroid Build Coastguard Worker pos += 2;
1612*03f9172cSAndroid Build Coastguard Worker enabled = sme_sae_is_group_enabled(wpa_s, group);
1613*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
1614*03f9172cSAndroid Build Coastguard Worker group, enabled ? "enabled" : "disabled");
1615*03f9172cSAndroid Build Coastguard Worker if (enabled)
1616*03f9172cSAndroid Build Coastguard Worker return 1;
1617*03f9172cSAndroid Build Coastguard Worker }
1618*03f9172cSAndroid Build Coastguard Worker
1619*03f9172cSAndroid Build Coastguard Worker return 0;
1620*03f9172cSAndroid Build Coastguard Worker }
1621*03f9172cSAndroid Build Coastguard Worker
1622*03f9172cSAndroid Build Coastguard Worker
sme_external_ml_auth(struct wpa_supplicant * wpa_s,const u8 * data,size_t len,int ie_offset,u16 status_code)1623*03f9172cSAndroid Build Coastguard Worker static int sme_external_ml_auth(struct wpa_supplicant *wpa_s,
1624*03f9172cSAndroid Build Coastguard Worker const u8 *data, size_t len, int ie_offset,
1625*03f9172cSAndroid Build Coastguard Worker u16 status_code)
1626*03f9172cSAndroid Build Coastguard Worker {
1627*03f9172cSAndroid Build Coastguard Worker struct ieee802_11_elems elems;
1628*03f9172cSAndroid Build Coastguard Worker const u8 *mld_addr;
1629*03f9172cSAndroid Build Coastguard Worker
1630*03f9172cSAndroid Build Coastguard Worker if (ieee802_11_parse_elems(data + ie_offset, len - ie_offset,
1631*03f9172cSAndroid Build Coastguard Worker &elems, 0) == ParseFailed) {
1632*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: Failed parsing elements");
1633*03f9172cSAndroid Build Coastguard Worker return -1;
1634*03f9172cSAndroid Build Coastguard Worker }
1635*03f9172cSAndroid Build Coastguard Worker
1636*03f9172cSAndroid Build Coastguard Worker if (!elems.basic_mle || !elems.basic_mle_len) {
1637*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: No ML element in authentication");
1638*03f9172cSAndroid Build Coastguard Worker if (status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ ||
1639*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_SUCCESS ||
1640*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
1641*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_SAE_PK)
1642*03f9172cSAndroid Build Coastguard Worker return -1;
1643*03f9172cSAndroid Build Coastguard Worker /* Accept missing Multi-Link element in failed authentication
1644*03f9172cSAndroid Build Coastguard Worker * cases. */
1645*03f9172cSAndroid Build Coastguard Worker return 0;
1646*03f9172cSAndroid Build Coastguard Worker }
1647*03f9172cSAndroid Build Coastguard Worker
1648*03f9172cSAndroid Build Coastguard Worker mld_addr = get_basic_mle_mld_addr(elems.basic_mle, elems.basic_mle_len);
1649*03f9172cSAndroid Build Coastguard Worker if (!mld_addr) {
1650*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: No MLD address in ML element");
1651*03f9172cSAndroid Build Coastguard Worker return -1;
1652*03f9172cSAndroid Build Coastguard Worker }
1653*03f9172cSAndroid Build Coastguard Worker
1654*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: mld_address=" MACSTR, MAC2STR(mld_addr));
1655*03f9172cSAndroid Build Coastguard Worker
1656*03f9172cSAndroid Build Coastguard Worker if (!ether_addr_equal(wpa_s->sme.ext_auth_ap_mld_addr, mld_addr)) {
1657*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "MLD: Unexpected MLD address (expected "
1658*03f9172cSAndroid Build Coastguard Worker MACSTR ")",
1659*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->sme.ext_auth_ap_mld_addr));
1660*03f9172cSAndroid Build Coastguard Worker return -1;
1661*03f9172cSAndroid Build Coastguard Worker }
1662*03f9172cSAndroid Build Coastguard Worker
1663*03f9172cSAndroid Build Coastguard Worker return 0;
1664*03f9172cSAndroid Build Coastguard Worker }
1665*03f9172cSAndroid Build Coastguard Worker
1666*03f9172cSAndroid Build Coastguard Worker
sme_sae_auth(struct wpa_supplicant * wpa_s,u16 auth_transaction,u16 status_code,const u8 * data,size_t len,int external,const u8 * sa,int * ie_offset)1667*03f9172cSAndroid Build Coastguard Worker static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
1668*03f9172cSAndroid Build Coastguard Worker u16 status_code, const u8 *data, size_t len,
1669*03f9172cSAndroid Build Coastguard Worker int external, const u8 *sa, int *ie_offset)
1670*03f9172cSAndroid Build Coastguard Worker {
1671*03f9172cSAndroid Build Coastguard Worker int *groups;
1672*03f9172cSAndroid Build Coastguard Worker
1673*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
1674*03f9172cSAndroid Build Coastguard Worker "status code %u", auth_transaction, status_code);
1675*03f9172cSAndroid Build Coastguard Worker
1676*03f9172cSAndroid Build Coastguard Worker if (auth_transaction == 1 &&
1677*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1678*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.state == SAE_COMMITTED &&
1679*03f9172cSAndroid Build Coastguard Worker ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1680*03f9172cSAndroid Build Coastguard Worker (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
1681*03f9172cSAndroid Build Coastguard Worker int default_groups[] = { 19, 20, 21, 0 };
1682*03f9172cSAndroid Build Coastguard Worker u16 group;
1683*03f9172cSAndroid Build Coastguard Worker const u8 *token_pos;
1684*03f9172cSAndroid Build Coastguard Worker size_t token_len;
1685*03f9172cSAndroid Build Coastguard Worker int h2e = 0;
1686*03f9172cSAndroid Build Coastguard Worker
1687*03f9172cSAndroid Build Coastguard Worker groups = wpa_s->conf->sae_groups;
1688*03f9172cSAndroid Build Coastguard Worker if (!groups || groups[0] <= 0)
1689*03f9172cSAndroid Build Coastguard Worker groups = default_groups;
1690*03f9172cSAndroid Build Coastguard Worker
1691*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG, "SME: SAE anti-clogging token request",
1692*03f9172cSAndroid Build Coastguard Worker data, len);
1693*03f9172cSAndroid Build Coastguard Worker if (len < sizeof(le16)) {
1694*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
1695*03f9172cSAndroid Build Coastguard Worker "SME: Too short SAE anti-clogging token request");
1696*03f9172cSAndroid Build Coastguard Worker return -1;
1697*03f9172cSAndroid Build Coastguard Worker }
1698*03f9172cSAndroid Build Coastguard Worker group = WPA_GET_LE16(data);
1699*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
1700*03f9172cSAndroid Build Coastguard Worker "SME: SAE anti-clogging token requested (group %u)",
1701*03f9172cSAndroid Build Coastguard Worker group);
1702*03f9172cSAndroid Build Coastguard Worker if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
1703*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_SUCCESS) {
1704*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_ERROR,
1705*03f9172cSAndroid Build Coastguard Worker "SME: SAE group %u of anti-clogging request is invalid",
1706*03f9172cSAndroid Build Coastguard Worker group);
1707*03f9172cSAndroid Build Coastguard Worker return -1;
1708*03f9172cSAndroid Build Coastguard Worker }
1709*03f9172cSAndroid Build Coastguard Worker wpabuf_free(wpa_s->sme.sae_token);
1710*03f9172cSAndroid Build Coastguard Worker token_pos = data + sizeof(le16);
1711*03f9172cSAndroid Build Coastguard Worker token_len = len - sizeof(le16);
1712*03f9172cSAndroid Build Coastguard Worker h2e = wpa_s->sme.sae.h2e;
1713*03f9172cSAndroid Build Coastguard Worker if (h2e) {
1714*03f9172cSAndroid Build Coastguard Worker u8 id, elen, extid;
1715*03f9172cSAndroid Build Coastguard Worker
1716*03f9172cSAndroid Build Coastguard Worker if (token_len < 3) {
1717*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
1718*03f9172cSAndroid Build Coastguard Worker "SME: Too short SAE anti-clogging token container");
1719*03f9172cSAndroid Build Coastguard Worker return -1;
1720*03f9172cSAndroid Build Coastguard Worker }
1721*03f9172cSAndroid Build Coastguard Worker id = *token_pos++;
1722*03f9172cSAndroid Build Coastguard Worker elen = *token_pos++;
1723*03f9172cSAndroid Build Coastguard Worker extid = *token_pos++;
1724*03f9172cSAndroid Build Coastguard Worker if (id != WLAN_EID_EXTENSION ||
1725*03f9172cSAndroid Build Coastguard Worker elen == 0 || elen > token_len - 2 ||
1726*03f9172cSAndroid Build Coastguard Worker extid != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN) {
1727*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
1728*03f9172cSAndroid Build Coastguard Worker "SME: Invalid SAE anti-clogging token container header");
1729*03f9172cSAndroid Build Coastguard Worker return -1;
1730*03f9172cSAndroid Build Coastguard Worker }
1731*03f9172cSAndroid Build Coastguard Worker token_len = elen - 1;
1732*03f9172cSAndroid Build Coastguard Worker }
1733*03f9172cSAndroid Build Coastguard Worker
1734*03f9172cSAndroid Build Coastguard Worker *ie_offset = token_pos + token_len - data;
1735*03f9172cSAndroid Build Coastguard Worker
1736*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_token = wpabuf_alloc_copy(token_pos, token_len);
1737*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->sme.sae_token) {
1738*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_ERROR,
1739*03f9172cSAndroid Build Coastguard Worker "SME: Failed to allocate SAE token");
1740*03f9172cSAndroid Build Coastguard Worker return -1;
1741*03f9172cSAndroid Build Coastguard Worker }
1742*03f9172cSAndroid Build Coastguard Worker
1743*03f9172cSAndroid Build Coastguard Worker wpa_hexdump_buf(MSG_DEBUG, "SME: Requested anti-clogging token",
1744*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_token);
1745*03f9172cSAndroid Build Coastguard Worker if (!external) {
1746*03f9172cSAndroid Build Coastguard Worker sme_send_authentication(wpa_s, wpa_s->current_bss,
1747*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid, 2);
1748*03f9172cSAndroid Build Coastguard Worker } else {
1749*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.ext_ml_auth &&
1750*03f9172cSAndroid Build Coastguard Worker sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1751*03f9172cSAndroid Build Coastguard Worker status_code))
1752*03f9172cSAndroid Build Coastguard Worker return -1;
1753*03f9172cSAndroid Build Coastguard Worker
1754*03f9172cSAndroid Build Coastguard Worker sme_external_auth_send_sae_commit(
1755*03f9172cSAndroid Build Coastguard Worker wpa_s, wpa_s->sme.ext_auth_bssid,
1756*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_wpa_ssid);
1757*03f9172cSAndroid Build Coastguard Worker }
1758*03f9172cSAndroid Build Coastguard Worker return 0;
1759*03f9172cSAndroid Build Coastguard Worker }
1760*03f9172cSAndroid Build Coastguard Worker
1761*03f9172cSAndroid Build Coastguard Worker if (auth_transaction == 1 &&
1762*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1763*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.state == SAE_COMMITTED &&
1764*03f9172cSAndroid Build Coastguard Worker ((external && wpa_s->sme.ext_auth_wpa_ssid) ||
1765*03f9172cSAndroid Build Coastguard Worker (!external && wpa_s->current_bss && wpa_s->current_ssid))) {
1766*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
1767*03f9172cSAndroid Build Coastguard Worker int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
1768*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.group);
1769*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_group_index++;
1770*03f9172cSAndroid Build Coastguard Worker if (sme_set_sae_group(wpa_s, external) < 0)
1771*03f9172cSAndroid Build Coastguard Worker return -1; /* no other groups enabled */
1772*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
1773*03f9172cSAndroid Build Coastguard Worker if (!external) {
1774*03f9172cSAndroid Build Coastguard Worker sme_send_authentication(wpa_s, wpa_s->current_bss,
1775*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid, 1);
1776*03f9172cSAndroid Build Coastguard Worker } else {
1777*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.ext_ml_auth &&
1778*03f9172cSAndroid Build Coastguard Worker sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1779*03f9172cSAndroid Build Coastguard Worker status_code))
1780*03f9172cSAndroid Build Coastguard Worker return -1;
1781*03f9172cSAndroid Build Coastguard Worker
1782*03f9172cSAndroid Build Coastguard Worker sme_external_auth_send_sae_commit(
1783*03f9172cSAndroid Build Coastguard Worker wpa_s, wpa_s->sme.ext_auth_bssid,
1784*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_wpa_ssid);
1785*03f9172cSAndroid Build Coastguard Worker }
1786*03f9172cSAndroid Build Coastguard Worker return 0;
1787*03f9172cSAndroid Build Coastguard Worker }
1788*03f9172cSAndroid Build Coastguard Worker
1789*03f9172cSAndroid Build Coastguard Worker if (auth_transaction == 1 &&
1790*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1791*03f9172cSAndroid Build Coastguard Worker const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1792*03f9172cSAndroid Build Coastguard Worker
1793*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO,
1794*03f9172cSAndroid Build Coastguard Worker WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER MACSTR,
1795*03f9172cSAndroid Build Coastguard Worker MAC2STR(bssid));
1796*03f9172cSAndroid Build Coastguard Worker return -1;
1797*03f9172cSAndroid Build Coastguard Worker }
1798*03f9172cSAndroid Build Coastguard Worker
1799*03f9172cSAndroid Build Coastguard Worker if (status_code != WLAN_STATUS_SUCCESS &&
1800*03f9172cSAndroid Build Coastguard Worker status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT &&
1801*03f9172cSAndroid Build Coastguard Worker status_code != WLAN_STATUS_SAE_PK) {
1802*03f9172cSAndroid Build Coastguard Worker const u8 *bssid = sa ? sa : wpa_s->pending_bssid;
1803*03f9172cSAndroid Build Coastguard Worker
1804*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
1805*03f9172cSAndroid Build Coastguard Worker " auth_type=%u auth_transaction=%u status_code=%u",
1806*03f9172cSAndroid Build Coastguard Worker MAC2STR(bssid), WLAN_AUTH_SAE,
1807*03f9172cSAndroid Build Coastguard Worker auth_transaction, status_code);
1808*03f9172cSAndroid Build Coastguard Worker return -2;
1809*03f9172cSAndroid Build Coastguard Worker }
1810*03f9172cSAndroid Build Coastguard Worker
1811*03f9172cSAndroid Build Coastguard Worker if (auth_transaction == 1) {
1812*03f9172cSAndroid Build Coastguard Worker u16 res;
1813*03f9172cSAndroid Build Coastguard Worker
1814*03f9172cSAndroid Build Coastguard Worker groups = wpa_s->conf->sae_groups;
1815*03f9172cSAndroid Build Coastguard Worker
1816*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
1817*03f9172cSAndroid Build Coastguard Worker if ((external && !wpa_s->sme.ext_auth_wpa_ssid) ||
1818*03f9172cSAndroid Build Coastguard Worker (!external &&
1819*03f9172cSAndroid Build Coastguard Worker (!wpa_s->current_bss || !wpa_s->current_ssid)))
1820*03f9172cSAndroid Build Coastguard Worker return -1;
1821*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sae.state != SAE_COMMITTED) {
1822*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1823*03f9172cSAndroid Build Coastguard Worker "SAE: Ignore commit message while waiting for confirm");
1824*03f9172cSAndroid Build Coastguard Worker return 0;
1825*03f9172cSAndroid Build Coastguard Worker }
1826*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sae.h2e && status_code == WLAN_STATUS_SUCCESS) {
1827*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1828*03f9172cSAndroid Build Coastguard Worker "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected");
1829*03f9172cSAndroid Build Coastguard Worker return -1;
1830*03f9172cSAndroid Build Coastguard Worker }
1831*03f9172cSAndroid Build Coastguard Worker if ((!wpa_s->sme.sae.h2e || wpa_s->sme.sae.pk) &&
1832*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) {
1833*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1834*03f9172cSAndroid Build Coastguard Worker "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected");
1835*03f9172cSAndroid Build Coastguard Worker return -1;
1836*03f9172cSAndroid Build Coastguard Worker }
1837*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->sme.sae.pk &&
1838*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_SAE_PK) {
1839*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1840*03f9172cSAndroid Build Coastguard Worker "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected");
1841*03f9172cSAndroid Build Coastguard Worker return -1;
1842*03f9172cSAndroid Build Coastguard Worker }
1843*03f9172cSAndroid Build Coastguard Worker
1844*03f9172cSAndroid Build Coastguard Worker if (groups && groups[0] <= 0)
1845*03f9172cSAndroid Build Coastguard Worker groups = NULL;
1846*03f9172cSAndroid Build Coastguard Worker res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
1847*03f9172cSAndroid Build Coastguard Worker groups, status_code ==
1848*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_SAE_HASH_TO_ELEMENT ||
1849*03f9172cSAndroid Build Coastguard Worker status_code == WLAN_STATUS_SAE_PK,
1850*03f9172cSAndroid Build Coastguard Worker ie_offset);
1851*03f9172cSAndroid Build Coastguard Worker if (res == SAE_SILENTLY_DISCARD) {
1852*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1853*03f9172cSAndroid Build Coastguard Worker "SAE: Drop commit message due to reflection attack");
1854*03f9172cSAndroid Build Coastguard Worker return 0;
1855*03f9172cSAndroid Build Coastguard Worker }
1856*03f9172cSAndroid Build Coastguard Worker if (res != WLAN_STATUS_SUCCESS)
1857*03f9172cSAndroid Build Coastguard Worker return -1;
1858*03f9172cSAndroid Build Coastguard Worker
1859*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sae.tmp &&
1860*03f9172cSAndroid Build Coastguard Worker sme_check_sae_rejected_groups(
1861*03f9172cSAndroid Build Coastguard Worker wpa_s,
1862*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.tmp->peer_rejected_groups))
1863*03f9172cSAndroid Build Coastguard Worker return -1;
1864*03f9172cSAndroid Build Coastguard Worker
1865*03f9172cSAndroid Build Coastguard Worker if (sae_process_commit(&wpa_s->sme.sae) < 0) {
1866*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
1867*03f9172cSAndroid Build Coastguard Worker "commit");
1868*03f9172cSAndroid Build Coastguard Worker return -1;
1869*03f9172cSAndroid Build Coastguard Worker }
1870*03f9172cSAndroid Build Coastguard Worker
1871*03f9172cSAndroid Build Coastguard Worker wpabuf_free(wpa_s->sme.sae_token);
1872*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_token = NULL;
1873*03f9172cSAndroid Build Coastguard Worker if (!external) {
1874*03f9172cSAndroid Build Coastguard Worker sme_send_authentication(wpa_s, wpa_s->current_bss,
1875*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid, 0);
1876*03f9172cSAndroid Build Coastguard Worker } else {
1877*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.ext_ml_auth &&
1878*03f9172cSAndroid Build Coastguard Worker sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1879*03f9172cSAndroid Build Coastguard Worker status_code))
1880*03f9172cSAndroid Build Coastguard Worker return -1;
1881*03f9172cSAndroid Build Coastguard Worker
1882*03f9172cSAndroid Build Coastguard Worker sme_external_auth_send_sae_confirm(wpa_s, sa);
1883*03f9172cSAndroid Build Coastguard Worker }
1884*03f9172cSAndroid Build Coastguard Worker return 0;
1885*03f9172cSAndroid Build Coastguard Worker } else if (auth_transaction == 2) {
1886*03f9172cSAndroid Build Coastguard Worker if (status_code != WLAN_STATUS_SUCCESS)
1887*03f9172cSAndroid Build Coastguard Worker return -1;
1888*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
1889*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sae.state != SAE_CONFIRMED)
1890*03f9172cSAndroid Build Coastguard Worker return -1;
1891*03f9172cSAndroid Build Coastguard Worker if (sae_check_confirm(&wpa_s->sme.sae, data, len,
1892*03f9172cSAndroid Build Coastguard Worker ie_offset) < 0)
1893*03f9172cSAndroid Build Coastguard Worker return -1;
1894*03f9172cSAndroid Build Coastguard Worker if (external && wpa_s->sme.ext_ml_auth &&
1895*03f9172cSAndroid Build Coastguard Worker sme_external_ml_auth(wpa_s, data, len, *ie_offset,
1896*03f9172cSAndroid Build Coastguard Worker status_code))
1897*03f9172cSAndroid Build Coastguard Worker return -1;
1898*03f9172cSAndroid Build Coastguard Worker
1899*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.state = SAE_ACCEPTED;
1900*03f9172cSAndroid Build Coastguard Worker sae_clear_temp_data(&wpa_s->sme.sae);
1901*03f9172cSAndroid Build Coastguard Worker wpa_s_clear_sae_rejected(wpa_s);
1902*03f9172cSAndroid Build Coastguard Worker
1903*03f9172cSAndroid Build Coastguard Worker if (external) {
1904*03f9172cSAndroid Build Coastguard Worker /* Report success to driver */
1905*03f9172cSAndroid Build Coastguard Worker sme_send_external_auth_status(wpa_s,
1906*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_SUCCESS);
1907*03f9172cSAndroid Build Coastguard Worker }
1908*03f9172cSAndroid Build Coastguard Worker
1909*03f9172cSAndroid Build Coastguard Worker return 1;
1910*03f9172cSAndroid Build Coastguard Worker }
1911*03f9172cSAndroid Build Coastguard Worker
1912*03f9172cSAndroid Build Coastguard Worker return -1;
1913*03f9172cSAndroid Build Coastguard Worker }
1914*03f9172cSAndroid Build Coastguard Worker
1915*03f9172cSAndroid Build Coastguard Worker
sme_sae_set_pmk(struct wpa_supplicant * wpa_s,const u8 * bssid)1916*03f9172cSAndroid Build Coastguard Worker static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
1917*03f9172cSAndroid Build Coastguard Worker {
1918*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
1919*03f9172cSAndroid Build Coastguard Worker "SME: SAE completed - setting PMK for 4-way handshake");
1920*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, wpa_s->sme.sae.pmk_len,
1921*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.pmkid, bssid);
1922*03f9172cSAndroid Build Coastguard Worker if (wpa_s->conf->sae_pmkid_in_assoc) {
1923*03f9172cSAndroid Build Coastguard Worker /* Update the own RSNE contents now that we have set the PMK
1924*03f9172cSAndroid Build Coastguard Worker * and added a PMKSA cache entry based on the successfully
1925*03f9172cSAndroid Build Coastguard Worker * completed SAE exchange. In practice, this will add the PMKID
1926*03f9172cSAndroid Build Coastguard Worker * into RSNE. */
1927*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.assoc_req_ie_len + 2 + PMKID_LEN >
1928*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie)) {
1929*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_WARNING,
1930*03f9172cSAndroid Build Coastguard Worker "RSN: Not enough room for inserting own PMKID into RSNE");
1931*03f9172cSAndroid Build Coastguard Worker return -1;
1932*03f9172cSAndroid Build Coastguard Worker }
1933*03f9172cSAndroid Build Coastguard Worker if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
1934*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
1935*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae.pmkid, true) < 0)
1936*03f9172cSAndroid Build Coastguard Worker return -1;
1937*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG,
1938*03f9172cSAndroid Build Coastguard Worker "SME: Updated Association Request IEs",
1939*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
1940*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len);
1941*03f9172cSAndroid Build Coastguard Worker }
1942*03f9172cSAndroid Build Coastguard Worker
1943*03f9172cSAndroid Build Coastguard Worker return 0;
1944*03f9172cSAndroid Build Coastguard Worker }
1945*03f9172cSAndroid Build Coastguard Worker
1946*03f9172cSAndroid Build Coastguard Worker
sme_external_auth_mgmt_rx(struct wpa_supplicant * wpa_s,const u8 * auth_frame,size_t len)1947*03f9172cSAndroid Build Coastguard Worker void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
1948*03f9172cSAndroid Build Coastguard Worker const u8 *auth_frame, size_t len)
1949*03f9172cSAndroid Build Coastguard Worker {
1950*03f9172cSAndroid Build Coastguard Worker const struct ieee80211_mgmt *header;
1951*03f9172cSAndroid Build Coastguard Worker size_t auth_length;
1952*03f9172cSAndroid Build Coastguard Worker
1953*03f9172cSAndroid Build Coastguard Worker header = (const struct ieee80211_mgmt *) auth_frame;
1954*03f9172cSAndroid Build Coastguard Worker auth_length = IEEE80211_HDRLEN + sizeof(header->u.auth);
1955*03f9172cSAndroid Build Coastguard Worker
1956*03f9172cSAndroid Build Coastguard Worker if (len < auth_length) {
1957*03f9172cSAndroid Build Coastguard Worker /* Notify failure to the driver */
1958*03f9172cSAndroid Build Coastguard Worker sme_send_external_auth_status(wpa_s,
1959*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_UNSPECIFIED_FAILURE);
1960*03f9172cSAndroid Build Coastguard Worker return;
1961*03f9172cSAndroid Build Coastguard Worker }
1962*03f9172cSAndroid Build Coastguard Worker
1963*03f9172cSAndroid Build Coastguard Worker if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
1964*03f9172cSAndroid Build Coastguard Worker int res;
1965*03f9172cSAndroid Build Coastguard Worker int ie_offset = 0;
1966*03f9172cSAndroid Build Coastguard Worker
1967*03f9172cSAndroid Build Coastguard Worker res = sme_sae_auth(
1968*03f9172cSAndroid Build Coastguard Worker wpa_s, le_to_host16(header->u.auth.auth_transaction),
1969*03f9172cSAndroid Build Coastguard Worker le_to_host16(header->u.auth.status_code),
1970*03f9172cSAndroid Build Coastguard Worker header->u.auth.variable,
1971*03f9172cSAndroid Build Coastguard Worker len - auth_length, 1, header->sa, &ie_offset);
1972*03f9172cSAndroid Build Coastguard Worker if (res < 0) {
1973*03f9172cSAndroid Build Coastguard Worker /* Notify failure to the driver */
1974*03f9172cSAndroid Build Coastguard Worker sme_send_external_auth_status(
1975*03f9172cSAndroid Build Coastguard Worker wpa_s,
1976*03f9172cSAndroid Build Coastguard Worker res == -2 ?
1977*03f9172cSAndroid Build Coastguard Worker le_to_host16(header->u.auth.status_code) :
1978*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_UNSPECIFIED_FAILURE);
1979*03f9172cSAndroid Build Coastguard Worker return;
1980*03f9172cSAndroid Build Coastguard Worker }
1981*03f9172cSAndroid Build Coastguard Worker if (res != 1)
1982*03f9172cSAndroid Build Coastguard Worker return;
1983*03f9172cSAndroid Build Coastguard Worker
1984*03f9172cSAndroid Build Coastguard Worker if (sme_sae_set_pmk(wpa_s,
1985*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_ml_auth ?
1986*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_ap_mld_addr :
1987*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ext_auth_bssid) < 0)
1988*03f9172cSAndroid Build Coastguard Worker return;
1989*03f9172cSAndroid Build Coastguard Worker }
1990*03f9172cSAndroid Build Coastguard Worker }
1991*03f9172cSAndroid Build Coastguard Worker
1992*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
1993*03f9172cSAndroid Build Coastguard Worker
1994*03f9172cSAndroid Build Coastguard Worker
sme_event_auth(struct wpa_supplicant * wpa_s,union wpa_event_data * data)1995*03f9172cSAndroid Build Coastguard Worker void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
1996*03f9172cSAndroid Build Coastguard Worker {
1997*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid = wpa_s->current_ssid;
1998*03f9172cSAndroid Build Coastguard Worker int ie_offset = 0;
1999*03f9172cSAndroid Build Coastguard Worker
2000*03f9172cSAndroid Build Coastguard Worker if (ssid == NULL) {
2001*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
2002*03f9172cSAndroid Build Coastguard Worker "when network is not selected");
2003*03f9172cSAndroid Build Coastguard Worker return;
2004*03f9172cSAndroid Build Coastguard Worker }
2005*03f9172cSAndroid Build Coastguard Worker
2006*03f9172cSAndroid Build Coastguard Worker if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
2007*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
2008*03f9172cSAndroid Build Coastguard Worker "when not in authenticating state");
2009*03f9172cSAndroid Build Coastguard Worker return;
2010*03f9172cSAndroid Build Coastguard Worker }
2011*03f9172cSAndroid Build Coastguard Worker
2012*03f9172cSAndroid Build Coastguard Worker if (!ether_addr_equal(wpa_s->pending_bssid, data->auth.peer) &&
2013*03f9172cSAndroid Build Coastguard Worker !(wpa_s->valid_links &&
2014*03f9172cSAndroid Build Coastguard Worker ether_addr_equal(wpa_s->ap_mld_addr, data->auth.peer))) {
2015*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
2016*03f9172cSAndroid Build Coastguard Worker "unexpected peer " MACSTR,
2017*03f9172cSAndroid Build Coastguard Worker MAC2STR(data->auth.peer));
2018*03f9172cSAndroid Build Coastguard Worker return;
2019*03f9172cSAndroid Build Coastguard Worker }
2020*03f9172cSAndroid Build Coastguard Worker
2021*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
2022*03f9172cSAndroid Build Coastguard Worker " auth_type=%d auth_transaction=%d status_code=%d",
2023*03f9172cSAndroid Build Coastguard Worker MAC2STR(data->auth.peer), data->auth.auth_type,
2024*03f9172cSAndroid Build Coastguard Worker data->auth.auth_transaction, data->auth.status_code);
2025*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
2026*03f9172cSAndroid Build Coastguard Worker data->auth.ies, data->auth.ies_len);
2027*03f9172cSAndroid Build Coastguard Worker
2028*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
2029*03f9172cSAndroid Build Coastguard Worker
2030*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
2031*03f9172cSAndroid Build Coastguard Worker if (data->auth.auth_type == WLAN_AUTH_SAE) {
2032*03f9172cSAndroid Build Coastguard Worker const u8 *addr = wpa_s->pending_bssid;
2033*03f9172cSAndroid Build Coastguard Worker int res;
2034*03f9172cSAndroid Build Coastguard Worker
2035*03f9172cSAndroid Build Coastguard Worker res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
2036*03f9172cSAndroid Build Coastguard Worker data->auth.status_code, data->auth.ies,
2037*03f9172cSAndroid Build Coastguard Worker data->auth.ies_len, 0, data->auth.peer,
2038*03f9172cSAndroid Build Coastguard Worker &ie_offset);
2039*03f9172cSAndroid Build Coastguard Worker if (res < 0) {
2040*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2041*03f9172cSAndroid Build Coastguard Worker NULL);
2042*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2043*03f9172cSAndroid Build Coastguard Worker
2044*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sae_rejected_groups &&
2045*03f9172cSAndroid Build Coastguard Worker ssid->disabled_until.sec) {
2046*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
2047*03f9172cSAndroid Build Coastguard Worker "SME: Clear SAE state with rejected groups due to continuous failures");
2048*03f9172cSAndroid Build Coastguard Worker wpa_s_clear_sae_rejected(wpa_s);
2049*03f9172cSAndroid Build Coastguard Worker }
2050*03f9172cSAndroid Build Coastguard Worker }
2051*03f9172cSAndroid Build Coastguard Worker if (res != 1)
2052*03f9172cSAndroid Build Coastguard Worker return;
2053*03f9172cSAndroid Build Coastguard Worker
2054*03f9172cSAndroid Build Coastguard Worker if (wpa_s->valid_links)
2055*03f9172cSAndroid Build Coastguard Worker addr = wpa_s->ap_mld_addr;
2056*03f9172cSAndroid Build Coastguard Worker
2057*03f9172cSAndroid Build Coastguard Worker if (sme_sae_set_pmk(wpa_s, addr) < 0)
2058*03f9172cSAndroid Build Coastguard Worker return;
2059*03f9172cSAndroid Build Coastguard Worker }
2060*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
2061*03f9172cSAndroid Build Coastguard Worker
2062*03f9172cSAndroid Build Coastguard Worker if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
2063*03f9172cSAndroid Build Coastguard Worker char *ie_txt = NULL;
2064*03f9172cSAndroid Build Coastguard Worker
2065*03f9172cSAndroid Build Coastguard Worker if (data->auth.ies && data->auth.ies_len) {
2066*03f9172cSAndroid Build Coastguard Worker size_t buflen = 2 * data->auth.ies_len + 1;
2067*03f9172cSAndroid Build Coastguard Worker ie_txt = os_malloc(buflen);
2068*03f9172cSAndroid Build Coastguard Worker if (ie_txt) {
2069*03f9172cSAndroid Build Coastguard Worker wpa_snprintf_hex(ie_txt, buflen, data->auth.ies,
2070*03f9172cSAndroid Build Coastguard Worker data->auth.ies_len);
2071*03f9172cSAndroid Build Coastguard Worker }
2072*03f9172cSAndroid Build Coastguard Worker }
2073*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AUTH_REJECT MACSTR
2074*03f9172cSAndroid Build Coastguard Worker " auth_type=%u auth_transaction=%u status_code=%u%s%s",
2075*03f9172cSAndroid Build Coastguard Worker MAC2STR(data->auth.peer), data->auth.auth_type,
2076*03f9172cSAndroid Build Coastguard Worker data->auth.auth_transaction, data->auth.status_code,
2077*03f9172cSAndroid Build Coastguard Worker ie_txt ? " ie=" : "",
2078*03f9172cSAndroid Build Coastguard Worker ie_txt ? ie_txt : "");
2079*03f9172cSAndroid Build Coastguard Worker os_free(ie_txt);
2080*03f9172cSAndroid Build Coastguard Worker
2081*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FILS
2082*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS ||
2083*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.auth_alg == WPA_AUTH_ALG_FILS_SK_PFS)
2084*03f9172cSAndroid Build Coastguard Worker fils_connection_failure(wpa_s);
2085*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FILS */
2086*03f9172cSAndroid Build Coastguard Worker
2087*03f9172cSAndroid Build Coastguard Worker if (data->auth.status_code !=
2088*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
2089*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.auth_alg == data->auth.auth_type ||
2090*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
2091*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2092*03f9172cSAndroid Build Coastguard Worker NULL);
2093*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2094*03f9172cSAndroid Build Coastguard Worker return;
2095*03f9172cSAndroid Build Coastguard Worker }
2096*03f9172cSAndroid Build Coastguard Worker
2097*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
2098*03f9172cSAndroid Build Coastguard Worker
2099*03f9172cSAndroid Build Coastguard Worker switch (data->auth.auth_type) {
2100*03f9172cSAndroid Build Coastguard Worker case WLAN_AUTH_OPEN:
2101*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
2102*03f9172cSAndroid Build Coastguard Worker
2103*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
2104*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2105*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid);
2106*03f9172cSAndroid Build Coastguard Worker return;
2107*03f9172cSAndroid Build Coastguard Worker
2108*03f9172cSAndroid Build Coastguard Worker case WLAN_AUTH_SHARED_KEY:
2109*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
2110*03f9172cSAndroid Build Coastguard Worker
2111*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
2112*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
2113*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid);
2114*03f9172cSAndroid Build Coastguard Worker return;
2115*03f9172cSAndroid Build Coastguard Worker
2116*03f9172cSAndroid Build Coastguard Worker default:
2117*03f9172cSAndroid Build Coastguard Worker return;
2118*03f9172cSAndroid Build Coastguard Worker }
2119*03f9172cSAndroid Build Coastguard Worker }
2120*03f9172cSAndroid Build Coastguard Worker
2121*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R
2122*03f9172cSAndroid Build Coastguard Worker if (data->auth.auth_type == WLAN_AUTH_FT) {
2123*03f9172cSAndroid Build Coastguard Worker const u8 *ric_ies = NULL;
2124*03f9172cSAndroid Build Coastguard Worker size_t ric_ies_len = 0;
2125*03f9172cSAndroid Build Coastguard Worker
2126*03f9172cSAndroid Build Coastguard Worker if (wpa_s->ric_ies) {
2127*03f9172cSAndroid Build Coastguard Worker ric_ies = wpabuf_head(wpa_s->ric_ies);
2128*03f9172cSAndroid Build Coastguard Worker ric_ies_len = wpabuf_len(wpa_s->ric_ies);
2129*03f9172cSAndroid Build Coastguard Worker }
2130*03f9172cSAndroid Build Coastguard Worker if (wpa_ft_process_response(wpa_s->wpa, data->auth.ies,
2131*03f9172cSAndroid Build Coastguard Worker data->auth.ies_len, 0,
2132*03f9172cSAndroid Build Coastguard Worker data->auth.peer,
2133*03f9172cSAndroid Build Coastguard Worker ric_ies, ric_ies_len) < 0) {
2134*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
2135*03f9172cSAndroid Build Coastguard Worker "SME: FT Authentication response processing failed");
2136*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2137*03f9172cSAndroid Build Coastguard Worker MACSTR
2138*03f9172cSAndroid Build Coastguard Worker " reason=%d locally_generated=1",
2139*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->pending_bssid),
2140*03f9172cSAndroid Build Coastguard Worker WLAN_REASON_DEAUTH_LEAVING);
2141*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2142*03f9172cSAndroid Build Coastguard Worker NULL);
2143*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
2144*03f9172cSAndroid Build Coastguard Worker return;
2145*03f9172cSAndroid Build Coastguard Worker }
2146*03f9172cSAndroid Build Coastguard Worker }
2147*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R */
2148*03f9172cSAndroid Build Coastguard Worker
2149*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FILS
2150*03f9172cSAndroid Build Coastguard Worker if (data->auth.auth_type == WLAN_AUTH_FILS_SK ||
2151*03f9172cSAndroid Build Coastguard Worker data->auth.auth_type == WLAN_AUTH_FILS_SK_PFS) {
2152*03f9172cSAndroid Build Coastguard Worker u16 expect_auth_type;
2153*03f9172cSAndroid Build Coastguard Worker
2154*03f9172cSAndroid Build Coastguard Worker expect_auth_type = wpa_s->sme.auth_alg ==
2155*03f9172cSAndroid Build Coastguard Worker WPA_AUTH_ALG_FILS_SK_PFS ? WLAN_AUTH_FILS_SK_PFS :
2156*03f9172cSAndroid Build Coastguard Worker WLAN_AUTH_FILS_SK;
2157*03f9172cSAndroid Build Coastguard Worker if (data->auth.auth_type != expect_auth_type) {
2158*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
2159*03f9172cSAndroid Build Coastguard Worker "SME: FILS Authentication response used different auth alg (%u; expected %u)",
2160*03f9172cSAndroid Build Coastguard Worker data->auth.auth_type, expect_auth_type);
2161*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2162*03f9172cSAndroid Build Coastguard Worker MACSTR
2163*03f9172cSAndroid Build Coastguard Worker " reason=%d locally_generated=1",
2164*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->pending_bssid),
2165*03f9172cSAndroid Build Coastguard Worker WLAN_REASON_DEAUTH_LEAVING);
2166*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2167*03f9172cSAndroid Build Coastguard Worker NULL);
2168*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
2169*03f9172cSAndroid Build Coastguard Worker return;
2170*03f9172cSAndroid Build Coastguard Worker }
2171*03f9172cSAndroid Build Coastguard Worker
2172*03f9172cSAndroid Build Coastguard Worker if (fils_process_auth(wpa_s->wpa, wpa_s->pending_bssid,
2173*03f9172cSAndroid Build Coastguard Worker data->auth.ies, data->auth.ies_len) < 0) {
2174*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
2175*03f9172cSAndroid Build Coastguard Worker "SME: FILS Authentication response processing failed");
2176*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid="
2177*03f9172cSAndroid Build Coastguard Worker MACSTR
2178*03f9172cSAndroid Build Coastguard Worker " reason=%d locally_generated=1",
2179*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->pending_bssid),
2180*03f9172cSAndroid Build Coastguard Worker WLAN_REASON_DEAUTH_LEAVING);
2181*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2182*03f9172cSAndroid Build Coastguard Worker NULL);
2183*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
2184*03f9172cSAndroid Build Coastguard Worker return;
2185*03f9172cSAndroid Build Coastguard Worker }
2186*03f9172cSAndroid Build Coastguard Worker }
2187*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FILS */
2188*03f9172cSAndroid Build Coastguard Worker
2189*03f9172cSAndroid Build Coastguard Worker /* TODO: Support additional auth_type values as well */
2190*03f9172cSAndroid Build Coastguard Worker if ((data->auth.auth_type == WLAN_AUTH_OPEN ||
2191*03f9172cSAndroid Build Coastguard Worker data->auth.auth_type == WLAN_AUTH_SAE) &&
2192*03f9172cSAndroid Build Coastguard Worker wpas_sme_ml_auth(wpa_s, data, ie_offset) < 0) {
2193*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
2194*03f9172cSAndroid Build Coastguard Worker "MLD: Failed to parse ML Authentication frame");
2195*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR
2196*03f9172cSAndroid Build Coastguard Worker " reason=%d locally_generated=1",
2197*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->pending_bssid),
2198*03f9172cSAndroid Build Coastguard Worker WLAN_REASON_DEAUTH_LEAVING);
2199*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
2200*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_deauthenticate(wpa_s,
2201*03f9172cSAndroid Build Coastguard Worker WLAN_REASON_DEAUTH_LEAVING);
2202*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
2203*03f9172cSAndroid Build Coastguard Worker "MLD: Authentication - clearing MLD state");
2204*03f9172cSAndroid Build Coastguard Worker wpas_reset_mlo_info(wpa_s);
2205*03f9172cSAndroid Build Coastguard Worker return;
2206*03f9172cSAndroid Build Coastguard Worker }
2207*03f9172cSAndroid Build Coastguard Worker
2208*03f9172cSAndroid Build Coastguard Worker sme_associate(wpa_s, ssid->mode, data->auth.peer,
2209*03f9172cSAndroid Build Coastguard Worker data->auth.auth_type);
2210*03f9172cSAndroid Build Coastguard Worker }
2211*03f9172cSAndroid Build Coastguard Worker
2212*03f9172cSAndroid Build Coastguard Worker
2213*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R
remove_ie(u8 * buf,size_t * len,u8 eid)2214*03f9172cSAndroid Build Coastguard Worker static void remove_ie(u8 *buf, size_t *len, u8 eid)
2215*03f9172cSAndroid Build Coastguard Worker {
2216*03f9172cSAndroid Build Coastguard Worker u8 *pos, *next, *end;
2217*03f9172cSAndroid Build Coastguard Worker
2218*03f9172cSAndroid Build Coastguard Worker pos = (u8 *) get_ie(buf, *len, eid);
2219*03f9172cSAndroid Build Coastguard Worker if (pos) {
2220*03f9172cSAndroid Build Coastguard Worker next = pos + 2 + pos[1];
2221*03f9172cSAndroid Build Coastguard Worker end = buf + *len;
2222*03f9172cSAndroid Build Coastguard Worker *len -= 2 + pos[1];
2223*03f9172cSAndroid Build Coastguard Worker os_memmove(pos, next, end - next);
2224*03f9172cSAndroid Build Coastguard Worker }
2225*03f9172cSAndroid Build Coastguard Worker }
2226*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R */
2227*03f9172cSAndroid Build Coastguard Worker
2228*03f9172cSAndroid Build Coastguard Worker
sme_associate(struct wpa_supplicant * wpa_s,enum wpas_mode mode,const u8 * bssid,u16 auth_type)2229*03f9172cSAndroid Build Coastguard Worker void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
2230*03f9172cSAndroid Build Coastguard Worker const u8 *bssid, u16 auth_type)
2231*03f9172cSAndroid Build Coastguard Worker {
2232*03f9172cSAndroid Build Coastguard Worker struct wpa_driver_associate_params params;
2233*03f9172cSAndroid Build Coastguard Worker struct ieee802_11_elems elems;
2234*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid = wpa_s->current_ssid;
2235*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FILS
2236*03f9172cSAndroid Build Coastguard Worker u8 nonces[2 * FILS_NONCE_LEN];
2237*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FILS */
2238*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_HT_OVERRIDES
2239*03f9172cSAndroid Build Coastguard Worker struct ieee80211_ht_capabilities htcaps;
2240*03f9172cSAndroid Build Coastguard Worker struct ieee80211_ht_capabilities htcaps_mask;
2241*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_HT_OVERRIDES */
2242*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_VHT_OVERRIDES
2243*03f9172cSAndroid Build Coastguard Worker struct ieee80211_vht_capabilities vhtcaps;
2244*03f9172cSAndroid Build Coastguard Worker struct ieee80211_vht_capabilities vhtcaps_mask;
2245*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_VHT_OVERRIDES */
2246*03f9172cSAndroid Build Coastguard Worker
2247*03f9172cSAndroid Build Coastguard Worker os_memset(¶ms, 0, sizeof(params));
2248*03f9172cSAndroid Build Coastguard Worker
2249*03f9172cSAndroid Build Coastguard Worker /* Save auth type, in case we need to retry after comeback timer. */
2250*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_auth_type = auth_type;
2251*03f9172cSAndroid Build Coastguard Worker
2252*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_FILS
2253*03f9172cSAndroid Build Coastguard Worker if (auth_type == WLAN_AUTH_FILS_SK ||
2254*03f9172cSAndroid Build Coastguard Worker auth_type == WLAN_AUTH_FILS_SK_PFS) {
2255*03f9172cSAndroid Build Coastguard Worker struct wpabuf *buf;
2256*03f9172cSAndroid Build Coastguard Worker const u8 *snonce, *anonce;
2257*03f9172cSAndroid Build Coastguard Worker const unsigned int max_hlp = 20;
2258*03f9172cSAndroid Build Coastguard Worker struct wpabuf *hlp[max_hlp];
2259*03f9172cSAndroid Build Coastguard Worker unsigned int i, num_hlp = 0;
2260*03f9172cSAndroid Build Coastguard Worker struct fils_hlp_req *req;
2261*03f9172cSAndroid Build Coastguard Worker
2262*03f9172cSAndroid Build Coastguard Worker dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
2263*03f9172cSAndroid Build Coastguard Worker list) {
2264*03f9172cSAndroid Build Coastguard Worker hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
2265*03f9172cSAndroid Build Coastguard Worker wpabuf_len(req->pkt));
2266*03f9172cSAndroid Build Coastguard Worker if (!hlp[num_hlp])
2267*03f9172cSAndroid Build Coastguard Worker break;
2268*03f9172cSAndroid Build Coastguard Worker wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
2269*03f9172cSAndroid Build Coastguard Worker wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
2270*03f9172cSAndroid Build Coastguard Worker ETH_ALEN);
2271*03f9172cSAndroid Build Coastguard Worker wpabuf_put_data(hlp[num_hlp],
2272*03f9172cSAndroid Build Coastguard Worker "\xaa\xaa\x03\x00\x00\x00", 6);
2273*03f9172cSAndroid Build Coastguard Worker wpabuf_put_buf(hlp[num_hlp], req->pkt);
2274*03f9172cSAndroid Build Coastguard Worker num_hlp++;
2275*03f9172cSAndroid Build Coastguard Worker if (num_hlp >= max_hlp)
2276*03f9172cSAndroid Build Coastguard Worker break;
2277*03f9172cSAndroid Build Coastguard Worker }
2278*03f9172cSAndroid Build Coastguard Worker
2279*03f9172cSAndroid Build Coastguard Worker buf = fils_build_assoc_req(wpa_s->wpa, ¶ms.fils_kek,
2280*03f9172cSAndroid Build Coastguard Worker ¶ms.fils_kek_len, &snonce,
2281*03f9172cSAndroid Build Coastguard Worker &anonce,
2282*03f9172cSAndroid Build Coastguard Worker (const struct wpabuf **) hlp,
2283*03f9172cSAndroid Build Coastguard Worker num_hlp);
2284*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < num_hlp; i++)
2285*03f9172cSAndroid Build Coastguard Worker wpabuf_free(hlp[i]);
2286*03f9172cSAndroid Build Coastguard Worker if (!buf)
2287*03f9172cSAndroid Build Coastguard Worker return;
2288*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG, "FILS: assoc_req before FILS elements",
2289*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
2290*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len);
2291*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R
2292*03f9172cSAndroid Build Coastguard Worker if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
2293*03f9172cSAndroid Build Coastguard Worker /* Remove RSNE and MDE to allow them to be overridden
2294*03f9172cSAndroid Build Coastguard Worker * with FILS+FT specific values from
2295*03f9172cSAndroid Build Coastguard Worker * fils_build_assoc_req(). */
2296*03f9172cSAndroid Build Coastguard Worker remove_ie(wpa_s->sme.assoc_req_ie,
2297*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
2298*03f9172cSAndroid Build Coastguard Worker WLAN_EID_RSN);
2299*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG,
2300*03f9172cSAndroid Build Coastguard Worker "FILS: assoc_req after RSNE removal",
2301*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
2302*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len);
2303*03f9172cSAndroid Build Coastguard Worker remove_ie(wpa_s->sme.assoc_req_ie,
2304*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
2305*03f9172cSAndroid Build Coastguard Worker WLAN_EID_MOBILITY_DOMAIN);
2306*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG,
2307*03f9172cSAndroid Build Coastguard Worker "FILS: assoc_req after MDE removal",
2308*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
2309*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len);
2310*03f9172cSAndroid Build Coastguard Worker }
2311*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R */
2312*03f9172cSAndroid Build Coastguard Worker /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
2313*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
2314*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie)) {
2315*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_ERROR,
2316*03f9172cSAndroid Build Coastguard Worker "FILS: Not enough buffer room for own AssocReq elements");
2317*03f9172cSAndroid Build Coastguard Worker wpabuf_free(buf);
2318*03f9172cSAndroid Build Coastguard Worker return;
2319*03f9172cSAndroid Build Coastguard Worker }
2320*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2321*03f9172cSAndroid Build Coastguard Worker wpabuf_head(buf), wpabuf_len(buf));
2322*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
2323*03f9172cSAndroid Build Coastguard Worker wpabuf_free(buf);
2324*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG, "FILS: assoc_req after FILS elements",
2325*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
2326*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len);
2327*03f9172cSAndroid Build Coastguard Worker
2328*03f9172cSAndroid Build Coastguard Worker os_memcpy(nonces, snonce, FILS_NONCE_LEN);
2329*03f9172cSAndroid Build Coastguard Worker os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
2330*03f9172cSAndroid Build Coastguard Worker params.fils_nonces = nonces;
2331*03f9172cSAndroid Build Coastguard Worker params.fils_nonces_len = sizeof(nonces);
2332*03f9172cSAndroid Build Coastguard Worker }
2333*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_FILS */
2334*03f9172cSAndroid Build Coastguard Worker
2335*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_OWE
2336*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
2337*03f9172cSAndroid Build Coastguard Worker if (get_ie_ext(wpa_s->sme.assoc_req_ie, wpa_s->sme.assoc_req_ie_len,
2338*03f9172cSAndroid Build Coastguard Worker WLAN_EID_EXT_OWE_DH_PARAM)) {
2339*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
2340*03f9172cSAndroid Build Coastguard Worker } else
2341*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
2342*03f9172cSAndroid Build Coastguard Worker if (auth_type == WLAN_AUTH_OPEN &&
2343*03f9172cSAndroid Build Coastguard Worker wpa_s->key_mgmt == WPA_KEY_MGMT_OWE) {
2344*03f9172cSAndroid Build Coastguard Worker struct wpabuf *owe_ie;
2345*03f9172cSAndroid Build Coastguard Worker u16 group;
2346*03f9172cSAndroid Build Coastguard Worker
2347*03f9172cSAndroid Build Coastguard Worker if (ssid && ssid->owe_group) {
2348*03f9172cSAndroid Build Coastguard Worker group = ssid->owe_group;
2349*03f9172cSAndroid Build Coastguard Worker } else if (wpa_s->assoc_status_code ==
2350*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
2351*03f9172cSAndroid Build Coastguard Worker if (wpa_s->last_owe_group == 19)
2352*03f9172cSAndroid Build Coastguard Worker group = 20;
2353*03f9172cSAndroid Build Coastguard Worker else if (wpa_s->last_owe_group == 20)
2354*03f9172cSAndroid Build Coastguard Worker group = 21;
2355*03f9172cSAndroid Build Coastguard Worker else
2356*03f9172cSAndroid Build Coastguard Worker group = OWE_DH_GROUP;
2357*03f9172cSAndroid Build Coastguard Worker } else {
2358*03f9172cSAndroid Build Coastguard Worker group = OWE_DH_GROUP;
2359*03f9172cSAndroid Build Coastguard Worker }
2360*03f9172cSAndroid Build Coastguard Worker
2361*03f9172cSAndroid Build Coastguard Worker wpa_s->last_owe_group = group;
2362*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
2363*03f9172cSAndroid Build Coastguard Worker owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
2364*03f9172cSAndroid Build Coastguard Worker if (!owe_ie) {
2365*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_ERROR,
2366*03f9172cSAndroid Build Coastguard Worker "OWE: Failed to build IE for Association Request frame");
2367*03f9172cSAndroid Build Coastguard Worker return;
2368*03f9172cSAndroid Build Coastguard Worker }
2369*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(owe_ie) >
2370*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie)) {
2371*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_ERROR,
2372*03f9172cSAndroid Build Coastguard Worker "OWE: Not enough buffer room for own Association Request frame elements");
2373*03f9172cSAndroid Build Coastguard Worker wpabuf_free(owe_ie);
2374*03f9172cSAndroid Build Coastguard Worker return;
2375*03f9172cSAndroid Build Coastguard Worker }
2376*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2377*03f9172cSAndroid Build Coastguard Worker wpabuf_head(owe_ie), wpabuf_len(owe_ie));
2378*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += wpabuf_len(owe_ie);
2379*03f9172cSAndroid Build Coastguard Worker wpabuf_free(owe_ie);
2380*03f9172cSAndroid Build Coastguard Worker }
2381*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_OWE */
2382*03f9172cSAndroid Build Coastguard Worker
2383*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP2
2384*03f9172cSAndroid Build Coastguard Worker if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid &&
2385*03f9172cSAndroid Build Coastguard Worker ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 &&
2386*03f9172cSAndroid Build Coastguard Worker !ssid->dpp_pfs_fallback) {
2387*03f9172cSAndroid Build Coastguard Worker struct rsn_pmksa_cache_entry *pmksa;
2388*03f9172cSAndroid Build Coastguard Worker
2389*03f9172cSAndroid Build Coastguard Worker pmksa = pmksa_cache_get_current(wpa_s->wpa);
2390*03f9172cSAndroid Build Coastguard Worker if (!pmksa || !pmksa->dpp_pfs)
2391*03f9172cSAndroid Build Coastguard Worker goto pfs_fail;
2392*03f9172cSAndroid Build Coastguard Worker
2393*03f9172cSAndroid Build Coastguard Worker dpp_pfs_free(wpa_s->dpp_pfs);
2394*03f9172cSAndroid Build Coastguard Worker wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey,
2395*03f9172cSAndroid Build Coastguard Worker ssid->dpp_netaccesskey_len);
2396*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->dpp_pfs) {
2397*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "DPP: Could not initialize PFS");
2398*03f9172cSAndroid Build Coastguard Worker /* Try to continue without PFS */
2399*03f9172cSAndroid Build Coastguard Worker goto pfs_fail;
2400*03f9172cSAndroid Build Coastguard Worker }
2401*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.assoc_req_ie_len +
2402*03f9172cSAndroid Build Coastguard Worker wpabuf_len(wpa_s->dpp_pfs->ie) >
2403*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie)) {
2404*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_ERROR,
2405*03f9172cSAndroid Build Coastguard Worker "DPP: Not enough buffer room for own Association Request frame elements");
2406*03f9172cSAndroid Build Coastguard Worker dpp_pfs_free(wpa_s->dpp_pfs);
2407*03f9172cSAndroid Build Coastguard Worker wpa_s->dpp_pfs = NULL;
2408*03f9172cSAndroid Build Coastguard Worker goto pfs_fail;
2409*03f9172cSAndroid Build Coastguard Worker }
2410*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2411*03f9172cSAndroid Build Coastguard Worker wpabuf_head(wpa_s->dpp_pfs->ie),
2412*03f9172cSAndroid Build Coastguard Worker wpabuf_len(wpa_s->dpp_pfs->ie));
2413*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += wpabuf_len(wpa_s->dpp_pfs->ie);
2414*03f9172cSAndroid Build Coastguard Worker }
2415*03f9172cSAndroid Build Coastguard Worker pfs_fail:
2416*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP2 */
2417*03f9172cSAndroid Build Coastguard Worker
2418*03f9172cSAndroid Build Coastguard Worker #ifndef CONFIG_NO_ROBUST_AV
2419*03f9172cSAndroid Build Coastguard Worker wpa_s->mscs_setup_done = false;
2420*03f9172cSAndroid Build Coastguard Worker if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
2421*03f9172cSAndroid Build Coastguard Worker wpa_s->robust_av.valid_config) {
2422*03f9172cSAndroid Build Coastguard Worker struct wpabuf *mscs_ie;
2423*03f9172cSAndroid Build Coastguard Worker size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len;
2424*03f9172cSAndroid Build Coastguard Worker
2425*03f9172cSAndroid Build Coastguard Worker buf_len = 3 + /* MSCS descriptor IE header */
2426*03f9172cSAndroid Build Coastguard Worker 1 + /* Request type */
2427*03f9172cSAndroid Build Coastguard Worker 2 + /* User priority control */
2428*03f9172cSAndroid Build Coastguard Worker 4 + /* Stream timeout */
2429*03f9172cSAndroid Build Coastguard Worker 3 + /* TCLAS Mask IE header */
2430*03f9172cSAndroid Build Coastguard Worker wpa_s->robust_av.frame_classifier_len;
2431*03f9172cSAndroid Build Coastguard Worker mscs_ie = wpabuf_alloc(buf_len);
2432*03f9172cSAndroid Build Coastguard Worker if (!mscs_ie) {
2433*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO,
2434*03f9172cSAndroid Build Coastguard Worker "MSCS: Failed to allocate MSCS IE");
2435*03f9172cSAndroid Build Coastguard Worker goto mscs_fail;
2436*03f9172cSAndroid Build Coastguard Worker }
2437*03f9172cSAndroid Build Coastguard Worker
2438*03f9172cSAndroid Build Coastguard Worker wpa_ie_len = &wpa_s->sme.assoc_req_ie_len;
2439*03f9172cSAndroid Build Coastguard Worker max_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
2440*03f9172cSAndroid Build Coastguard Worker wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie);
2441*03f9172cSAndroid Build Coastguard Worker if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) {
2442*03f9172cSAndroid Build Coastguard Worker wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie);
2443*03f9172cSAndroid Build Coastguard Worker mscs_ie_len = wpabuf_len(mscs_ie);
2444*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len,
2445*03f9172cSAndroid Build Coastguard Worker wpabuf_head(mscs_ie), mscs_ie_len);
2446*03f9172cSAndroid Build Coastguard Worker *wpa_ie_len += mscs_ie_len;
2447*03f9172cSAndroid Build Coastguard Worker }
2448*03f9172cSAndroid Build Coastguard Worker
2449*03f9172cSAndroid Build Coastguard Worker wpabuf_free(mscs_ie);
2450*03f9172cSAndroid Build Coastguard Worker }
2451*03f9172cSAndroid Build Coastguard Worker mscs_fail:
2452*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_NO_ROBUST_AV */
2453*03f9172cSAndroid Build Coastguard Worker
2454*03f9172cSAndroid Build Coastguard Worker if (ssid && ssid->multi_ap_backhaul_sta) {
2455*03f9172cSAndroid Build Coastguard Worker size_t multi_ap_ie_len;
2456*03f9172cSAndroid Build Coastguard Worker struct multi_ap_params multi_ap = { 0 };
2457*03f9172cSAndroid Build Coastguard Worker
2458*03f9172cSAndroid Build Coastguard Worker multi_ap.capability = MULTI_AP_BACKHAUL_STA;
2459*03f9172cSAndroid Build Coastguard Worker multi_ap.profile = ssid->multi_ap_profile;
2460*03f9172cSAndroid Build Coastguard Worker
2461*03f9172cSAndroid Build Coastguard Worker multi_ap_ie_len = add_multi_ap_ie(
2462*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
2463*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie) -
2464*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len,
2465*03f9172cSAndroid Build Coastguard Worker &multi_ap);
2466*03f9172cSAndroid Build Coastguard Worker if (multi_ap_ie_len == 0) {
2467*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_ERROR,
2468*03f9172cSAndroid Build Coastguard Worker "Multi-AP: Failed to build Multi-AP IE");
2469*03f9172cSAndroid Build Coastguard Worker return;
2470*03f9172cSAndroid Build Coastguard Worker }
2471*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += multi_ap_ie_len;
2472*03f9172cSAndroid Build Coastguard Worker }
2473*03f9172cSAndroid Build Coastguard Worker
2474*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE_SUPPORT,
2475*03f9172cSAndroid Build Coastguard Worker wpas_rsn_overriding(wpa_s));
2476*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
2477*03f9172cSAndroid Build Coastguard Worker RSN_OVERRIDE_NOT_USED);
2478*03f9172cSAndroid Build Coastguard Worker if (wpas_rsn_overriding(wpa_s) &&
2479*03f9172cSAndroid Build Coastguard Worker wpas_ap_supports_rsn_overriding(wpa_s, wpa_s->current_bss) &&
2480*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len + 2 + 4 <=
2481*03f9172cSAndroid Build Coastguard Worker sizeof(wpa_s->sme.assoc_req_ie)) {
2482*03f9172cSAndroid Build Coastguard Worker u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
2483*03f9172cSAndroid Build Coastguard Worker const u8 *ie;
2484*03f9172cSAndroid Build Coastguard Worker enum rsn_selection_variant variant = RSN_SELECTION_RSNE;
2485*03f9172cSAndroid Build Coastguard Worker
2486*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_OVERRIDE,
2487*03f9172cSAndroid Build Coastguard Worker RSN_OVERRIDE_RSNE);
2488*03f9172cSAndroid Build Coastguard Worker ie = wpa_bss_get_rsne(wpa_s, wpa_s->current_bss, ssid,
2489*03f9172cSAndroid Build Coastguard Worker wpa_s->valid_links);
2490*03f9172cSAndroid Build Coastguard Worker if (ie && ie[0] == WLAN_EID_VENDOR_SPECIFIC && ie[1] >= 4) {
2491*03f9172cSAndroid Build Coastguard Worker u32 type;
2492*03f9172cSAndroid Build Coastguard Worker
2493*03f9172cSAndroid Build Coastguard Worker type = WPA_GET_BE32(&ie[2]);
2494*03f9172cSAndroid Build Coastguard Worker if (type == RSNE_OVERRIDE_IE_VENDOR_TYPE) {
2495*03f9172cSAndroid Build Coastguard Worker variant = RSN_SELECTION_RSNE_OVERRIDE;
2496*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_param(wpa_s->wpa,
2497*03f9172cSAndroid Build Coastguard Worker WPA_PARAM_RSN_OVERRIDE,
2498*03f9172cSAndroid Build Coastguard Worker RSN_OVERRIDE_RSNE_OVERRIDE);
2499*03f9172cSAndroid Build Coastguard Worker } else if (type == RSNE_OVERRIDE_2_IE_VENDOR_TYPE) {
2500*03f9172cSAndroid Build Coastguard Worker variant = RSN_SELECTION_RSNE_OVERRIDE_2;
2501*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_param(wpa_s->wpa,
2502*03f9172cSAndroid Build Coastguard Worker WPA_PARAM_RSN_OVERRIDE,
2503*03f9172cSAndroid Build Coastguard Worker RSN_OVERRIDE_RSNE_OVERRIDE_2);
2504*03f9172cSAndroid Build Coastguard Worker }
2505*03f9172cSAndroid Build Coastguard Worker }
2506*03f9172cSAndroid Build Coastguard Worker
2507*03f9172cSAndroid Build Coastguard Worker /* Indicate which RSNE variant was used */
2508*03f9172cSAndroid Build Coastguard Worker *pos++ = WLAN_EID_VENDOR_SPECIFIC;
2509*03f9172cSAndroid Build Coastguard Worker *pos++ = 4 + 1;
2510*03f9172cSAndroid Build Coastguard Worker WPA_PUT_BE32(pos, RSN_SELECTION_IE_VENDOR_TYPE);
2511*03f9172cSAndroid Build Coastguard Worker pos += 4;
2512*03f9172cSAndroid Build Coastguard Worker *pos = variant;
2513*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += 2 + 4 + 1;
2514*03f9172cSAndroid Build Coastguard Worker }
2515*03f9172cSAndroid Build Coastguard Worker
2516*03f9172cSAndroid Build Coastguard Worker params.bssid = bssid;
2517*03f9172cSAndroid Build Coastguard Worker params.ssid = wpa_s->sme.ssid;
2518*03f9172cSAndroid Build Coastguard Worker params.ssid_len = wpa_s->sme.ssid_len;
2519*03f9172cSAndroid Build Coastguard Worker params.freq.freq = wpa_s->sme.freq;
2520*03f9172cSAndroid Build Coastguard Worker params.bg_scan_period = ssid ? ssid->bg_scan_period : -1;
2521*03f9172cSAndroid Build Coastguard Worker params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
2522*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie : NULL;
2523*03f9172cSAndroid Build Coastguard Worker params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
2524*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
2525*03f9172cSAndroid Build Coastguard Worker params.wpa_ie, params.wpa_ie_len);
2526*03f9172cSAndroid Build Coastguard Worker params.pairwise_suite = wpa_s->pairwise_cipher;
2527*03f9172cSAndroid Build Coastguard Worker params.group_suite = wpa_s->group_cipher;
2528*03f9172cSAndroid Build Coastguard Worker params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
2529*03f9172cSAndroid Build Coastguard Worker params.key_mgmt_suite = wpa_s->key_mgmt;
2530*03f9172cSAndroid Build Coastguard Worker params.wpa_proto = wpa_s->wpa_proto;
2531*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_HT_OVERRIDES
2532*03f9172cSAndroid Build Coastguard Worker os_memset(&htcaps, 0, sizeof(htcaps));
2533*03f9172cSAndroid Build Coastguard Worker os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
2534*03f9172cSAndroid Build Coastguard Worker params.htcaps = (u8 *) &htcaps;
2535*03f9172cSAndroid Build Coastguard Worker params.htcaps_mask = (u8 *) &htcaps_mask;
2536*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms);
2537*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_HT_OVERRIDES */
2538*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_VHT_OVERRIDES
2539*03f9172cSAndroid Build Coastguard Worker os_memset(&vhtcaps, 0, sizeof(vhtcaps));
2540*03f9172cSAndroid Build Coastguard Worker os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
2541*03f9172cSAndroid Build Coastguard Worker params.vhtcaps = &vhtcaps;
2542*03f9172cSAndroid Build Coastguard Worker params.vhtcaps_mask = &vhtcaps_mask;
2543*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_apply_vht_overrides(wpa_s, ssid, ¶ms);
2544*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_VHT_OVERRIDES */
2545*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_HE_OVERRIDES
2546*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_apply_he_overrides(wpa_s, ssid, ¶ms);
2547*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_HE_OVERRIDES */
2548*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_apply_eht_overrides(wpa_s, ssid, ¶ms);
2549*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R
2550*03f9172cSAndroid Build Coastguard Worker if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
2551*03f9172cSAndroid Build Coastguard Worker get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
2552*03f9172cSAndroid Build Coastguard Worker WLAN_EID_RIC_DATA)) {
2553*03f9172cSAndroid Build Coastguard Worker /* There seems to be a pretty inconvenient bug in the Linux
2554*03f9172cSAndroid Build Coastguard Worker * kernel IE splitting functionality when RIC is used. For now,
2555*03f9172cSAndroid Build Coastguard Worker * skip correct behavior in IE construction here (i.e., drop the
2556*03f9172cSAndroid Build Coastguard Worker * additional non-FT-specific IEs) to avoid kernel issues. This
2557*03f9172cSAndroid Build Coastguard Worker * is fine since RIC is used only for testing purposes in the
2558*03f9172cSAndroid Build Coastguard Worker * current implementation. */
2559*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO,
2560*03f9172cSAndroid Build Coastguard Worker "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
2561*03f9172cSAndroid Build Coastguard Worker params.wpa_ie = wpa_s->sme.ft_ies;
2562*03f9172cSAndroid Build Coastguard Worker params.wpa_ie_len = wpa_s->sme.ft_ies_len;
2563*03f9172cSAndroid Build Coastguard Worker } else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
2564*03f9172cSAndroid Build Coastguard Worker const u8 *rm_en, *pos, *end;
2565*03f9172cSAndroid Build Coastguard Worker size_t rm_en_len = 0;
2566*03f9172cSAndroid Build Coastguard Worker u8 *rm_en_dup = NULL, *wpos;
2567*03f9172cSAndroid Build Coastguard Worker
2568*03f9172cSAndroid Build Coastguard Worker /* Remove RSNE, MDE, FTE to allow them to be overridden with
2569*03f9172cSAndroid Build Coastguard Worker * FT specific values */
2570*03f9172cSAndroid Build Coastguard Worker remove_ie(wpa_s->sme.assoc_req_ie,
2571*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
2572*03f9172cSAndroid Build Coastguard Worker WLAN_EID_RSN);
2573*03f9172cSAndroid Build Coastguard Worker remove_ie(wpa_s->sme.assoc_req_ie,
2574*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
2575*03f9172cSAndroid Build Coastguard Worker WLAN_EID_MOBILITY_DOMAIN);
2576*03f9172cSAndroid Build Coastguard Worker remove_ie(wpa_s->sme.assoc_req_ie,
2577*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
2578*03f9172cSAndroid Build Coastguard Worker WLAN_EID_FAST_BSS_TRANSITION);
2579*03f9172cSAndroid Build Coastguard Worker rm_en = get_ie(wpa_s->sme.assoc_req_ie,
2580*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len,
2581*03f9172cSAndroid Build Coastguard Worker WLAN_EID_RRM_ENABLED_CAPABILITIES);
2582*03f9172cSAndroid Build Coastguard Worker if (rm_en) {
2583*03f9172cSAndroid Build Coastguard Worker /* Need to remove RM Enabled Capabilities element as
2584*03f9172cSAndroid Build Coastguard Worker * well temporarily, so that it can be placed between
2585*03f9172cSAndroid Build Coastguard Worker * RSNE and MDE. */
2586*03f9172cSAndroid Build Coastguard Worker rm_en_len = 2 + rm_en[1];
2587*03f9172cSAndroid Build Coastguard Worker rm_en_dup = os_memdup(rm_en, rm_en_len);
2588*03f9172cSAndroid Build Coastguard Worker remove_ie(wpa_s->sme.assoc_req_ie,
2589*03f9172cSAndroid Build Coastguard Worker &wpa_s->sme.assoc_req_ie_len,
2590*03f9172cSAndroid Build Coastguard Worker WLAN_EID_RRM_ENABLED_CAPABILITIES);
2591*03f9172cSAndroid Build Coastguard Worker }
2592*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG,
2593*03f9172cSAndroid Build Coastguard Worker "SME: Association Request IEs after FT IE removal",
2594*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
2595*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len);
2596*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
2597*03f9172cSAndroid Build Coastguard Worker rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
2598*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_ERROR,
2599*03f9172cSAndroid Build Coastguard Worker "SME: Not enough buffer room for FT IEs in Association Request frame");
2600*03f9172cSAndroid Build Coastguard Worker os_free(rm_en_dup);
2601*03f9172cSAndroid Build Coastguard Worker return;
2602*03f9172cSAndroid Build Coastguard Worker }
2603*03f9172cSAndroid Build Coastguard Worker
2604*03f9172cSAndroid Build Coastguard Worker os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
2605*03f9172cSAndroid Build Coastguard Worker rm_en_len,
2606*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie,
2607*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len);
2608*03f9172cSAndroid Build Coastguard Worker pos = wpa_s->sme.ft_ies;
2609*03f9172cSAndroid Build Coastguard Worker end = pos + wpa_s->sme.ft_ies_len;
2610*03f9172cSAndroid Build Coastguard Worker wpos = wpa_s->sme.assoc_req_ie;
2611*03f9172cSAndroid Build Coastguard Worker if (*pos == WLAN_EID_RSN) {
2612*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpos, pos, 2 + pos[1]);
2613*03f9172cSAndroid Build Coastguard Worker wpos += 2 + pos[1];
2614*03f9172cSAndroid Build Coastguard Worker pos += 2 + pos[1];
2615*03f9172cSAndroid Build Coastguard Worker }
2616*03f9172cSAndroid Build Coastguard Worker if (rm_en_dup) {
2617*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpos, rm_en_dup, rm_en_len);
2618*03f9172cSAndroid Build Coastguard Worker wpos += rm_en_len;
2619*03f9172cSAndroid Build Coastguard Worker os_free(rm_en_dup);
2620*03f9172cSAndroid Build Coastguard Worker }
2621*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpos, pos, end - pos);
2622*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
2623*03f9172cSAndroid Build Coastguard Worker rm_en_len;
2624*03f9172cSAndroid Build Coastguard Worker params.wpa_ie = wpa_s->sme.assoc_req_ie;
2625*03f9172cSAndroid Build Coastguard Worker params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
2626*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG,
2627*03f9172cSAndroid Build Coastguard Worker "SME: Association Request IEs after FT override",
2628*03f9172cSAndroid Build Coastguard Worker params.wpa_ie, params.wpa_ie_len);
2629*03f9172cSAndroid Build Coastguard Worker }
2630*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R */
2631*03f9172cSAndroid Build Coastguard Worker params.mode = mode;
2632*03f9172cSAndroid Build Coastguard Worker params.mgmt_frame_protection = wpa_s->sme.mfp;
2633*03f9172cSAndroid Build Coastguard Worker params.rrm_used = wpa_s->rrm.rrm_used;
2634*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.prev_bssid_set)
2635*03f9172cSAndroid Build Coastguard Worker params.prev_bssid = wpa_s->sme.prev_bssid;
2636*03f9172cSAndroid Build Coastguard Worker
2637*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
2638*03f9172cSAndroid Build Coastguard Worker " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
2639*03f9172cSAndroid Build Coastguard Worker params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
2640*03f9172cSAndroid Build Coastguard Worker params.freq.freq);
2641*03f9172cSAndroid Build Coastguard Worker
2642*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
2643*03f9172cSAndroid Build Coastguard Worker
2644*03f9172cSAndroid Build Coastguard Worker if (params.wpa_ie == NULL ||
2645*03f9172cSAndroid Build Coastguard Worker ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
2646*03f9172cSAndroid Build Coastguard Worker < 0) {
2647*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
2648*03f9172cSAndroid Build Coastguard Worker os_memset(&elems, 0, sizeof(elems));
2649*03f9172cSAndroid Build Coastguard Worker }
2650*03f9172cSAndroid Build Coastguard Worker if (elems.rsn_ie) {
2651*03f9172cSAndroid Build Coastguard Worker params.wpa_proto = WPA_PROTO_RSN;
2652*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
2653*03f9172cSAndroid Build Coastguard Worker elems.rsn_ie_len + 2);
2654*03f9172cSAndroid Build Coastguard Worker } else if (elems.wpa_ie) {
2655*03f9172cSAndroid Build Coastguard Worker params.wpa_proto = WPA_PROTO_WPA;
2656*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
2657*03f9172cSAndroid Build Coastguard Worker elems.wpa_ie_len + 2);
2658*03f9172cSAndroid Build Coastguard Worker } else if (elems.osen) {
2659*03f9172cSAndroid Build Coastguard Worker params.wpa_proto = WPA_PROTO_OSEN;
2660*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
2661*03f9172cSAndroid Build Coastguard Worker elems.osen_len + 2);
2662*03f9172cSAndroid Build Coastguard Worker } else
2663*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
2664*03f9172cSAndroid Build Coastguard Worker if (elems.rsnxe)
2665*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_assoc_rsnxe(wpa_s->wpa, elems.rsnxe - 2,
2666*03f9172cSAndroid Build Coastguard Worker elems.rsnxe_len + 2);
2667*03f9172cSAndroid Build Coastguard Worker else
2668*03f9172cSAndroid Build Coastguard Worker wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
2669*03f9172cSAndroid Build Coastguard Worker if (ssid && ssid->p2p_group)
2670*03f9172cSAndroid Build Coastguard Worker params.p2p = 1;
2671*03f9172cSAndroid Build Coastguard Worker
2672*03f9172cSAndroid Build Coastguard Worker if (wpa_s->p2pdev->set_sta_uapsd)
2673*03f9172cSAndroid Build Coastguard Worker params.uapsd = wpa_s->p2pdev->sta_uapsd;
2674*03f9172cSAndroid Build Coastguard Worker else
2675*03f9172cSAndroid Build Coastguard Worker params.uapsd = -1;
2676*03f9172cSAndroid Build Coastguard Worker
2677*03f9172cSAndroid Build Coastguard Worker if (wpa_s->valid_links) {
2678*03f9172cSAndroid Build Coastguard Worker unsigned int i;
2679*03f9172cSAndroid Build Coastguard Worker
2680*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
2681*03f9172cSAndroid Build Coastguard Worker "MLD: In association. assoc_link_id=%u, valid_links=0x%x",
2682*03f9172cSAndroid Build Coastguard Worker wpa_s->mlo_assoc_link_id, wpa_s->valid_links);
2683*03f9172cSAndroid Build Coastguard Worker
2684*03f9172cSAndroid Build Coastguard Worker params.mld_params.mld_addr = wpa_s->ap_mld_addr;
2685*03f9172cSAndroid Build Coastguard Worker params.mld_params.valid_links = wpa_s->valid_links;
2686*03f9172cSAndroid Build Coastguard Worker params.mld_params.assoc_link_id = wpa_s->mlo_assoc_link_id;
2687*03f9172cSAndroid Build Coastguard Worker for_each_link(wpa_s->valid_links, i) {
2688*03f9172cSAndroid Build Coastguard Worker params.mld_params.mld_links[i].bssid =
2689*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].bssid;
2690*03f9172cSAndroid Build Coastguard Worker params.mld_params.mld_links[i].freq =
2691*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].freq;
2692*03f9172cSAndroid Build Coastguard Worker params.mld_params.mld_links[i].disabled =
2693*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].disabled;
2694*03f9172cSAndroid Build Coastguard Worker
2695*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
2696*03f9172cSAndroid Build Coastguard Worker "MLD: id=%u, freq=%d, disabled=%u, " MACSTR,
2697*03f9172cSAndroid Build Coastguard Worker i, wpa_s->links[i].freq,
2698*03f9172cSAndroid Build Coastguard Worker wpa_s->links[i].disabled,
2699*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->links[i].bssid));
2700*03f9172cSAndroid Build Coastguard Worker }
2701*03f9172cSAndroid Build Coastguard Worker }
2702*03f9172cSAndroid Build Coastguard Worker
2703*03f9172cSAndroid Build Coastguard Worker if (wpa_drv_associate(wpa_s, ¶ms) < 0) {
2704*03f9172cSAndroid Build Coastguard Worker unsigned int n_failed_links = 0;
2705*03f9172cSAndroid Build Coastguard Worker int i;
2706*03f9172cSAndroid Build Coastguard Worker
2707*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
2708*03f9172cSAndroid Build Coastguard Worker "driver failed");
2709*03f9172cSAndroid Build Coastguard Worker
2710*03f9172cSAndroid Build Coastguard Worker /* Prepare list of failed links for error report */
2711*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < MAX_NUM_MLD_LINKS; i++) {
2712*03f9172cSAndroid Build Coastguard Worker if (!(wpa_s->valid_links & BIT(i)) ||
2713*03f9172cSAndroid Build Coastguard Worker wpa_s->mlo_assoc_link_id == i ||
2714*03f9172cSAndroid Build Coastguard Worker !params.mld_params.mld_links[i].error)
2715*03f9172cSAndroid Build Coastguard Worker continue;
2716*03f9172cSAndroid Build Coastguard Worker
2717*03f9172cSAndroid Build Coastguard Worker wpa_bssid_ignore_add(wpa_s, wpa_s->links[i].bssid);
2718*03f9172cSAndroid Build Coastguard Worker n_failed_links++;
2719*03f9172cSAndroid Build Coastguard Worker }
2720*03f9172cSAndroid Build Coastguard Worker
2721*03f9172cSAndroid Build Coastguard Worker if (n_failed_links) {
2722*03f9172cSAndroid Build Coastguard Worker /* Deauth and connect (possibly to the same AP MLD) */
2723*03f9172cSAndroid Build Coastguard Worker wpa_drv_deauthenticate(wpa_s, wpa_s->ap_mld_addr,
2724*03f9172cSAndroid Build Coastguard Worker WLAN_REASON_DEAUTH_LEAVING);
2725*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
2726*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
2727*03f9172cSAndroid Build Coastguard Worker wpas_request_connection(wpa_s);
2728*03f9172cSAndroid Build Coastguard Worker } else {
2729*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid,
2730*03f9172cSAndroid Build Coastguard Worker NULL);
2731*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2732*03f9172cSAndroid Build Coastguard Worker os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2733*03f9172cSAndroid Build Coastguard Worker }
2734*03f9172cSAndroid Build Coastguard Worker return;
2735*03f9172cSAndroid Build Coastguard Worker }
2736*03f9172cSAndroid Build Coastguard Worker
2737*03f9172cSAndroid Build Coastguard Worker eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
2738*03f9172cSAndroid Build Coastguard Worker NULL);
2739*03f9172cSAndroid Build Coastguard Worker
2740*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
2741*03f9172cSAndroid Build Coastguard Worker wpabuf_free(wpa_s->last_assoc_req_wpa_ie);
2742*03f9172cSAndroid Build Coastguard Worker wpa_s->last_assoc_req_wpa_ie = NULL;
2743*03f9172cSAndroid Build Coastguard Worker if (params.wpa_ie)
2744*03f9172cSAndroid Build Coastguard Worker wpa_s->last_assoc_req_wpa_ie =
2745*03f9172cSAndroid Build Coastguard Worker wpabuf_alloc_copy(params.wpa_ie, params.wpa_ie_len);
2746*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
2747*03f9172cSAndroid Build Coastguard Worker }
2748*03f9172cSAndroid Build Coastguard Worker
2749*03f9172cSAndroid Build Coastguard Worker
sme_update_ft_ies(struct wpa_supplicant * wpa_s,const u8 * md,const u8 * ies,size_t ies_len)2750*03f9172cSAndroid Build Coastguard Worker int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
2751*03f9172cSAndroid Build Coastguard Worker const u8 *ies, size_t ies_len)
2752*03f9172cSAndroid Build Coastguard Worker {
2753*03f9172cSAndroid Build Coastguard Worker if (md == NULL || ies == NULL) {
2754*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
2755*03f9172cSAndroid Build Coastguard Worker os_free(wpa_s->sme.ft_ies);
2756*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ft_ies = NULL;
2757*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ft_ies_len = 0;
2758*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ft_used = 0;
2759*03f9172cSAndroid Build Coastguard Worker return 0;
2760*03f9172cSAndroid Build Coastguard Worker }
2761*03f9172cSAndroid Build Coastguard Worker
2762*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
2763*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
2764*03f9172cSAndroid Build Coastguard Worker os_free(wpa_s->sme.ft_ies);
2765*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ft_ies = os_memdup(ies, ies_len);
2766*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.ft_ies == NULL)
2767*03f9172cSAndroid Build Coastguard Worker return -1;
2768*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ft_ies_len = ies_len;
2769*03f9172cSAndroid Build Coastguard Worker return 0;
2770*03f9172cSAndroid Build Coastguard Worker }
2771*03f9172cSAndroid Build Coastguard Worker
2772*03f9172cSAndroid Build Coastguard Worker
sme_deauth(struct wpa_supplicant * wpa_s,const u8 ** link_bssids)2773*03f9172cSAndroid Build Coastguard Worker static void sme_deauth(struct wpa_supplicant *wpa_s, const u8 **link_bssids)
2774*03f9172cSAndroid Build Coastguard Worker {
2775*03f9172cSAndroid Build Coastguard Worker int bssid_changed;
2776*03f9172cSAndroid Build Coastguard Worker const u8 *bssid;
2777*03f9172cSAndroid Build Coastguard Worker
2778*03f9172cSAndroid Build Coastguard Worker bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
2779*03f9172cSAndroid Build Coastguard Worker
2780*03f9172cSAndroid Build Coastguard Worker if (wpa_s->valid_links)
2781*03f9172cSAndroid Build Coastguard Worker bssid = wpa_s->ap_mld_addr;
2782*03f9172cSAndroid Build Coastguard Worker else
2783*03f9172cSAndroid Build Coastguard Worker bssid = wpa_s->pending_bssid;
2784*03f9172cSAndroid Build Coastguard Worker
2785*03f9172cSAndroid Build Coastguard Worker if (wpa_drv_deauthenticate(wpa_s, bssid,
2786*03f9172cSAndroid Build Coastguard Worker WLAN_REASON_DEAUTH_LEAVING) < 0) {
2787*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
2788*03f9172cSAndroid Build Coastguard Worker "failed");
2789*03f9172cSAndroid Build Coastguard Worker }
2790*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.prev_bssid_set = 0;
2791*03f9172cSAndroid Build Coastguard Worker
2792*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid, link_bssids);
2793*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
2794*03f9172cSAndroid Build Coastguard Worker os_memset(wpa_s->bssid, 0, ETH_ALEN);
2795*03f9172cSAndroid Build Coastguard Worker os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
2796*03f9172cSAndroid Build Coastguard Worker if (bssid_changed)
2797*03f9172cSAndroid Build Coastguard Worker wpas_notify_bssid_changed(wpa_s);
2798*03f9172cSAndroid Build Coastguard Worker }
2799*03f9172cSAndroid Build Coastguard Worker
2800*03f9172cSAndroid Build Coastguard Worker
sme_assoc_comeback_timer(void * eloop_ctx,void * timeout_ctx)2801*03f9172cSAndroid Build Coastguard Worker static void sme_assoc_comeback_timer(void *eloop_ctx, void *timeout_ctx)
2802*03f9172cSAndroid Build Coastguard Worker {
2803*03f9172cSAndroid Build Coastguard Worker struct wpa_supplicant *wpa_s = eloop_ctx;
2804*03f9172cSAndroid Build Coastguard Worker
2805*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->current_bss || !wpa_s->current_ssid) {
2806*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_DEBUG,
2807*03f9172cSAndroid Build Coastguard Worker "SME: Comeback timeout expired; SSID/BSSID cleared; ignoring");
2808*03f9172cSAndroid Build Coastguard Worker return;
2809*03f9172cSAndroid Build Coastguard Worker }
2810*03f9172cSAndroid Build Coastguard Worker
2811*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_DEBUG,
2812*03f9172cSAndroid Build Coastguard Worker "SME: Comeback timeout expired; retry associating with "
2813*03f9172cSAndroid Build Coastguard Worker MACSTR "; mode=%d auth_type=%u",
2814*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->current_bss->bssid),
2815*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid->mode,
2816*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_auth_type);
2817*03f9172cSAndroid Build Coastguard Worker
2818*03f9172cSAndroid Build Coastguard Worker /* Authentication state was completed already; just try association
2819*03f9172cSAndroid Build Coastguard Worker * again. */
2820*03f9172cSAndroid Build Coastguard Worker sme_associate(wpa_s, wpa_s->current_ssid->mode,
2821*03f9172cSAndroid Build Coastguard Worker wpa_s->current_bss->bssid,
2822*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.assoc_auth_type);
2823*03f9172cSAndroid Build Coastguard Worker }
2824*03f9172cSAndroid Build Coastguard Worker
2825*03f9172cSAndroid Build Coastguard Worker
sme_try_assoc_comeback(struct wpa_supplicant * wpa_s,union wpa_event_data * data)2826*03f9172cSAndroid Build Coastguard Worker static bool sme_try_assoc_comeback(struct wpa_supplicant *wpa_s,
2827*03f9172cSAndroid Build Coastguard Worker union wpa_event_data *data)
2828*03f9172cSAndroid Build Coastguard Worker {
2829*03f9172cSAndroid Build Coastguard Worker struct ieee802_11_elems elems;
2830*03f9172cSAndroid Build Coastguard Worker u32 timeout_interval;
2831*03f9172cSAndroid Build Coastguard Worker unsigned long comeback_usec;
2832*03f9172cSAndroid Build Coastguard Worker u8 type = WLAN_TIMEOUT_ASSOC_COMEBACK;
2833*03f9172cSAndroid Build Coastguard Worker
2834*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
2835*03f9172cSAndroid Build Coastguard Worker if (wpa_s->test_assoc_comeback_type != -1)
2836*03f9172cSAndroid Build Coastguard Worker type = wpa_s->test_assoc_comeback_type;
2837*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
2838*03f9172cSAndroid Build Coastguard Worker
2839*03f9172cSAndroid Build Coastguard Worker if (ieee802_11_parse_elems(data->assoc_reject.resp_ies,
2840*03f9172cSAndroid Build Coastguard Worker data->assoc_reject.resp_ies_len,
2841*03f9172cSAndroid Build Coastguard Worker &elems, 0) == ParseFailed) {
2842*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO,
2843*03f9172cSAndroid Build Coastguard Worker "SME: Temporary assoc reject: failed to parse (Re)Association Response frame elements");
2844*03f9172cSAndroid Build Coastguard Worker return false;
2845*03f9172cSAndroid Build Coastguard Worker }
2846*03f9172cSAndroid Build Coastguard Worker
2847*03f9172cSAndroid Build Coastguard Worker if (!elems.timeout_int) {
2848*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO,
2849*03f9172cSAndroid Build Coastguard Worker "SME: Temporary assoc reject: missing timeout interval IE");
2850*03f9172cSAndroid Build Coastguard Worker return false;
2851*03f9172cSAndroid Build Coastguard Worker }
2852*03f9172cSAndroid Build Coastguard Worker
2853*03f9172cSAndroid Build Coastguard Worker if (elems.timeout_int[0] != type) {
2854*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO,
2855*03f9172cSAndroid Build Coastguard Worker "SME: Temporary assoc reject: missing association comeback time");
2856*03f9172cSAndroid Build Coastguard Worker return false;
2857*03f9172cSAndroid Build Coastguard Worker }
2858*03f9172cSAndroid Build Coastguard Worker
2859*03f9172cSAndroid Build Coastguard Worker timeout_interval = WPA_GET_LE32(&elems.timeout_int[1]);
2860*03f9172cSAndroid Build Coastguard Worker if (timeout_interval > 60000) {
2861*03f9172cSAndroid Build Coastguard Worker /* This is unprotected information and there is no point in
2862*03f9172cSAndroid Build Coastguard Worker * getting stuck waiting for very long duration based on it */
2863*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_DEBUG,
2864*03f9172cSAndroid Build Coastguard Worker "SME: Ignore overly long association comeback interval: %u TUs",
2865*03f9172cSAndroid Build Coastguard Worker timeout_interval);
2866*03f9172cSAndroid Build Coastguard Worker return false;
2867*03f9172cSAndroid Build Coastguard Worker }
2868*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_DEBUG, "SME: Association comeback interval: %u TUs",
2869*03f9172cSAndroid Build Coastguard Worker timeout_interval);
2870*03f9172cSAndroid Build Coastguard Worker
2871*03f9172cSAndroid Build Coastguard Worker comeback_usec = timeout_interval * 1024;
2872*03f9172cSAndroid Build Coastguard Worker eloop_register_timeout(comeback_usec / 1000000, comeback_usec % 1000000,
2873*03f9172cSAndroid Build Coastguard Worker sme_assoc_comeback_timer, wpa_s, NULL);
2874*03f9172cSAndroid Build Coastguard Worker return true;
2875*03f9172cSAndroid Build Coastguard Worker }
2876*03f9172cSAndroid Build Coastguard Worker
2877*03f9172cSAndroid Build Coastguard Worker
sme_event_assoc_reject(struct wpa_supplicant * wpa_s,union wpa_event_data * data,const u8 ** link_bssids)2878*03f9172cSAndroid Build Coastguard Worker void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
2879*03f9172cSAndroid Build Coastguard Worker union wpa_event_data *data,
2880*03f9172cSAndroid Build Coastguard Worker const u8 **link_bssids)
2881*03f9172cSAndroid Build Coastguard Worker {
2882*03f9172cSAndroid Build Coastguard Worker const u8 *bssid;
2883*03f9172cSAndroid Build Coastguard Worker
2884*03f9172cSAndroid Build Coastguard Worker if (wpa_s->valid_links)
2885*03f9172cSAndroid Build Coastguard Worker bssid = wpa_s->ap_mld_addr;
2886*03f9172cSAndroid Build Coastguard Worker else
2887*03f9172cSAndroid Build Coastguard Worker bssid = wpa_s->pending_bssid;
2888*03f9172cSAndroid Build Coastguard Worker
2889*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
2890*03f9172cSAndroid Build Coastguard Worker "status code %d", MAC2STR(wpa_s->pending_bssid),
2891*03f9172cSAndroid Build Coastguard Worker data->assoc_reject.status_code);
2892*03f9172cSAndroid Build Coastguard Worker
2893*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
2894*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
2895*03f9172cSAndroid Build Coastguard Worker
2896*03f9172cSAndroid Build Coastguard Worker /* Authentication phase has been completed at this point. Check whether
2897*03f9172cSAndroid Build Coastguard Worker * the AP rejected association temporarily due to still holding a
2898*03f9172cSAndroid Build Coastguard Worker * security associationis with us (MFP). If so, we must wait for the
2899*03f9172cSAndroid Build Coastguard Worker * AP's association comeback timeout period before associating again. */
2900*03f9172cSAndroid Build Coastguard Worker if (data->assoc_reject.status_code ==
2901*03f9172cSAndroid Build Coastguard Worker WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
2902*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_DEBUG,
2903*03f9172cSAndroid Build Coastguard Worker "SME: Temporary association reject from BSS " MACSTR,
2904*03f9172cSAndroid Build Coastguard Worker MAC2STR(bssid));
2905*03f9172cSAndroid Build Coastguard Worker if (sme_try_assoc_comeback(wpa_s, data)) {
2906*03f9172cSAndroid Build Coastguard Worker /* Break out early; comeback error is not a failure. */
2907*03f9172cSAndroid Build Coastguard Worker return;
2908*03f9172cSAndroid Build Coastguard Worker }
2909*03f9172cSAndroid Build Coastguard Worker }
2910*03f9172cSAndroid Build Coastguard Worker
2911*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
2912*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
2913*03f9172cSAndroid Build Coastguard Worker wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
2914*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
2915*03f9172cSAndroid Build Coastguard Worker "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
2916*03f9172cSAndroid Build Coastguard Worker wpa_sm_aborted_cached(wpa_s->wpa);
2917*03f9172cSAndroid Build Coastguard Worker wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
2918*03f9172cSAndroid Build Coastguard Worker if (wpa_s->current_bss) {
2919*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss = wpa_s->current_bss;
2920*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid = wpa_s->current_ssid;
2921*03f9172cSAndroid Build Coastguard Worker
2922*03f9172cSAndroid Build Coastguard Worker wpa_drv_deauthenticate(wpa_s, bssid,
2923*03f9172cSAndroid Build Coastguard Worker WLAN_REASON_DEAUTH_LEAVING);
2924*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
2925*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
2926*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_connect(wpa_s, bss, ssid);
2927*03f9172cSAndroid Build Coastguard Worker return;
2928*03f9172cSAndroid Build Coastguard Worker }
2929*03f9172cSAndroid Build Coastguard Worker }
2930*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
2931*03f9172cSAndroid Build Coastguard Worker
2932*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_DPP
2933*03f9172cSAndroid Build Coastguard Worker if (wpa_s->current_ssid &&
2934*03f9172cSAndroid Build Coastguard Worker wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP &&
2935*03f9172cSAndroid Build Coastguard Worker !data->assoc_reject.timed_out &&
2936*03f9172cSAndroid Build Coastguard Worker data->assoc_reject.status_code == WLAN_STATUS_INVALID_PMKID) {
2937*03f9172cSAndroid Build Coastguard Worker struct rsn_pmksa_cache_entry *pmksa;
2938*03f9172cSAndroid Build Coastguard Worker
2939*03f9172cSAndroid Build Coastguard Worker pmksa = pmksa_cache_get_current(wpa_s->wpa);
2940*03f9172cSAndroid Build Coastguard Worker if (pmksa) {
2941*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
2942*03f9172cSAndroid Build Coastguard Worker "DPP: Drop PMKSA cache entry for the BSS due to invalid PMKID report");
2943*03f9172cSAndroid Build Coastguard Worker wpa_sm_pmksa_cache_remove(wpa_s->wpa, pmksa);
2944*03f9172cSAndroid Build Coastguard Worker }
2945*03f9172cSAndroid Build Coastguard Worker wpa_sm_aborted_cached(wpa_s->wpa);
2946*03f9172cSAndroid Build Coastguard Worker if (wpa_s->current_bss) {
2947*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss = wpa_s->current_bss;
2948*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid = wpa_s->current_ssid;
2949*03f9172cSAndroid Build Coastguard Worker
2950*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
2951*03f9172cSAndroid Build Coastguard Worker "DPP: Try network introduction again");
2952*03f9172cSAndroid Build Coastguard Worker wpas_connect_work_done(wpa_s);
2953*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
2954*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_connect(wpa_s, bss, ssid);
2955*03f9172cSAndroid Build Coastguard Worker return;
2956*03f9172cSAndroid Build Coastguard Worker }
2957*03f9172cSAndroid Build Coastguard Worker }
2958*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_DPP */
2959*03f9172cSAndroid Build Coastguard Worker
2960*03f9172cSAndroid Build Coastguard Worker /*
2961*03f9172cSAndroid Build Coastguard Worker * For now, unconditionally terminate the previous authentication. In
2962*03f9172cSAndroid Build Coastguard Worker * theory, this should not be needed, but mac80211 gets quite confused
2963*03f9172cSAndroid Build Coastguard Worker * if the authentication is left pending.. Some roaming cases might
2964*03f9172cSAndroid Build Coastguard Worker * benefit from using the previous authentication, so this could be
2965*03f9172cSAndroid Build Coastguard Worker * optimized in the future.
2966*03f9172cSAndroid Build Coastguard Worker */
2967*03f9172cSAndroid Build Coastguard Worker sme_deauth(wpa_s, link_bssids);
2968*03f9172cSAndroid Build Coastguard Worker }
2969*03f9172cSAndroid Build Coastguard Worker
2970*03f9172cSAndroid Build Coastguard Worker
sme_event_auth_timed_out(struct wpa_supplicant * wpa_s,union wpa_event_data * data)2971*03f9172cSAndroid Build Coastguard Worker void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
2972*03f9172cSAndroid Build Coastguard Worker union wpa_event_data *data)
2973*03f9172cSAndroid Build Coastguard Worker {
2974*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
2975*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
2976*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
2977*03f9172cSAndroid Build Coastguard Worker }
2978*03f9172cSAndroid Build Coastguard Worker
2979*03f9172cSAndroid Build Coastguard Worker
sme_event_assoc_timed_out(struct wpa_supplicant * wpa_s,union wpa_event_data * data)2980*03f9172cSAndroid Build Coastguard Worker void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
2981*03f9172cSAndroid Build Coastguard Worker union wpa_event_data *data)
2982*03f9172cSAndroid Build Coastguard Worker {
2983*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
2984*03f9172cSAndroid Build Coastguard Worker wpas_connection_failed(wpa_s, wpa_s->pending_bssid, NULL);
2985*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_mark_disassoc(wpa_s);
2986*03f9172cSAndroid Build Coastguard Worker }
2987*03f9172cSAndroid Build Coastguard Worker
2988*03f9172cSAndroid Build Coastguard Worker
sme_event_disassoc(struct wpa_supplicant * wpa_s,struct disassoc_info * info)2989*03f9172cSAndroid Build Coastguard Worker void sme_event_disassoc(struct wpa_supplicant *wpa_s,
2990*03f9172cSAndroid Build Coastguard Worker struct disassoc_info *info)
2991*03f9172cSAndroid Build Coastguard Worker {
2992*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
2993*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.prev_bssid_set) {
2994*03f9172cSAndroid Build Coastguard Worker /*
2995*03f9172cSAndroid Build Coastguard Worker * cfg80211/mac80211 can get into somewhat confused state if
2996*03f9172cSAndroid Build Coastguard Worker * the AP only disassociates us and leaves us in authenticated
2997*03f9172cSAndroid Build Coastguard Worker * state. For now, force the state to be cleared to avoid
2998*03f9172cSAndroid Build Coastguard Worker * confusing errors if we try to associate with the AP again.
2999*03f9172cSAndroid Build Coastguard Worker */
3000*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
3001*03f9172cSAndroid Build Coastguard Worker "driver state");
3002*03f9172cSAndroid Build Coastguard Worker wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
3003*03f9172cSAndroid Build Coastguard Worker WLAN_REASON_DEAUTH_LEAVING);
3004*03f9172cSAndroid Build Coastguard Worker }
3005*03f9172cSAndroid Build Coastguard Worker }
3006*03f9172cSAndroid Build Coastguard Worker
3007*03f9172cSAndroid Build Coastguard Worker
sme_auth_timer(void * eloop_ctx,void * timeout_ctx)3008*03f9172cSAndroid Build Coastguard Worker static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
3009*03f9172cSAndroid Build Coastguard Worker {
3010*03f9172cSAndroid Build Coastguard Worker struct wpa_supplicant *wpa_s = eloop_ctx;
3011*03f9172cSAndroid Build Coastguard Worker if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
3012*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
3013*03f9172cSAndroid Build Coastguard Worker sme_deauth(wpa_s, NULL);
3014*03f9172cSAndroid Build Coastguard Worker }
3015*03f9172cSAndroid Build Coastguard Worker }
3016*03f9172cSAndroid Build Coastguard Worker
3017*03f9172cSAndroid Build Coastguard Worker
sme_assoc_timer(void * eloop_ctx,void * timeout_ctx)3018*03f9172cSAndroid Build Coastguard Worker static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
3019*03f9172cSAndroid Build Coastguard Worker {
3020*03f9172cSAndroid Build Coastguard Worker struct wpa_supplicant *wpa_s = eloop_ctx;
3021*03f9172cSAndroid Build Coastguard Worker if (wpa_s->wpa_state == WPA_ASSOCIATING) {
3022*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
3023*03f9172cSAndroid Build Coastguard Worker sme_deauth(wpa_s, NULL);
3024*03f9172cSAndroid Build Coastguard Worker }
3025*03f9172cSAndroid Build Coastguard Worker }
3026*03f9172cSAndroid Build Coastguard Worker
3027*03f9172cSAndroid Build Coastguard Worker
sme_state_changed(struct wpa_supplicant * wpa_s)3028*03f9172cSAndroid Build Coastguard Worker void sme_state_changed(struct wpa_supplicant *wpa_s)
3029*03f9172cSAndroid Build Coastguard Worker {
3030*03f9172cSAndroid Build Coastguard Worker /* Make sure timers are cleaned up appropriately. */
3031*03f9172cSAndroid Build Coastguard Worker if (wpa_s->wpa_state != WPA_ASSOCIATING) {
3032*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
3033*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
3034*03f9172cSAndroid Build Coastguard Worker }
3035*03f9172cSAndroid Build Coastguard Worker if (wpa_s->wpa_state != WPA_AUTHENTICATING)
3036*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
3037*03f9172cSAndroid Build Coastguard Worker }
3038*03f9172cSAndroid Build Coastguard Worker
3039*03f9172cSAndroid Build Coastguard Worker
sme_clear_on_disassoc(struct wpa_supplicant * wpa_s)3040*03f9172cSAndroid Build Coastguard Worker void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
3041*03f9172cSAndroid Build Coastguard Worker {
3042*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.prev_bssid_set = 0;
3043*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
3044*03f9172cSAndroid Build Coastguard Worker wpabuf_free(wpa_s->sme.sae_token);
3045*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_token = NULL;
3046*03f9172cSAndroid Build Coastguard Worker sae_clear_data(&wpa_s->sme.sae);
3047*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
3048*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_IEEE80211R
3049*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
3050*03f9172cSAndroid Build Coastguard Worker sme_update_ft_ies(wpa_s, NULL, NULL, 0);
3051*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_IEEE80211R */
3052*03f9172cSAndroid Build Coastguard Worker sme_stop_sa_query(wpa_s);
3053*03f9172cSAndroid Build Coastguard Worker }
3054*03f9172cSAndroid Build Coastguard Worker
3055*03f9172cSAndroid Build Coastguard Worker
sme_deinit(struct wpa_supplicant * wpa_s)3056*03f9172cSAndroid Build Coastguard Worker void sme_deinit(struct wpa_supplicant *wpa_s)
3057*03f9172cSAndroid Build Coastguard Worker {
3058*03f9172cSAndroid Build Coastguard Worker sme_clear_on_disassoc(wpa_s);
3059*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_SAE
3060*03f9172cSAndroid Build Coastguard Worker os_free(wpa_s->sme.sae_rejected_groups);
3061*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sae_rejected_groups = NULL;
3062*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_SAE */
3063*03f9172cSAndroid Build Coastguard Worker
3064*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
3065*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
3066*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
3067*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_assoc_comeback_timer, wpa_s, NULL);
3068*03f9172cSAndroid Build Coastguard Worker }
3069*03f9172cSAndroid Build Coastguard Worker
3070*03f9172cSAndroid Build Coastguard Worker
sme_send_2040_bss_coex(struct wpa_supplicant * wpa_s,const u8 * chan_list,u8 num_channels,u8 num_intol)3071*03f9172cSAndroid Build Coastguard Worker static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
3072*03f9172cSAndroid Build Coastguard Worker const u8 *chan_list, u8 num_channels,
3073*03f9172cSAndroid Build Coastguard Worker u8 num_intol)
3074*03f9172cSAndroid Build Coastguard Worker {
3075*03f9172cSAndroid Build Coastguard Worker struct ieee80211_2040_bss_coex_ie *bc_ie;
3076*03f9172cSAndroid Build Coastguard Worker struct ieee80211_2040_intol_chan_report *ic_report;
3077*03f9172cSAndroid Build Coastguard Worker struct wpabuf *buf;
3078*03f9172cSAndroid Build Coastguard Worker
3079*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
3080*03f9172cSAndroid Build Coastguard Worker " (num_channels=%u num_intol=%u)",
3081*03f9172cSAndroid Build Coastguard Worker MAC2STR(wpa_s->bssid), num_channels, num_intol);
3082*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
3083*03f9172cSAndroid Build Coastguard Worker chan_list, num_channels);
3084*03f9172cSAndroid Build Coastguard Worker
3085*03f9172cSAndroid Build Coastguard Worker buf = wpabuf_alloc(2 + /* action.category + action_code */
3086*03f9172cSAndroid Build Coastguard Worker sizeof(struct ieee80211_2040_bss_coex_ie) +
3087*03f9172cSAndroid Build Coastguard Worker sizeof(struct ieee80211_2040_intol_chan_report) +
3088*03f9172cSAndroid Build Coastguard Worker num_channels);
3089*03f9172cSAndroid Build Coastguard Worker if (buf == NULL)
3090*03f9172cSAndroid Build Coastguard Worker return;
3091*03f9172cSAndroid Build Coastguard Worker
3092*03f9172cSAndroid Build Coastguard Worker wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
3093*03f9172cSAndroid Build Coastguard Worker wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
3094*03f9172cSAndroid Build Coastguard Worker
3095*03f9172cSAndroid Build Coastguard Worker bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
3096*03f9172cSAndroid Build Coastguard Worker bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
3097*03f9172cSAndroid Build Coastguard Worker bc_ie->length = 1;
3098*03f9172cSAndroid Build Coastguard Worker if (num_intol)
3099*03f9172cSAndroid Build Coastguard Worker bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
3100*03f9172cSAndroid Build Coastguard Worker
3101*03f9172cSAndroid Build Coastguard Worker if (num_channels > 0) {
3102*03f9172cSAndroid Build Coastguard Worker ic_report = wpabuf_put(buf, sizeof(*ic_report));
3103*03f9172cSAndroid Build Coastguard Worker ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
3104*03f9172cSAndroid Build Coastguard Worker ic_report->length = num_channels + 1;
3105*03f9172cSAndroid Build Coastguard Worker ic_report->op_class = 0;
3106*03f9172cSAndroid Build Coastguard Worker os_memcpy(wpabuf_put(buf, num_channels), chan_list,
3107*03f9172cSAndroid Build Coastguard Worker num_channels);
3108*03f9172cSAndroid Build Coastguard Worker }
3109*03f9172cSAndroid Build Coastguard Worker
3110*03f9172cSAndroid Build Coastguard Worker if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3111*03f9172cSAndroid Build Coastguard Worker wpa_s->own_addr, wpa_s->bssid,
3112*03f9172cSAndroid Build Coastguard Worker wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
3113*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO,
3114*03f9172cSAndroid Build Coastguard Worker "SME: Failed to send 20/40 BSS Coexistence frame");
3115*03f9172cSAndroid Build Coastguard Worker }
3116*03f9172cSAndroid Build Coastguard Worker
3117*03f9172cSAndroid Build Coastguard Worker wpabuf_free(buf);
3118*03f9172cSAndroid Build Coastguard Worker }
3119*03f9172cSAndroid Build Coastguard Worker
3120*03f9172cSAndroid Build Coastguard Worker
sme_proc_obss_scan(struct wpa_supplicant * wpa_s)3121*03f9172cSAndroid Build Coastguard Worker int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
3122*03f9172cSAndroid Build Coastguard Worker {
3123*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss;
3124*03f9172cSAndroid Build Coastguard Worker const u8 *ie;
3125*03f9172cSAndroid Build Coastguard Worker u16 ht_cap;
3126*03f9172cSAndroid Build Coastguard Worker u8 chan_list[P2P_MAX_CHANNELS], channel;
3127*03f9172cSAndroid Build Coastguard Worker u8 num_channels = 0, num_intol = 0, i;
3128*03f9172cSAndroid Build Coastguard Worker
3129*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->sme.sched_obss_scan)
3130*03f9172cSAndroid Build Coastguard Worker return 0;
3131*03f9172cSAndroid Build Coastguard Worker
3132*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sched_obss_scan = 0;
3133*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
3134*03f9172cSAndroid Build Coastguard Worker return 1;
3135*03f9172cSAndroid Build Coastguard Worker
3136*03f9172cSAndroid Build Coastguard Worker /*
3137*03f9172cSAndroid Build Coastguard Worker * Check whether AP uses regulatory triplet or channel triplet in
3138*03f9172cSAndroid Build Coastguard Worker * country info. Right now the operating class of the BSS channel
3139*03f9172cSAndroid Build Coastguard Worker * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
3140*03f9172cSAndroid Build Coastguard Worker * based on the assumption that operating class triplet is not used in
3141*03f9172cSAndroid Build Coastguard Worker * beacon frame. If the First Channel Number/Operating Extension
3142*03f9172cSAndroid Build Coastguard Worker * Identifier octet has a positive integer value of 201 or greater,
3143*03f9172cSAndroid Build Coastguard Worker * then its operating class triplet.
3144*03f9172cSAndroid Build Coastguard Worker *
3145*03f9172cSAndroid Build Coastguard Worker * TODO: If Supported Operating Classes element is present in beacon
3146*03f9172cSAndroid Build Coastguard Worker * frame, have to lookup operating class in Annex E and fill them in
3147*03f9172cSAndroid Build Coastguard Worker * 2040 coex frame.
3148*03f9172cSAndroid Build Coastguard Worker */
3149*03f9172cSAndroid Build Coastguard Worker ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
3150*03f9172cSAndroid Build Coastguard Worker if (ie && (ie[1] >= 6) && (ie[5] >= 201))
3151*03f9172cSAndroid Build Coastguard Worker return 1;
3152*03f9172cSAndroid Build Coastguard Worker
3153*03f9172cSAndroid Build Coastguard Worker os_memset(chan_list, 0, sizeof(chan_list));
3154*03f9172cSAndroid Build Coastguard Worker
3155*03f9172cSAndroid Build Coastguard Worker dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
3156*03f9172cSAndroid Build Coastguard Worker /* Skip other band bss */
3157*03f9172cSAndroid Build Coastguard Worker enum hostapd_hw_mode mode;
3158*03f9172cSAndroid Build Coastguard Worker mode = ieee80211_freq_to_chan(bss->freq, &channel);
3159*03f9172cSAndroid Build Coastguard Worker if (mode != HOSTAPD_MODE_IEEE80211G &&
3160*03f9172cSAndroid Build Coastguard Worker mode != HOSTAPD_MODE_IEEE80211B)
3161*03f9172cSAndroid Build Coastguard Worker continue;
3162*03f9172cSAndroid Build Coastguard Worker
3163*03f9172cSAndroid Build Coastguard Worker ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
3164*03f9172cSAndroid Build Coastguard Worker ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
3165*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
3166*03f9172cSAndroid Build Coastguard Worker " freq=%u chan=%u ht_cap=0x%x",
3167*03f9172cSAndroid Build Coastguard Worker MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
3168*03f9172cSAndroid Build Coastguard Worker
3169*03f9172cSAndroid Build Coastguard Worker if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
3170*03f9172cSAndroid Build Coastguard Worker if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
3171*03f9172cSAndroid Build Coastguard Worker num_intol++;
3172*03f9172cSAndroid Build Coastguard Worker
3173*03f9172cSAndroid Build Coastguard Worker /* Check whether the channel is already considered */
3174*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < num_channels; i++) {
3175*03f9172cSAndroid Build Coastguard Worker if (channel == chan_list[i])
3176*03f9172cSAndroid Build Coastguard Worker break;
3177*03f9172cSAndroid Build Coastguard Worker }
3178*03f9172cSAndroid Build Coastguard Worker if (i != num_channels)
3179*03f9172cSAndroid Build Coastguard Worker continue;
3180*03f9172cSAndroid Build Coastguard Worker
3181*03f9172cSAndroid Build Coastguard Worker chan_list[num_channels++] = channel;
3182*03f9172cSAndroid Build Coastguard Worker }
3183*03f9172cSAndroid Build Coastguard Worker }
3184*03f9172cSAndroid Build Coastguard Worker
3185*03f9172cSAndroid Build Coastguard Worker sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
3186*03f9172cSAndroid Build Coastguard Worker return 1;
3187*03f9172cSAndroid Build Coastguard Worker }
3188*03f9172cSAndroid Build Coastguard Worker
3189*03f9172cSAndroid Build Coastguard Worker
wpa_obss_scan_freqs_list(struct wpa_supplicant * wpa_s,struct wpa_driver_scan_params * params)3190*03f9172cSAndroid Build Coastguard Worker static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
3191*03f9172cSAndroid Build Coastguard Worker struct wpa_driver_scan_params *params)
3192*03f9172cSAndroid Build Coastguard Worker {
3193*03f9172cSAndroid Build Coastguard Worker /* Include only affected channels */
3194*03f9172cSAndroid Build Coastguard Worker struct hostapd_hw_modes *mode;
3195*03f9172cSAndroid Build Coastguard Worker int count, i;
3196*03f9172cSAndroid Build Coastguard Worker int start, end;
3197*03f9172cSAndroid Build Coastguard Worker
3198*03f9172cSAndroid Build Coastguard Worker mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
3199*03f9172cSAndroid Build Coastguard Worker HOSTAPD_MODE_IEEE80211G, false);
3200*03f9172cSAndroid Build Coastguard Worker if (mode == NULL) {
3201*03f9172cSAndroid Build Coastguard Worker /* No channels supported in this band - use empty list */
3202*03f9172cSAndroid Build Coastguard Worker params->freqs = os_zalloc(sizeof(int));
3203*03f9172cSAndroid Build Coastguard Worker return;
3204*03f9172cSAndroid Build Coastguard Worker }
3205*03f9172cSAndroid Build Coastguard Worker
3206*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
3207*03f9172cSAndroid Build Coastguard Worker wpa_s->current_bss) {
3208*03f9172cSAndroid Build Coastguard Worker const u8 *ie;
3209*03f9172cSAndroid Build Coastguard Worker
3210*03f9172cSAndroid Build Coastguard Worker ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
3211*03f9172cSAndroid Build Coastguard Worker if (ie && ie[1] >= 2) {
3212*03f9172cSAndroid Build Coastguard Worker u8 o;
3213*03f9172cSAndroid Build Coastguard Worker
3214*03f9172cSAndroid Build Coastguard Worker o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
3215*03f9172cSAndroid Build Coastguard Worker if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
3216*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
3217*03f9172cSAndroid Build Coastguard Worker else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
3218*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
3219*03f9172cSAndroid Build Coastguard Worker }
3220*03f9172cSAndroid Build Coastguard Worker }
3221*03f9172cSAndroid Build Coastguard Worker
3222*03f9172cSAndroid Build Coastguard Worker start = wpa_s->assoc_freq - 10;
3223*03f9172cSAndroid Build Coastguard Worker end = wpa_s->assoc_freq + 10;
3224*03f9172cSAndroid Build Coastguard Worker switch (wpa_s->sme.ht_sec_chan) {
3225*03f9172cSAndroid Build Coastguard Worker case HT_SEC_CHAN_UNKNOWN:
3226*03f9172cSAndroid Build Coastguard Worker /* HT40+ possible on channels 1..9 */
3227*03f9172cSAndroid Build Coastguard Worker if (wpa_s->assoc_freq <= 2452)
3228*03f9172cSAndroid Build Coastguard Worker start -= 20;
3229*03f9172cSAndroid Build Coastguard Worker /* HT40- possible on channels 5-13 */
3230*03f9172cSAndroid Build Coastguard Worker if (wpa_s->assoc_freq >= 2432)
3231*03f9172cSAndroid Build Coastguard Worker end += 20;
3232*03f9172cSAndroid Build Coastguard Worker break;
3233*03f9172cSAndroid Build Coastguard Worker case HT_SEC_CHAN_ABOVE:
3234*03f9172cSAndroid Build Coastguard Worker end += 20;
3235*03f9172cSAndroid Build Coastguard Worker break;
3236*03f9172cSAndroid Build Coastguard Worker case HT_SEC_CHAN_BELOW:
3237*03f9172cSAndroid Build Coastguard Worker start -= 20;
3238*03f9172cSAndroid Build Coastguard Worker break;
3239*03f9172cSAndroid Build Coastguard Worker }
3240*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
3241*03f9172cSAndroid Build Coastguard Worker "OBSS: assoc_freq %d possible affected range %d-%d",
3242*03f9172cSAndroid Build Coastguard Worker wpa_s->assoc_freq, start, end);
3243*03f9172cSAndroid Build Coastguard Worker
3244*03f9172cSAndroid Build Coastguard Worker params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
3245*03f9172cSAndroid Build Coastguard Worker if (params->freqs == NULL)
3246*03f9172cSAndroid Build Coastguard Worker return;
3247*03f9172cSAndroid Build Coastguard Worker for (count = 0, i = 0; i < mode->num_channels; i++) {
3248*03f9172cSAndroid Build Coastguard Worker int freq;
3249*03f9172cSAndroid Build Coastguard Worker
3250*03f9172cSAndroid Build Coastguard Worker if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
3251*03f9172cSAndroid Build Coastguard Worker continue;
3252*03f9172cSAndroid Build Coastguard Worker freq = mode->channels[i].freq;
3253*03f9172cSAndroid Build Coastguard Worker if (freq - 10 >= end || freq + 10 <= start)
3254*03f9172cSAndroid Build Coastguard Worker continue; /* not affected */
3255*03f9172cSAndroid Build Coastguard Worker params->freqs[count++] = freq;
3256*03f9172cSAndroid Build Coastguard Worker }
3257*03f9172cSAndroid Build Coastguard Worker }
3258*03f9172cSAndroid Build Coastguard Worker
3259*03f9172cSAndroid Build Coastguard Worker
sme_obss_scan_timeout(void * eloop_ctx,void * timeout_ctx)3260*03f9172cSAndroid Build Coastguard Worker static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
3261*03f9172cSAndroid Build Coastguard Worker {
3262*03f9172cSAndroid Build Coastguard Worker struct wpa_supplicant *wpa_s = eloop_ctx;
3263*03f9172cSAndroid Build Coastguard Worker struct wpa_driver_scan_params params;
3264*03f9172cSAndroid Build Coastguard Worker
3265*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->current_bss) {
3266*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
3267*03f9172cSAndroid Build Coastguard Worker return;
3268*03f9172cSAndroid Build Coastguard Worker }
3269*03f9172cSAndroid Build Coastguard Worker
3270*03f9172cSAndroid Build Coastguard Worker os_memset(¶ms, 0, sizeof(params));
3271*03f9172cSAndroid Build Coastguard Worker wpa_obss_scan_freqs_list(wpa_s, ¶ms);
3272*03f9172cSAndroid Build Coastguard Worker params.low_priority = 1;
3273*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
3274*03f9172cSAndroid Build Coastguard Worker
3275*03f9172cSAndroid Build Coastguard Worker if (wpa_supplicant_trigger_scan(wpa_s, ¶ms, true, false))
3276*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
3277*03f9172cSAndroid Build Coastguard Worker else
3278*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sched_obss_scan = 1;
3279*03f9172cSAndroid Build Coastguard Worker os_free(params.freqs);
3280*03f9172cSAndroid Build Coastguard Worker
3281*03f9172cSAndroid Build Coastguard Worker eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3282*03f9172cSAndroid Build Coastguard Worker sme_obss_scan_timeout, wpa_s, NULL);
3283*03f9172cSAndroid Build Coastguard Worker }
3284*03f9172cSAndroid Build Coastguard Worker
3285*03f9172cSAndroid Build Coastguard Worker
sme_sched_obss_scan(struct wpa_supplicant * wpa_s,int enable)3286*03f9172cSAndroid Build Coastguard Worker void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
3287*03f9172cSAndroid Build Coastguard Worker {
3288*03f9172cSAndroid Build Coastguard Worker const u8 *ie;
3289*03f9172cSAndroid Build Coastguard Worker struct wpa_bss *bss = wpa_s->current_bss;
3290*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid = wpa_s->current_ssid;
3291*03f9172cSAndroid Build Coastguard Worker struct hostapd_hw_modes *hw_mode = NULL;
3292*03f9172cSAndroid Build Coastguard Worker int i;
3293*03f9172cSAndroid Build Coastguard Worker
3294*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
3295*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sched_obss_scan = 0;
3296*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
3297*03f9172cSAndroid Build Coastguard Worker if (!enable)
3298*03f9172cSAndroid Build Coastguard Worker return;
3299*03f9172cSAndroid Build Coastguard Worker
3300*03f9172cSAndroid Build Coastguard Worker /*
3301*03f9172cSAndroid Build Coastguard Worker * Schedule OBSS scan if driver is using station SME in wpa_supplicant
3302*03f9172cSAndroid Build Coastguard Worker * or it expects OBSS scan to be performed by wpa_supplicant.
3303*03f9172cSAndroid Build Coastguard Worker */
3304*03f9172cSAndroid Build Coastguard Worker if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
3305*03f9172cSAndroid Build Coastguard Worker (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
3306*03f9172cSAndroid Build Coastguard Worker ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
3307*03f9172cSAndroid Build Coastguard Worker return;
3308*03f9172cSAndroid Build Coastguard Worker
3309*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_HT_OVERRIDES
3310*03f9172cSAndroid Build Coastguard Worker /* No need for OBSS scan if HT40 is explicitly disabled */
3311*03f9172cSAndroid Build Coastguard Worker if (ssid->disable_ht40)
3312*03f9172cSAndroid Build Coastguard Worker return;
3313*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_HT_OVERRIDES */
3314*03f9172cSAndroid Build Coastguard Worker
3315*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->hw.modes)
3316*03f9172cSAndroid Build Coastguard Worker return;
3317*03f9172cSAndroid Build Coastguard Worker
3318*03f9172cSAndroid Build Coastguard Worker /* only HT caps in 11g mode are relevant */
3319*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < wpa_s->hw.num_modes; i++) {
3320*03f9172cSAndroid Build Coastguard Worker hw_mode = &wpa_s->hw.modes[i];
3321*03f9172cSAndroid Build Coastguard Worker if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
3322*03f9172cSAndroid Build Coastguard Worker break;
3323*03f9172cSAndroid Build Coastguard Worker }
3324*03f9172cSAndroid Build Coastguard Worker
3325*03f9172cSAndroid Build Coastguard Worker /* Driver does not support HT40 for 11g or doesn't have 11g. */
3326*03f9172cSAndroid Build Coastguard Worker if (i == wpa_s->hw.num_modes || !hw_mode ||
3327*03f9172cSAndroid Build Coastguard Worker !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3328*03f9172cSAndroid Build Coastguard Worker return;
3329*03f9172cSAndroid Build Coastguard Worker
3330*03f9172cSAndroid Build Coastguard Worker if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
3331*03f9172cSAndroid Build Coastguard Worker return; /* Not associated on 2.4 GHz band */
3332*03f9172cSAndroid Build Coastguard Worker
3333*03f9172cSAndroid Build Coastguard Worker /* Check whether AP supports HT40 */
3334*03f9172cSAndroid Build Coastguard Worker ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
3335*03f9172cSAndroid Build Coastguard Worker if (!ie || ie[1] < 2 ||
3336*03f9172cSAndroid Build Coastguard Worker !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
3337*03f9172cSAndroid Build Coastguard Worker return; /* AP does not support HT40 */
3338*03f9172cSAndroid Build Coastguard Worker
3339*03f9172cSAndroid Build Coastguard Worker ie = wpa_bss_get_ie(wpa_s->current_bss,
3340*03f9172cSAndroid Build Coastguard Worker WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
3341*03f9172cSAndroid Build Coastguard Worker if (!ie || ie[1] < 14)
3342*03f9172cSAndroid Build Coastguard Worker return; /* AP does not request OBSS scans */
3343*03f9172cSAndroid Build Coastguard Worker
3344*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
3345*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.obss_scan_int < 10) {
3346*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
3347*03f9172cSAndroid Build Coastguard Worker "replaced with the minimum 10 sec",
3348*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.obss_scan_int);
3349*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.obss_scan_int = 10;
3350*03f9172cSAndroid Build Coastguard Worker }
3351*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
3352*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.obss_scan_int);
3353*03f9172cSAndroid Build Coastguard Worker eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
3354*03f9172cSAndroid Build Coastguard Worker sme_obss_scan_timeout, wpa_s, NULL);
3355*03f9172cSAndroid Build Coastguard Worker }
3356*03f9172cSAndroid Build Coastguard Worker
3357*03f9172cSAndroid Build Coastguard Worker
3358*03f9172cSAndroid Build Coastguard Worker static const unsigned int sa_query_max_timeout = 1000;
3359*03f9172cSAndroid Build Coastguard Worker static const unsigned int sa_query_retry_timeout = 201;
3360*03f9172cSAndroid Build Coastguard Worker static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
3361*03f9172cSAndroid Build Coastguard Worker
sme_check_sa_query_timeout(struct wpa_supplicant * wpa_s)3362*03f9172cSAndroid Build Coastguard Worker static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
3363*03f9172cSAndroid Build Coastguard Worker {
3364*03f9172cSAndroid Build Coastguard Worker u32 tu;
3365*03f9172cSAndroid Build Coastguard Worker struct os_reltime now, passed;
3366*03f9172cSAndroid Build Coastguard Worker os_get_reltime(&now);
3367*03f9172cSAndroid Build Coastguard Worker os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
3368*03f9172cSAndroid Build Coastguard Worker tu = (passed.sec * 1000000 + passed.usec) / 1024;
3369*03f9172cSAndroid Build Coastguard Worker if (sa_query_max_timeout < tu) {
3370*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
3371*03f9172cSAndroid Build Coastguard Worker sme_stop_sa_query(wpa_s);
3372*03f9172cSAndroid Build Coastguard Worker wpa_supplicant_deauthenticate(
3373*03f9172cSAndroid Build Coastguard Worker wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
3374*03f9172cSAndroid Build Coastguard Worker return 1;
3375*03f9172cSAndroid Build Coastguard Worker }
3376*03f9172cSAndroid Build Coastguard Worker
3377*03f9172cSAndroid Build Coastguard Worker return 0;
3378*03f9172cSAndroid Build Coastguard Worker }
3379*03f9172cSAndroid Build Coastguard Worker
3380*03f9172cSAndroid Build Coastguard Worker
sme_send_sa_query_req(struct wpa_supplicant * wpa_s,const u8 * trans_id)3381*03f9172cSAndroid Build Coastguard Worker static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
3382*03f9172cSAndroid Build Coastguard Worker const u8 *trans_id)
3383*03f9172cSAndroid Build Coastguard Worker {
3384*03f9172cSAndroid Build Coastguard Worker u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3385*03f9172cSAndroid Build Coastguard Worker u8 req_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3386*03f9172cSAndroid Build Coastguard Worker
3387*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
3388*03f9172cSAndroid Build Coastguard Worker MACSTR, MAC2STR(wpa_s->bssid));
3389*03f9172cSAndroid Build Coastguard Worker wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
3390*03f9172cSAndroid Build Coastguard Worker trans_id, WLAN_SA_QUERY_TR_ID_LEN);
3391*03f9172cSAndroid Build Coastguard Worker req[0] = WLAN_ACTION_SA_QUERY;
3392*03f9172cSAndroid Build Coastguard Worker req[1] = WLAN_SA_QUERY_REQUEST;
3393*03f9172cSAndroid Build Coastguard Worker os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
3394*03f9172cSAndroid Build Coastguard Worker
3395*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_OCV
3396*03f9172cSAndroid Build Coastguard Worker if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3397*03f9172cSAndroid Build Coastguard Worker struct wpa_channel_info ci;
3398*03f9172cSAndroid Build Coastguard Worker
3399*03f9172cSAndroid Build Coastguard Worker if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3400*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_WARNING,
3401*03f9172cSAndroid Build Coastguard Worker "Failed to get channel info for OCI element in SA Query Request frame");
3402*03f9172cSAndroid Build Coastguard Worker return;
3403*03f9172cSAndroid Build Coastguard Worker }
3404*03f9172cSAndroid Build Coastguard Worker
3405*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
3406*03f9172cSAndroid Build Coastguard Worker if (wpa_s->oci_freq_override_saquery_req) {
3407*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO,
3408*03f9172cSAndroid Build Coastguard Worker "TEST: Override SA Query Request OCI frequency %d -> %d MHz",
3409*03f9172cSAndroid Build Coastguard Worker ci.frequency,
3410*03f9172cSAndroid Build Coastguard Worker wpa_s->oci_freq_override_saquery_req);
3411*03f9172cSAndroid Build Coastguard Worker ci.frequency = wpa_s->oci_freq_override_saquery_req;
3412*03f9172cSAndroid Build Coastguard Worker }
3413*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
3414*03f9172cSAndroid Build Coastguard Worker
3415*03f9172cSAndroid Build Coastguard Worker if (ocv_insert_extended_oci(&ci, req + req_len) < 0)
3416*03f9172cSAndroid Build Coastguard Worker return;
3417*03f9172cSAndroid Build Coastguard Worker
3418*03f9172cSAndroid Build Coastguard Worker req_len += OCV_OCI_EXTENDED_LEN;
3419*03f9172cSAndroid Build Coastguard Worker }
3420*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_OCV */
3421*03f9172cSAndroid Build Coastguard Worker
3422*03f9172cSAndroid Build Coastguard Worker if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3423*03f9172cSAndroid Build Coastguard Worker wpa_s->own_addr, wpa_s->bssid,
3424*03f9172cSAndroid Build Coastguard Worker req, req_len, 0) < 0)
3425*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
3426*03f9172cSAndroid Build Coastguard Worker "Request");
3427*03f9172cSAndroid Build Coastguard Worker }
3428*03f9172cSAndroid Build Coastguard Worker
3429*03f9172cSAndroid Build Coastguard Worker
sme_sa_query_timer(void * eloop_ctx,void * timeout_ctx)3430*03f9172cSAndroid Build Coastguard Worker static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
3431*03f9172cSAndroid Build Coastguard Worker {
3432*03f9172cSAndroid Build Coastguard Worker struct wpa_supplicant *wpa_s = eloop_ctx;
3433*03f9172cSAndroid Build Coastguard Worker unsigned int timeout, sec, usec;
3434*03f9172cSAndroid Build Coastguard Worker u8 *trans_id, *nbuf;
3435*03f9172cSAndroid Build Coastguard Worker
3436*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sa_query_count > 0 &&
3437*03f9172cSAndroid Build Coastguard Worker sme_check_sa_query_timeout(wpa_s))
3438*03f9172cSAndroid Build Coastguard Worker return;
3439*03f9172cSAndroid Build Coastguard Worker
3440*03f9172cSAndroid Build Coastguard Worker nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
3441*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sa_query_count + 1,
3442*03f9172cSAndroid Build Coastguard Worker WLAN_SA_QUERY_TR_ID_LEN);
3443*03f9172cSAndroid Build Coastguard Worker if (nbuf == NULL) {
3444*03f9172cSAndroid Build Coastguard Worker sme_stop_sa_query(wpa_s);
3445*03f9172cSAndroid Build Coastguard Worker return;
3446*03f9172cSAndroid Build Coastguard Worker }
3447*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sa_query_count == 0) {
3448*03f9172cSAndroid Build Coastguard Worker /* Starting a new SA Query procedure */
3449*03f9172cSAndroid Build Coastguard Worker os_get_reltime(&wpa_s->sme.sa_query_start);
3450*03f9172cSAndroid Build Coastguard Worker }
3451*03f9172cSAndroid Build Coastguard Worker trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
3452*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sa_query_trans_id = nbuf;
3453*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sa_query_count++;
3454*03f9172cSAndroid Build Coastguard Worker
3455*03f9172cSAndroid Build Coastguard Worker if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
3456*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
3457*03f9172cSAndroid Build Coastguard Worker sme_stop_sa_query(wpa_s);
3458*03f9172cSAndroid Build Coastguard Worker return;
3459*03f9172cSAndroid Build Coastguard Worker }
3460*03f9172cSAndroid Build Coastguard Worker
3461*03f9172cSAndroid Build Coastguard Worker timeout = sa_query_retry_timeout;
3462*03f9172cSAndroid Build Coastguard Worker sec = ((timeout / 1000) * 1024) / 1000;
3463*03f9172cSAndroid Build Coastguard Worker usec = (timeout % 1000) * 1024;
3464*03f9172cSAndroid Build Coastguard Worker eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
3465*03f9172cSAndroid Build Coastguard Worker
3466*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
3467*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sa_query_count);
3468*03f9172cSAndroid Build Coastguard Worker
3469*03f9172cSAndroid Build Coastguard Worker sme_send_sa_query_req(wpa_s, trans_id);
3470*03f9172cSAndroid Build Coastguard Worker }
3471*03f9172cSAndroid Build Coastguard Worker
3472*03f9172cSAndroid Build Coastguard Worker
sme_start_sa_query(struct wpa_supplicant * wpa_s)3473*03f9172cSAndroid Build Coastguard Worker static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
3474*03f9172cSAndroid Build Coastguard Worker {
3475*03f9172cSAndroid Build Coastguard Worker sme_sa_query_timer(wpa_s, NULL);
3476*03f9172cSAndroid Build Coastguard Worker }
3477*03f9172cSAndroid Build Coastguard Worker
3478*03f9172cSAndroid Build Coastguard Worker
sme_stop_sa_query(struct wpa_supplicant * wpa_s)3479*03f9172cSAndroid Build Coastguard Worker static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
3480*03f9172cSAndroid Build Coastguard Worker {
3481*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sa_query_trans_id)
3482*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Stop SA Query");
3483*03f9172cSAndroid Build Coastguard Worker eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
3484*03f9172cSAndroid Build Coastguard Worker os_free(wpa_s->sme.sa_query_trans_id);
3485*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sa_query_trans_id = NULL;
3486*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.sa_query_count = 0;
3487*03f9172cSAndroid Build Coastguard Worker }
3488*03f9172cSAndroid Build Coastguard Worker
3489*03f9172cSAndroid Build Coastguard Worker
sme_event_unprot_disconnect(struct wpa_supplicant * wpa_s,const u8 * sa,const u8 * da,u16 reason_code)3490*03f9172cSAndroid Build Coastguard Worker void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
3491*03f9172cSAndroid Build Coastguard Worker const u8 *da, u16 reason_code)
3492*03f9172cSAndroid Build Coastguard Worker {
3493*03f9172cSAndroid Build Coastguard Worker struct wpa_ssid *ssid;
3494*03f9172cSAndroid Build Coastguard Worker struct os_reltime now;
3495*03f9172cSAndroid Build Coastguard Worker
3496*03f9172cSAndroid Build Coastguard Worker if (wpa_s->wpa_state != WPA_COMPLETED)
3497*03f9172cSAndroid Build Coastguard Worker return;
3498*03f9172cSAndroid Build Coastguard Worker ssid = wpa_s->current_ssid;
3499*03f9172cSAndroid Build Coastguard Worker if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
3500*03f9172cSAndroid Build Coastguard Worker return;
3501*03f9172cSAndroid Build Coastguard Worker if (!ether_addr_equal(sa, wpa_s->bssid))
3502*03f9172cSAndroid Build Coastguard Worker return;
3503*03f9172cSAndroid Build Coastguard Worker if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
3504*03f9172cSAndroid Build Coastguard Worker reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
3505*03f9172cSAndroid Build Coastguard Worker return;
3506*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.sa_query_count > 0)
3507*03f9172cSAndroid Build Coastguard Worker return;
3508*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
3509*03f9172cSAndroid Build Coastguard Worker if (wpa_s->disable_sa_query)
3510*03f9172cSAndroid Build Coastguard Worker return;
3511*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
3512*03f9172cSAndroid Build Coastguard Worker
3513*03f9172cSAndroid Build Coastguard Worker os_get_reltime(&now);
3514*03f9172cSAndroid Build Coastguard Worker if (wpa_s->sme.last_unprot_disconnect.sec &&
3515*03f9172cSAndroid Build Coastguard Worker !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
3516*03f9172cSAndroid Build Coastguard Worker return; /* limit SA Query procedure frequency */
3517*03f9172cSAndroid Build Coastguard Worker wpa_s->sme.last_unprot_disconnect = now;
3518*03f9172cSAndroid Build Coastguard Worker
3519*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
3520*03f9172cSAndroid Build Coastguard Worker "possible AP/STA state mismatch - trigger SA Query");
3521*03f9172cSAndroid Build Coastguard Worker sme_start_sa_query(wpa_s);
3522*03f9172cSAndroid Build Coastguard Worker }
3523*03f9172cSAndroid Build Coastguard Worker
3524*03f9172cSAndroid Build Coastguard Worker
sme_event_ch_switch(struct wpa_supplicant * wpa_s)3525*03f9172cSAndroid Build Coastguard Worker void sme_event_ch_switch(struct wpa_supplicant *wpa_s)
3526*03f9172cSAndroid Build Coastguard Worker {
3527*03f9172cSAndroid Build Coastguard Worker unsigned int usec;
3528*03f9172cSAndroid Build Coastguard Worker u32 _rand;
3529*03f9172cSAndroid Build Coastguard Worker
3530*03f9172cSAndroid Build Coastguard Worker if (wpa_s->wpa_state != WPA_COMPLETED ||
3531*03f9172cSAndroid Build Coastguard Worker !wpa_sm_ocv_enabled(wpa_s->wpa))
3532*03f9172cSAndroid Build Coastguard Worker return;
3533*03f9172cSAndroid Build Coastguard Worker
3534*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG,
3535*03f9172cSAndroid Build Coastguard Worker "SME: Channel switch completed - trigger new SA Query to verify new operating channel");
3536*03f9172cSAndroid Build Coastguard Worker sme_stop_sa_query(wpa_s);
3537*03f9172cSAndroid Build Coastguard Worker
3538*03f9172cSAndroid Build Coastguard Worker if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
3539*03f9172cSAndroid Build Coastguard Worker _rand = os_random();
3540*03f9172cSAndroid Build Coastguard Worker usec = _rand % (sa_query_ch_switch_max_delay + 1);
3541*03f9172cSAndroid Build Coastguard Worker eloop_register_timeout(0, usec, sme_sa_query_timer, wpa_s, NULL);
3542*03f9172cSAndroid Build Coastguard Worker }
3543*03f9172cSAndroid Build Coastguard Worker
3544*03f9172cSAndroid Build Coastguard Worker
sme_process_sa_query_request(struct wpa_supplicant * wpa_s,const u8 * sa,const u8 * data,size_t len)3545*03f9172cSAndroid Build Coastguard Worker static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s,
3546*03f9172cSAndroid Build Coastguard Worker const u8 *sa, const u8 *data,
3547*03f9172cSAndroid Build Coastguard Worker size_t len)
3548*03f9172cSAndroid Build Coastguard Worker {
3549*03f9172cSAndroid Build Coastguard Worker u8 resp[2 + WLAN_SA_QUERY_TR_ID_LEN + OCV_OCI_EXTENDED_LEN];
3550*03f9172cSAndroid Build Coastguard Worker u8 resp_len = 2 + WLAN_SA_QUERY_TR_ID_LEN;
3551*03f9172cSAndroid Build Coastguard Worker
3552*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Response to "
3553*03f9172cSAndroid Build Coastguard Worker MACSTR, MAC2STR(wpa_s->bssid));
3554*03f9172cSAndroid Build Coastguard Worker
3555*03f9172cSAndroid Build Coastguard Worker resp[0] = WLAN_ACTION_SA_QUERY;
3556*03f9172cSAndroid Build Coastguard Worker resp[1] = WLAN_SA_QUERY_RESPONSE;
3557*03f9172cSAndroid Build Coastguard Worker os_memcpy(resp + 2, data + 1, WLAN_SA_QUERY_TR_ID_LEN);
3558*03f9172cSAndroid Build Coastguard Worker
3559*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_OCV
3560*03f9172cSAndroid Build Coastguard Worker if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3561*03f9172cSAndroid Build Coastguard Worker struct wpa_channel_info ci;
3562*03f9172cSAndroid Build Coastguard Worker
3563*03f9172cSAndroid Build Coastguard Worker if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3564*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_WARNING,
3565*03f9172cSAndroid Build Coastguard Worker "Failed to get channel info for OCI element in SA Query Response frame");
3566*03f9172cSAndroid Build Coastguard Worker return;
3567*03f9172cSAndroid Build Coastguard Worker }
3568*03f9172cSAndroid Build Coastguard Worker
3569*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_TESTING_OPTIONS
3570*03f9172cSAndroid Build Coastguard Worker if (wpa_s->oci_freq_override_saquery_resp) {
3571*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_INFO,
3572*03f9172cSAndroid Build Coastguard Worker "TEST: Override SA Query Response OCI frequency %d -> %d MHz",
3573*03f9172cSAndroid Build Coastguard Worker ci.frequency,
3574*03f9172cSAndroid Build Coastguard Worker wpa_s->oci_freq_override_saquery_resp);
3575*03f9172cSAndroid Build Coastguard Worker ci.frequency = wpa_s->oci_freq_override_saquery_resp;
3576*03f9172cSAndroid Build Coastguard Worker }
3577*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_TESTING_OPTIONS */
3578*03f9172cSAndroid Build Coastguard Worker
3579*03f9172cSAndroid Build Coastguard Worker if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0)
3580*03f9172cSAndroid Build Coastguard Worker return;
3581*03f9172cSAndroid Build Coastguard Worker
3582*03f9172cSAndroid Build Coastguard Worker resp_len += OCV_OCI_EXTENDED_LEN;
3583*03f9172cSAndroid Build Coastguard Worker }
3584*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_OCV */
3585*03f9172cSAndroid Build Coastguard Worker
3586*03f9172cSAndroid Build Coastguard Worker if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
3587*03f9172cSAndroid Build Coastguard Worker wpa_s->own_addr, wpa_s->bssid,
3588*03f9172cSAndroid Build Coastguard Worker resp, resp_len, 0) < 0)
3589*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO,
3590*03f9172cSAndroid Build Coastguard Worker "SME: Failed to send SA Query Response");
3591*03f9172cSAndroid Build Coastguard Worker }
3592*03f9172cSAndroid Build Coastguard Worker
3593*03f9172cSAndroid Build Coastguard Worker
sme_process_sa_query_response(struct wpa_supplicant * wpa_s,const u8 * sa,const u8 * data,size_t len)3594*03f9172cSAndroid Build Coastguard Worker static void sme_process_sa_query_response(struct wpa_supplicant *wpa_s,
3595*03f9172cSAndroid Build Coastguard Worker const u8 *sa, const u8 *data,
3596*03f9172cSAndroid Build Coastguard Worker size_t len)
3597*03f9172cSAndroid Build Coastguard Worker {
3598*03f9172cSAndroid Build Coastguard Worker int i;
3599*03f9172cSAndroid Build Coastguard Worker
3600*03f9172cSAndroid Build Coastguard Worker if (!wpa_s->sme.sa_query_trans_id)
3601*03f9172cSAndroid Build Coastguard Worker return;
3602*03f9172cSAndroid Build Coastguard Worker
3603*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
3604*03f9172cSAndroid Build Coastguard Worker MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3605*03f9172cSAndroid Build Coastguard Worker
3606*03f9172cSAndroid Build Coastguard Worker if (!ether_addr_equal(sa, wpa_s->bssid))
3607*03f9172cSAndroid Build Coastguard Worker return;
3608*03f9172cSAndroid Build Coastguard Worker
3609*03f9172cSAndroid Build Coastguard Worker for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
3610*03f9172cSAndroid Build Coastguard Worker if (os_memcmp(wpa_s->sme.sa_query_trans_id +
3611*03f9172cSAndroid Build Coastguard Worker i * WLAN_SA_QUERY_TR_ID_LEN,
3612*03f9172cSAndroid Build Coastguard Worker data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
3613*03f9172cSAndroid Build Coastguard Worker break;
3614*03f9172cSAndroid Build Coastguard Worker }
3615*03f9172cSAndroid Build Coastguard Worker
3616*03f9172cSAndroid Build Coastguard Worker if (i >= wpa_s->sme.sa_query_count) {
3617*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
3618*03f9172cSAndroid Build Coastguard Worker "transaction identifier found");
3619*03f9172cSAndroid Build Coastguard Worker return;
3620*03f9172cSAndroid Build Coastguard Worker }
3621*03f9172cSAndroid Build Coastguard Worker
3622*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
3623*03f9172cSAndroid Build Coastguard Worker "from " MACSTR, MAC2STR(sa));
3624*03f9172cSAndroid Build Coastguard Worker sme_stop_sa_query(wpa_s);
3625*03f9172cSAndroid Build Coastguard Worker }
3626*03f9172cSAndroid Build Coastguard Worker
3627*03f9172cSAndroid Build Coastguard Worker
sme_sa_query_rx(struct wpa_supplicant * wpa_s,const u8 * da,const u8 * sa,const u8 * data,size_t len)3628*03f9172cSAndroid Build Coastguard Worker void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *da, const u8 *sa,
3629*03f9172cSAndroid Build Coastguard Worker const u8 *data, size_t len)
3630*03f9172cSAndroid Build Coastguard Worker {
3631*03f9172cSAndroid Build Coastguard Worker if (len < 1 + WLAN_SA_QUERY_TR_ID_LEN)
3632*03f9172cSAndroid Build Coastguard Worker return;
3633*03f9172cSAndroid Build Coastguard Worker if (is_multicast_ether_addr(da)) {
3634*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
3635*03f9172cSAndroid Build Coastguard Worker "IEEE 802.11: Ignore group-addressed SA Query frame (A1=" MACSTR " A2=" MACSTR ")",
3636*03f9172cSAndroid Build Coastguard Worker MAC2STR(da), MAC2STR(sa));
3637*03f9172cSAndroid Build Coastguard Worker return;
3638*03f9172cSAndroid Build Coastguard Worker }
3639*03f9172cSAndroid Build Coastguard Worker
3640*03f9172cSAndroid Build Coastguard Worker wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query frame from "
3641*03f9172cSAndroid Build Coastguard Worker MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
3642*03f9172cSAndroid Build Coastguard Worker
3643*03f9172cSAndroid Build Coastguard Worker #ifdef CONFIG_OCV
3644*03f9172cSAndroid Build Coastguard Worker if (wpa_sm_ocv_enabled(wpa_s->wpa)) {
3645*03f9172cSAndroid Build Coastguard Worker struct ieee802_11_elems elems;
3646*03f9172cSAndroid Build Coastguard Worker struct wpa_channel_info ci;
3647*03f9172cSAndroid Build Coastguard Worker
3648*03f9172cSAndroid Build Coastguard Worker if (ieee802_11_parse_elems(data + 1 + WLAN_SA_QUERY_TR_ID_LEN,
3649*03f9172cSAndroid Build Coastguard Worker len - 1 - WLAN_SA_QUERY_TR_ID_LEN,
3650*03f9172cSAndroid Build Coastguard Worker &elems, 1) == ParseFailed) {
3651*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_DEBUG,
3652*03f9172cSAndroid Build Coastguard Worker "SA Query: Failed to parse elements");
3653*03f9172cSAndroid Build Coastguard Worker return;
3654*03f9172cSAndroid Build Coastguard Worker }
3655*03f9172cSAndroid Build Coastguard Worker
3656*03f9172cSAndroid Build Coastguard Worker if (wpa_drv_channel_info(wpa_s, &ci) != 0) {
3657*03f9172cSAndroid Build Coastguard Worker wpa_printf(MSG_WARNING,
3658*03f9172cSAndroid Build Coastguard Worker "Failed to get channel info to validate received OCI in SA Query Action frame");
3659*03f9172cSAndroid Build Coastguard Worker return;
3660*03f9172cSAndroid Build Coastguard Worker }
3661*03f9172cSAndroid Build Coastguard Worker
3662*03f9172cSAndroid Build Coastguard Worker if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
3663*03f9172cSAndroid Build Coastguard Worker channel_width_to_int(ci.chanwidth),
3664*03f9172cSAndroid Build Coastguard Worker ci.seg1_idx) != OCI_SUCCESS) {
3665*03f9172cSAndroid Build Coastguard Worker wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR
3666*03f9172cSAndroid Build Coastguard Worker " frame=saquery%s error=%s",
3667*03f9172cSAndroid Build Coastguard Worker MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ?
3668*03f9172cSAndroid Build Coastguard Worker "req" : "resp", ocv_errorstr);
3669*03f9172cSAndroid Build Coastguard Worker return;
3670*03f9172cSAndroid Build Coastguard Worker }
3671*03f9172cSAndroid Build Coastguard Worker }
3672*03f9172cSAndroid Build Coastguard Worker #endif /* CONFIG_OCV */
3673*03f9172cSAndroid Build Coastguard Worker
3674*03f9172cSAndroid Build Coastguard Worker if (data[0] == WLAN_SA_QUERY_REQUEST)
3675*03f9172cSAndroid Build Coastguard Worker sme_process_sa_query_request(wpa_s, sa, data, len);
3676*03f9172cSAndroid Build Coastguard Worker else if (data[0] == WLAN_SA_QUERY_RESPONSE)
3677*03f9172cSAndroid Build Coastguard Worker sme_process_sa_query_response(wpa_s, sa, data, len);
3678*03f9172cSAndroid Build Coastguard Worker }
3679