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