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