1 /*
2  * SPDX-FileCopyrightText: 2019-2021 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 "rsn_supp/wpa.h"
10 #include "rsn_supp/wpa_i.h"
11 #include "common/eapol_common.h"
12 #include "common/ieee802_11_defs.h"
13 #include "rsn_supp/wpa_ie.h"
14 #include "ap/wpa_auth.h"
15 #include "ap/wpa_auth_i.h"
16 #include "ap/ap_config.h"
17 #include "ap/hostapd.h"
18 #include "esp_wpas_glue.h"
19 #include "esp_hostap.h"
20 
21 #include "esp_system.h"
22 #include "crypto/crypto.h"
23 #include "crypto/sha1.h"
24 #include "crypto/aes_wrap.h"
25 
26 #include "esp_wifi_driver.h"
27 #include "esp_private/wifi.h"
28 #include "esp_wpa3_i.h"
29 #include "esp_wpa2.h"
30 #include "esp_common_i.h"
31 
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)32 void  wpa_install_key(enum wpa_alg alg, u8 *addr, int key_idx, int set_tx,
33                       u8 *seq, size_t seq_len, u8 *key, size_t key_len, enum key_flag key_flag)
34 {
35     esp_wifi_set_sta_key_internal(alg, addr, key_idx, set_tx, seq, seq_len, key, key_len, key_flag);
36 }
37 
wpa_get_key(uint8_t * ifx,int * alg,u8 * addr,int * key_idx,u8 * key,size_t key_len,enum key_flag key_flag)38 int  wpa_get_key(uint8_t *ifx, int *alg, u8 *addr, int *key_idx,
39                  u8 *key, size_t key_len, enum key_flag key_flag)
40 {
41     return esp_wifi_get_sta_key_internal(ifx, alg, addr, key_idx, key, key_len, key_flag);
42 }
43 
44 /**
45  * eapol_sm_notify_eap_success - Notification of external EAP success trigger
46  * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init()
47  * @success: %TRUE = set success, %FALSE = clear success
48  *
49  * Notify the EAPOL state machine that external event has forced EAP state to
50  * success (success = %TRUE). This can be cleared by setting success = %FALSE.
51  *
52  * This function is called to update EAP state when WPA-PSK key handshake has
53  * been completed successfully since WPA-PSK does not use EAP state machine.
54  */
55 
56 /* fix buf for tx for now */
57 #define WPA_TX_MSG_BUFF_MAXLEN 200
58 
wpa_sendto_wrapper(void * buffer,u16 len)59 void  wpa_sendto_wrapper(void *buffer, u16 len)
60 {
61     esp_wifi_internal_tx(0, buffer, len);
62 }
63 
wpa_deauthenticate(u8 reason_code)64 void  wpa_deauthenticate(u8 reason_code)
65 {
66     esp_wifi_deauthenticate_internal(reason_code);
67 }
68 
wpa_config_profile(void)69 int  wpa_config_profile(void)
70 {
71     if (esp_wifi_sta_prof_is_wpa_internal()) {
72         wpa_set_profile(WPA_PROTO_WPA, esp_wifi_sta_get_prof_authmode_internal());
73     } else if (esp_wifi_sta_prof_is_wpa2_internal() || esp_wifi_sta_prof_is_wpa3_internal()) {
74         wpa_set_profile(WPA_PROTO_RSN, esp_wifi_sta_get_prof_authmode_internal());
75     } else if (esp_wifi_sta_prof_is_wapi_internal()) {
76         wpa_set_profile(WPA_PROTO_WAPI, esp_wifi_sta_get_prof_authmode_internal());
77     } else {
78         /* do nothing */
79         return -1;
80     }
81     return 0;
82 }
83 
wpa_config_bss(uint8_t * bssid)84 int wpa_config_bss(uint8_t *bssid)
85 {
86     int ret = 0;
87     struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal();
88     u8 mac[6];
89 
90     esp_wifi_get_macaddr_internal(0, mac);
91     ret = wpa_set_bss((char *)mac, (char *)bssid, esp_wifi_sta_get_pairwise_cipher_internal(), esp_wifi_sta_get_group_cipher_internal(),
92                 (char *)esp_wifi_sta_get_prof_password_internal(), ssid->ssid, ssid->len);
93     return ret;
94 }
95 
wpa_config_assoc_ie(u8 proto,u8 * assoc_buf,u32 assoc_wpa_ie_len)96 void  wpa_config_assoc_ie(u8 proto, u8 *assoc_buf, u32 assoc_wpa_ie_len)
97 {
98     if (proto == BIT(0)) {
99         esp_wifi_set_appie_internal(WIFI_APPIE_WPA, assoc_buf, assoc_wpa_ie_len, 1);
100     } else {
101         esp_wifi_set_appie_internal(WIFI_APPIE_RSN, assoc_buf, assoc_wpa_ie_len, 1);
102     }
103 }
104 
wpa_neg_complete(void)105 void  wpa_neg_complete(void)
106 {
107     esp_wifi_auth_done_internal();
108 }
109 
wpa_attach(void)110 bool  wpa_attach(void)
111 {
112     bool ret = true;
113     ret = wpa_sm_init(NULL, wpa_sendto_wrapper,
114                  wpa_config_assoc_ie, wpa_install_key, wpa_get_key, wpa_deauthenticate, wpa_neg_complete);
115     if(ret) {
116         ret = (esp_wifi_register_tx_cb_internal(eapol_txcb, WIFI_TXCB_EAPOL_ID) == ESP_OK);
117     }
118     esp_set_scan_ie();
119     esp_set_assoc_ie();
120     return ret;
121 }
122 
wpa_ap_get_wpa_ie(uint8_t * ie_len)123 uint8_t  *wpa_ap_get_wpa_ie(uint8_t *ie_len)
124 {
125     struct hostapd_data *hapd = (struct hostapd_data *)esp_wifi_get_hostap_private_internal();
126 
127     if (!hapd || !hapd->wpa_auth || !hapd->wpa_auth->wpa_ie) {
128         return NULL;
129     }
130 
131     *ie_len = hapd->wpa_auth->wpa_ie_len;
132     return hapd->wpa_auth->wpa_ie;
133 }
134 
wpa_ap_rx_eapol(void * hapd_data,void * sm_data,u8 * data,size_t data_len)135 bool  wpa_ap_rx_eapol(void *hapd_data, void *sm_data, u8 *data, size_t data_len)
136 {
137     struct hostapd_data *hapd = (struct hostapd_data *)hapd_data;
138     struct wpa_state_machine *sm = (struct wpa_state_machine *)sm_data;
139 
140     if (!hapd || !sm) {
141         return false;
142     }
143 
144     wpa_receive(hapd->wpa_auth, sm, data, data_len);
145 
146     return true;
147 }
148 
wpa_ap_get_peer_spp_msg(void * sm_data,bool * spp_cap,bool * spp_req)149 void wpa_ap_get_peer_spp_msg(void *sm_data, bool *spp_cap, bool *spp_req)
150 {
151     struct wpa_state_machine *sm = (struct wpa_state_machine *)sm_data;
152 
153     if (!sm) {
154         return;
155     }
156 
157     *spp_cap = sm->spp_sup.capable;
158     *spp_req = sm->spp_sup.require;
159 }
160 
wpa_deattach(void)161 bool  wpa_deattach(void)
162 {
163     // TODO: Implemente esp_wpa2.c
164     // esp_wifi_sta_wpa2_ent_disable();
165     wpa_sm_deinit();
166     return true;
167 }
168 
wpa_sta_connect(uint8_t * bssid)169 int wpa_sta_connect(uint8_t *bssid)
170 {
171     /* use this API to set AP specific IEs during connection */
172     int ret = 0;
173     ret = wpa_config_profile();
174     if (ret == 0) {
175         ret = wpa_config_bss(bssid);
176         if (ret) {
177             wpa_printf(MSG_DEBUG, "Rejecting bss, validation failed");
178             return ret;
179         }
180     }
181 
182     return 0;
183 }
184 
wpa_config_done(void)185 void wpa_config_done(void)
186 {
187     /* used in future for setting scan and assoc IEs */
188     esp_set_assoc_ie();
189 }
190 
wpa_parse_wpa_ie_wrapper(const u8 * wpa_ie,size_t wpa_ie_len,wifi_wpa_ie_t * data)191 int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data)
192 {
193     struct wpa_ie_data ie;
194     int ret = 0;
195 
196     ret = wpa_parse_wpa_ie(wpa_ie, wpa_ie_len, &ie);
197     data->proto = ie.proto;
198     data->pairwise_cipher = cipher_type_map_supp_to_public(ie.pairwise_cipher);
199     data->group_cipher = cipher_type_map_supp_to_public(ie.group_cipher);
200     data->key_mgmt = ie.key_mgmt;
201     data->capabilities = ie.capabilities;
202     data->pmkid = ie.pmkid;
203     data->mgmt_group_cipher = cipher_type_map_supp_to_public(ie.mgmt_group_cipher);
204 
205     return ret;
206 }
207 
wpa_sta_disconnected_cb(uint8_t reason_code)208 static void wpa_sta_disconnected_cb(uint8_t reason_code)
209 {
210     switch (reason_code) {
211         case WIFI_REASON_UNSPECIFIED:
212         case WIFI_REASON_AUTH_EXPIRE:
213         case WIFI_REASON_NOT_AUTHED:
214         case WIFI_REASON_NOT_ASSOCED:
215         case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT:
216         case WIFI_REASON_INVALID_PMKID:
217         case WIFI_REASON_AUTH_FAIL:
218         case WIFI_REASON_ASSOC_FAIL:
219         case WIFI_REASON_CONNECTION_FAIL:
220         case WIFI_REASON_HANDSHAKE_TIMEOUT:
221             esp_wpa3_free_sae_data();
222             wpa_sta_clear_curr_pmksa();
223             break;
224         default:
225             break;
226     }
227 }
228 
229 #ifndef ROAMING_SUPPORT
esp_supplicant_common_init(struct wpa_funcs * wpa_cb)230 static inline int esp_supplicant_common_init(struct wpa_funcs *wpa_cb)
231 {
232 	wpa_cb->wpa_sta_rx_mgmt = NULL;
233 	wpa_cb->wpa_sta_profile_match = NULL;
234 
235 	return 0;
236 }
esp_supplicant_common_deinit(void)237 static inline void esp_supplicant_common_deinit(void)
238 {
239 }
240 #endif
241 
esp_supplicant_init(void)242 int esp_supplicant_init(void)
243 {
244     int ret = ESP_OK;
245     struct wpa_funcs *wpa_cb;
246 
247     wpa_cb = (struct wpa_funcs *)os_zalloc(sizeof(struct wpa_funcs));
248     if (!wpa_cb) {
249         return ESP_ERR_NO_MEM;
250     }
251 
252     wpa_cb->wpa_sta_init       = wpa_attach;
253     wpa_cb->wpa_sta_deinit     = wpa_deattach;
254     wpa_cb->wpa_sta_rx_eapol   = wpa_sm_rx_eapol;
255     wpa_cb->wpa_sta_connect    = wpa_sta_connect;
256     wpa_cb->wpa_sta_disconnected_cb = wpa_sta_disconnected_cb;
257     wpa_cb->wpa_sta_in_4way_handshake = wpa_sta_in_4way_handshake;
258 
259 #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
260     wpa_cb->wpa_ap_join       = wpa_ap_join;
261     wpa_cb->wpa_ap_remove     = wpa_ap_remove;
262     wpa_cb->wpa_ap_get_wpa_ie = wpa_ap_get_wpa_ie;
263     wpa_cb->wpa_ap_rx_eapol   = wpa_ap_rx_eapol;
264     wpa_cb->wpa_ap_get_peer_spp_msg  = wpa_ap_get_peer_spp_msg;
265     wpa_cb->wpa_ap_init       = hostap_init;
266     wpa_cb->wpa_ap_deinit     = hostap_deinit;
267 #endif
268 
269     wpa_cb->wpa_config_parse_string  = wpa_config_parse_string;
270     wpa_cb->wpa_parse_wpa_ie  = wpa_parse_wpa_ie_wrapper;
271     wpa_cb->wpa_config_bss = NULL;//wpa_config_bss;
272     wpa_cb->wpa_michael_mic_failure = wpa_michael_mic_failure;
273     wpa_cb->wpa_config_done = wpa_config_done;
274 
275     esp_wifi_register_wpa3_cb(wpa_cb);
276     ret = esp_supplicant_common_init(wpa_cb);
277 
278     if (ret != 0) {
279         return ret;
280     }
281 
282     esp_wifi_register_wpa_cb_internal(wpa_cb);
283 
284 #if CONFIG_WPA_WAPI_PSK
285     ret =  esp_wifi_internal_wapi_init();
286 #endif
287 
288     return ret;
289 }
290 
esp_supplicant_deinit(void)291 int esp_supplicant_deinit(void)
292 {
293     esp_supplicant_common_deinit();
294     return esp_wifi_unregister_wpa_cb_internal();
295 }
296