1 /*
2 * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "utils/includes.h"
8 #include "utils/common.h"
9 #include "utils/eloop.h"
10 #include "rsn_supp/wpa.h"
11 #include "rsn_supp/wpa_i.h"
12 #include "common/eapol_common.h"
13 #include "common/ieee802_11_defs.h"
14 #include "common/ieee802_11_common.h"
15 #include "rsn_supp/wpa_ie.h"
16 #include "ap/wpa_auth.h"
17 #include "ap/wpa_auth_i.h"
18 #include "ap/ap_config.h"
19 #include "ap/hostapd.h"
20 #include "esp_wpas_glue.h"
21 #include "esp_hostap.h"
22
23 #include "esp_system.h"
24 #include "crypto/crypto.h"
25 #include "crypto/sha1.h"
26 #include "crypto/aes_wrap.h"
27
28 #include "esp_wifi_driver.h"
29 #include "esp_private/wifi.h"
30 #include "esp_wpa3_i.h"
31 #include "esp_eap_client.h"
32 #include "esp_common_i.h"
33 #include "esp_owe_i.h"
34
35 #include "esp_wps.h"
36 #include "esp_wps_i.h"
37 #include "eap_server/eap.h"
38 #include "eapol_auth/eapol_auth_sm.h"
39 #include "ap/ieee802_1x.h"
40 #include "ap/sta_info.h"
41 #include "wps/wps_defs.h"
42 #include "wps/wps.h"
43
44 #include "zephyr_compat.h"
45 bool g_wpa_pmk_caching_disabled = 0;
46
47 const wifi_osi_funcs_t *wifi_funcs;
48 struct wpa_funcs *wpa_cb;
49
wpa_install_key(enum wpa_alg alg,u8 * addr,int key_idx,int set_tx,u8 * seq,size_t seq_len,u8 * key,size_t key_len,enum key_flag key_flag)50 void wpa_install_key(enum wpa_alg alg, u8 *addr, int key_idx, int set_tx,
51 u8 *seq, size_t seq_len, u8 *key, size_t key_len, enum key_flag key_flag)
52 {
53 esp_wifi_set_sta_key_internal(alg, addr, key_idx, set_tx, seq, seq_len, key, key_len, key_flag);
54 }
55
wpa_get_key(uint8_t * ifx,int * alg,u8 * addr,int * key_idx,u8 * key,size_t key_len,enum key_flag key_flag)56 int wpa_get_key(uint8_t *ifx, int *alg, u8 *addr, int *key_idx,
57 u8 *key, size_t key_len, enum key_flag key_flag)
58 {
59 return esp_wifi_get_sta_key_internal(ifx, alg, addr, key_idx, key, key_len, key_flag);
60 }
61
62 /**
63 * eapol_sm_notify_eap_success - Notification of external EAP success trigger
64 * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
65 * @success: %TRUE = set success, %FALSE = clear success
66 *
67 * Notify the EAPOL state machine that external event has forced EAP state to
68 * success (success = %TRUE). This can be cleared by setting success = %FALSE.
69 *
70 * This function is called to update EAP state when WPA-PSK key handshake has
71 * been completed successfully since WPA-PSK does not use EAP state machine.
72 */
73
74 /* fix buf for tx for now */
75 #define WPA_TX_MSG_BUFF_MAXLEN 200
76
wpa_sendto_wrapper(void * buffer,u16 len)77 void wpa_sendto_wrapper(void *buffer, u16 len)
78 {
79 esp_wifi_internal_tx(0, buffer, len);
80 }
81
wpa_deauthenticate(u8 reason_code)82 void wpa_deauthenticate(u8 reason_code)
83 {
84 esp_wifi_deauthenticate_internal(reason_code);
85 }
86
wpa_config_profile(uint8_t * bssid)87 int wpa_config_profile(uint8_t *bssid)
88 {
89 int ret = 0;
90
91 if (esp_wifi_sta_prof_is_wpa_internal()) {
92 wpa_set_profile(WPA_PROTO_WPA, esp_wifi_sta_get_prof_authmode_internal());
93 } else if (esp_wifi_sta_prof_is_rsn_internal()) {
94 wpa_set_profile(WPA_PROTO_RSN, esp_wifi_sta_get_prof_authmode_internal());
95 } else if (esp_wifi_sta_prof_is_wapi_internal()) {
96 wpa_set_profile(WPA_PROTO_WAPI, esp_wifi_sta_get_prof_authmode_internal());
97 } else {
98 ret = -1;
99 }
100
101 return ret;
102 }
103
wpa_config_bss(uint8_t * bssid)104 int wpa_config_bss(uint8_t *bssid)
105 {
106 int ret = 0;
107 struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal();
108 u8 mac[6];
109
110 esp_wifi_get_macaddr_internal(0, mac);
111 ret = wpa_set_bss((char *)mac, (char *)bssid, esp_wifi_sta_get_pairwise_cipher_internal(), esp_wifi_sta_get_group_cipher_internal(),
112 (char *)esp_wifi_sta_get_prof_password_internal(), ssid->ssid, ssid->len);
113 return ret;
114 }
115
wpa_config_assoc_ie(u8 proto,u8 * assoc_buf,u32 assoc_wpa_ie_len)116 void wpa_config_assoc_ie(u8 proto, u8 *assoc_buf, u32 assoc_wpa_ie_len)
117 {
118 if (proto == BIT(0)) {
119 esp_wifi_set_appie_internal(WIFI_APPIE_WPA, assoc_buf, assoc_wpa_ie_len, 1);
120 } else {
121 esp_wifi_set_appie_internal(WIFI_APPIE_RSN, assoc_buf, assoc_wpa_ie_len, 1);
122 }
123 }
124
wpa_neg_complete(void)125 void wpa_neg_complete(void)
126 {
127 esp_wifi_auth_done_internal();
128 }
129
wpa_attach(void)130 bool wpa_attach(void)
131 {
132 bool ret = true;
133 ret = wpa_sm_init();
134 if(ret) {
135 ret = (esp_wifi_register_eapol_txdonecb_internal(eapol_txcb) == ESP_OK);
136 }
137 esp_set_scan_ie();
138 return ret;
139 }
140
wpa_ap_get_wpa_ie(uint8_t * ie_len)141 uint8_t *wpa_ap_get_wpa_ie(uint8_t *ie_len)
142 {
143 struct hostapd_data *hapd = (struct hostapd_data *)esp_wifi_get_hostap_private_internal();
144
145 if (!hapd || !hapd->wpa_auth || !hapd->wpa_auth->wpa_ie) {
146 return NULL;
147 }
148
149 *ie_len = hapd->wpa_auth->wpa_ie_len;
150 return hapd->wpa_auth->wpa_ie;
151 }
152
wpa_ap_rx_eapol(void * hapd_data,void * sm_data,u8 * data,size_t data_len)153 bool wpa_ap_rx_eapol(void *hapd_data, void *sm_data, u8 *data, size_t data_len)
154 {
155 struct hostapd_data *hapd = (struct hostapd_data *)hapd_data;
156 struct sta_info *sta = (struct sta_info *)sm_data;
157 if (!hapd || !sta) {
158 wpa_printf(MSG_DEBUG, "hapd=%p sta=%p", hapd, sta);
159 return false;
160 }
161 #ifdef CONFIG_WPS_REGISTRAR
162 int wps_type = esp_wifi_get_wps_type_internal();
163
164 if ((wps_type == WPS_TYPE_PBC) ||
165 (wps_type == WPS_TYPE_PIN)) {
166 ieee802_1x_receive(hapd, sta->addr, data, data_len);
167 return true;
168 }
169 #endif
170 wpa_receive(hapd->wpa_auth, sta->wpa_sm, data, data_len);
171
172 return true;
173 }
174
wpa_ap_get_peer_spp_msg(void * sm_data,bool * spp_cap,bool * spp_req)175 void wpa_ap_get_peer_spp_msg(void *sm_data, bool *spp_cap, bool *spp_req)
176 {
177 struct sta_info *sta = sm_data;
178
179 if (!sta || !sta->wpa_sm) {
180 return;
181 }
182
183 *spp_cap = sta->wpa_sm->spp_sup.capable;
184 *spp_req = sta->wpa_sm->spp_sup.require;
185 }
186
wpa_deattach(void)187 bool wpa_deattach(void)
188 {
189 struct wpa_sm *sm = &gWpaSm;
190 esp_wpa3_free_sae_data();
191 #ifdef CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT
192 if (sm->wpa_sm_eap_disable) {
193 sm->wpa_sm_eap_disable();
194 }
195 #endif
196 if (sm->wpa_sm_wps_disable) {
197 sm->wpa_sm_wps_disable();
198 }
199 esp_wifi_register_eapol_txdonecb_internal(NULL);
200
201 wpa_sm_deinit();
202 return true;
203 }
204
wpa_sta_connect(uint8_t * bssid)205 int wpa_sta_connect(uint8_t *bssid)
206 {
207 /* use this API to set AP specific IEs during connection */
208 int ret = 0;
209 ret = wpa_config_profile(bssid);
210 if (ret == 0) {
211 ret = wpa_config_bss(bssid);
212 if (ret) {
213 wpa_printf(MSG_DEBUG, "Rejecting bss, validation failed");
214 return ret;
215 }
216 } else if (esp_wifi_sta_get_prof_authmode_internal() == NONE_AUTH) {
217 esp_set_assoc_ie((uint8_t *)bssid, NULL, 0, false);
218 }
219
220 ret = esp_wifi_sta_connect_internal(bssid);
221 return ret;
222 }
223
wpa_config_done(void)224 void wpa_config_done(void)
225 {
226 esp_set_scan_ie();
227 }
228
wpa_parse_wpa_ie_wrapper(const u8 * wpa_ie,size_t wpa_ie_len,wifi_wpa_ie_t * data)229 int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data)
230 {
231 struct wpa_ie_data ie;
232 int ret = 0;
233
234 ret = wpa_parse_wpa_ie(wpa_ie, wpa_ie_len, &ie);
235 data->proto = ie.proto;
236 data->pairwise_cipher = cipher_type_map_supp_to_public(ie.pairwise_cipher);
237 data->group_cipher = cipher_type_map_supp_to_public(ie.group_cipher);
238 data->key_mgmt = ie.key_mgmt;
239 data->capabilities = ie.capabilities;
240 data->pmkid = ie.pmkid;
241 data->mgmt_group_cipher = cipher_type_map_supp_to_public(ie.mgmt_group_cipher);
242 data->rsnxe_capa = ie.rsnxe_capa;
243
244 return ret;
245 }
246
wpa_sta_connected_cb(uint8_t * bssid)247 static void wpa_sta_connected_cb(uint8_t *bssid)
248 {
249 supplicant_sta_conn_handler(bssid);
250 }
251
wpa_sta_disconnected_cb(uint8_t reason_code)252 static void wpa_sta_disconnected_cb(uint8_t reason_code)
253 {
254 switch (reason_code) {
255 case WIFI_REASON_AUTH_EXPIRE:
256 case WIFI_REASON_CLASS2_FRAME_FROM_NONAUTH_STA:
257 case WIFI_REASON_CLASS3_FRAME_FROM_NONASSOC_STA:
258 case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
259 case WIFI_REASON_INVALID_PMKID:
260 case WIFI_REASON_AUTH_FAIL:
261 case WIFI_REASON_ASSOC_FAIL:
262 case WIFI_REASON_CONNECTION_FAIL:
263 case WIFI_REASON_HANDSHAKE_TIMEOUT:
264 wpa_sta_clear_curr_pmksa();
265 wpa_sm_notify_disassoc(&gWpaSm);
266 break;
267 default:
268 if (g_wpa_pmk_caching_disabled) {
269 wpa_sta_clear_curr_pmksa();
270 }
271 break;
272 }
273
274 struct wps_sm_funcs *wps_sm_cb = wps_get_wps_sm_cb();
275 if (wps_sm_cb && wps_sm_cb->wps_sm_notify_deauth) {
276 wps_sm_cb->wps_sm_notify_deauth();
277 }
278
279 #ifdef CONFIG_OWE_STA
280 owe_deinit();
281 #endif /* CONFIG_OWE_STA */
282
283 esp_wpa3_free_sae_data();
284 supplicant_sta_disconn_handler();
285 }
286
287 #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
288
289 #ifdef CONFIG_WPS_REGISTRAR
check_n_add_wps_sta(struct hostapd_data * hapd,struct sta_info * sta_info,u8 * ies,u8 ies_len,bool * pmf_enable,int subtype)290 static int check_n_add_wps_sta(struct hostapd_data *hapd, struct sta_info *sta_info, u8 *ies, u8 ies_len, bool *pmf_enable, int subtype)
291 {
292 struct wpabuf *wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, WPS_DEV_OUI_WFA);
293 int wps_type = esp_wifi_get_wps_type_internal();
294
295 /* Condition for this, WPS is running and WPS IEs are part of assoc req */
296 if (!wps_ie || (wps_type == WPS_TYPE_DISABLE)) {
297 return 0;
298 }
299
300 if (wps_type == WPS_TYPE_PBC) {
301 if (esp_wps_registrar_check_pbc_overlap(hapd->wps)) {
302 wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected");
303 return -1;
304 }
305 }
306
307 sta_info->wps_ie = wps_ie;
308 sta_info->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta_info);
309
310 if (sta_info->eapol_sm) {
311 wpa_printf(MSG_DEBUG, "considering station " MACSTR " for WPS", MAC2STR(sta_info->addr));
312 if (esp_send_assoc_resp(hapd, sta_info->addr, WLAN_STATUS_SUCCESS, true, subtype) != WLAN_STATUS_SUCCESS) {
313 wpa_printf(MSG_ERROR, "failed to send assoc response " MACSTR, MAC2STR(sta_info->addr));
314 return -1;
315 }
316 }
317
318 return 0;
319 }
320 #endif
321
hostap_sta_join(void ** sta,u8 * bssid,u8 * wpa_ie,u8 wpa_ie_len,u8 * rsnxe,u8 rsnxe_len,bool * pmf_enable,int subtype,uint8_t * pairwise_cipher)322 static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8 *rsnxe, u8 rsnxe_len, bool *pmf_enable, int subtype, uint8_t *pairwise_cipher)
323 {
324 struct sta_info *sta_info = NULL;
325 struct hostapd_data *hapd = hostapd_get_hapd_data();
326 uint8_t reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
327
328 if (!hapd) {
329 goto fail;
330 }
331
332 if (*sta) {
333 struct sta_info *old_sta = *sta;
334 #ifdef CONFIG_SAE
335 if (old_sta->lock && os_semphr_take(old_sta->lock, 0) != TRUE) {
336 wpa_printf(MSG_INFO, "Ignore assoc request as softap is busy with sae calculation for station "MACSTR, MAC2STR(bssid));
337 if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) {
338 goto fail;
339 }
340 return false;
341 }
342 #endif /* CONFIG_SAE */
343 if (!esp_wifi_ap_is_sta_sae_reauth_node(bssid)) {
344 ap_free_sta(hapd, old_sta);
345 *sta = NULL;
346 }
347 #ifdef CONFIG_SAE
348 else if (old_sta && old_sta->lock) {
349 sta_info = old_sta;
350 goto process_old_sta;
351 }
352 #endif /* CONFIG_SAE */
353 }
354
355 sta_info = ap_get_sta(hapd, bssid);
356 if (!sta_info) {
357 sta_info = ap_sta_add(hapd,bssid);
358 if (!sta_info) {
359 wpa_printf(MSG_ERROR, "failed to add station " MACSTR, MAC2STR(bssid));
360 goto fail;
361 }
362 }
363 #ifdef CONFIG_SAE
364 if (sta_info->lock && os_semphr_take(sta_info->lock, 0) != TRUE) {
365 wpa_printf(MSG_INFO, "Ignore assoc request as softap is busy with sae calculation for station "MACSTR, MAC2STR(bssid));
366 if (esp_send_assoc_resp(hapd, bssid, WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY, rsnxe ? false : true, subtype) != WLAN_STATUS_SUCCESS) {
367 goto fail;
368 }
369 return false;
370 }
371
372 process_old_sta:
373 #endif /* CONFIG_SAE */
374
375
376 #ifdef CONFIG_WPS_REGISTRAR
377 if (check_n_add_wps_sta(hapd, sta_info, wpa_ie, wpa_ie_len, pmf_enable, subtype) == 0) {
378 if (sta_info->eapol_sm) {
379 goto done;
380 }
381 } else {
382 goto fail;
383 }
384 #endif
385 if (hostap_new_assoc_sta(sta_info, bssid, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len, pmf_enable, subtype, pairwise_cipher, &reason)) {
386 goto done;
387 } else {
388 goto fail;
389 }
390 done:
391 *sta = sta_info;
392 #ifdef CONFIG_SAE
393 if (sta_info->lock) {
394 os_semphr_give(sta_info->lock);
395 }
396 #endif /* CONFIG_SAE */
397 return true;
398
399 fail:
400
401 #ifdef CONFIG_SAE
402 if (sta_info && sta_info->lock) {
403 os_semphr_give(sta_info->lock);
404 }
405 #endif /* CONFIG_SAE */
406 esp_wifi_ap_deauth_internal(bssid, reason);
407 return false;
408 }
409 #endif
410
esp_supplicant_init(void)411 int esp_supplicant_init(void)
412 {
413 int ret = ESP_OK;
414
415 wifi_funcs = WIFI_OSI_FUNCS_INITIALIZER();
416 if (!wifi_funcs) {
417 return ESP_ERR_NOT_FOUND;
418 }
419 wpa_cb = (struct wpa_funcs *)os_zalloc(sizeof(struct wpa_funcs));
420 if (!wpa_cb) {
421 return ESP_ERR_NO_MEM;
422 }
423
424 wpa_cb->wpa_sta_init = wpa_attach;
425 wpa_cb->wpa_sta_deinit = wpa_deattach;
426 wpa_cb->wpa_sta_rx_eapol = wpa_sm_rx_eapol;
427 wpa_cb->wpa_sta_connect = wpa_sta_connect;
428 wpa_cb->wpa_sta_connected_cb = wpa_sta_connected_cb;
429 wpa_cb->wpa_sta_disconnected_cb = wpa_sta_disconnected_cb;
430 wpa_cb->wpa_sta_in_4way_handshake = wpa_sta_in_4way_handshake;
431
432 #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
433 wpa_cb->wpa_ap_join = hostap_sta_join;
434 wpa_cb->wpa_ap_remove = wpa_ap_remove;
435 wpa_cb->wpa_ap_get_wpa_ie = wpa_ap_get_wpa_ie;
436 wpa_cb->wpa_ap_rx_eapol = wpa_ap_rx_eapol;
437 wpa_cb->wpa_ap_get_peer_spp_msg = wpa_ap_get_peer_spp_msg;
438 wpa_cb->wpa_ap_init = hostap_init;
439 wpa_cb->wpa_ap_deinit = hostap_deinit;
440 #endif
441
442 wpa_cb->wpa_config_parse_string = wpa_config_parse_string;
443 wpa_cb->wpa_parse_wpa_ie = wpa_parse_wpa_ie_wrapper;
444 wpa_cb->wpa_config_bss = NULL;//wpa_config_bss;
445 wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure;
446 wpa_cb->wpa_config_done = wpa_config_done;
447 wpa_cb->wpa_sta_clear_curr_pmksa = wpa_sta_clear_curr_pmksa;
448
449 esp_wifi_register_wpa3_ap_cb(wpa_cb);
450 esp_wifi_register_wpa3_cb(wpa_cb);
451 #ifdef CONFIG_OWE_STA
452 esp_wifi_register_owe_cb(wpa_cb);
453 #endif /* CONFIG_OWE_STA */
454 eloop_init();
455 ret = esp_supplicant_common_init(wpa_cb);
456
457 if (ret != 0) {
458 return ret;
459 }
460
461 esp_wifi_register_wpa_cb_internal(wpa_cb);
462
463 #if CONFIG_ESP_WIFI_WAPI_PSK
464 ret = esp_wifi_internal_wapi_init();
465 #endif
466
467 return ret;
468 }
469
esp_supplicant_deinit(void)470 int esp_supplicant_deinit(void)
471 {
472 esp_supplicant_common_deinit();
473 esp_supplicant_unset_all_appie();
474 eloop_destroy();
475 wpa_cb = NULL;
476 #if CONFIG_ESP_WIFI_WAPI_PSK
477 esp_wifi_internal_wapi_deinit();
478 #endif
479 return esp_wifi_unregister_wpa_cb_internal();
480 }
481
esp_supplicant_disable_pmk_caching(bool disable)482 esp_err_t esp_supplicant_disable_pmk_caching(bool disable)
483 {
484 g_wpa_pmk_caching_disabled = disable;
485 return ESP_OK;
486 }
487