1 /*
2 * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #ifdef CONFIG_WPA3_SAE
7
8 #include "common/sae.h"
9 #include "common/ieee802_11_defs.h"
10 #include "esp_wifi_driver.h"
11 #include "rsn_supp/wpa.h"
12 #include "ap/hostapd.h"
13 #include "ap/ieee802_11.h"
14 #include "ap/sta_info.h"
15 #include "esp_wpa3_i.h"
16 #include "endian.h"
17 #include "esp_hostap.h"
18 #include <inttypes.h>
19 #include <zephyr/kernel.h>
20 static struct sae_pt *g_sae_pt;
21 static struct sae_data g_sae_data;
22 static struct wpabuf *g_sae_token = NULL;
23 static struct wpabuf *g_sae_commit = NULL;
24 static struct wpabuf *g_sae_confirm = NULL;
25 int g_allowed_groups[] = { IANA_SECP256R1, 0 };
26
wpa3_build_sae_commit(u8 * bssid,size_t * sae_msg_len)27 static esp_err_t wpa3_build_sae_commit(u8 *bssid, size_t *sae_msg_len)
28 {
29 int default_group = IANA_SECP256R1;
30 u32 len = 0;
31 uint8_t use_pt = 0;
32 u8 own_addr[ETH_ALEN];
33 const u8 *pw = (const u8 *)esp_wifi_sta_get_prof_password_internal();
34 struct wifi_ssid *ssid = esp_wifi_sta_get_prof_ssid_internal();
35 uint8_t sae_pwe = esp_wifi_get_config_sae_pwe_h2e_internal(WIFI_IF_STA);
36 char sae_pwd_id[SAE_H2E_IDENTIFIER_LEN+1] = {0};
37 bool valid_pwd_id = false;
38 const u8 *rsnxe;
39 u8 rsnxe_capa = 0;
40
41 rsnxe = esp_wifi_sta_get_rsnxe(bssid);
42 if (rsnxe && rsnxe[1] >= 1) {
43 rsnxe_capa = rsnxe[2];
44 }
45
46 #ifdef CONFIG_SAE_PK
47 bool use_pk = false;
48 uint8_t sae_pk_mode = esp_wifi_sta_get_config_sae_pk_internal();
49
50 if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) &&
51 sae_pk_mode != WPA3_SAE_PK_MODE_DISABLED &&
52 ((pw && sae_pk_valid_password((const char*)pw)))) {
53 use_pt = 1;
54 use_pk = true;
55 }
56
57 if (sae_pk_mode == WPA3_SAE_PK_MODE_ONLY && !use_pk) {
58 wpa_printf(MSG_DEBUG,
59 "SAE: Cannot use PK with the selected AP");
60 return ESP_FAIL;
61 }
62 #endif /* CONFIG_SAE_PK */
63 if (use_pt || sae_pwe == SAE_PWE_HASH_TO_ELEMENT ||
64 sae_pwe == SAE_PWE_BOTH) {
65 use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E));
66
67 if ((sae_pwe == SAE_PWE_HASH_TO_ELEMENT
68 #ifdef CONFIG_SAE_PK
69 || (use_pk && sae_pk_mode == WPA3_SAE_PK_MODE_ONLY)
70 #endif /* CONFIG_SAE_PK */
71 ) && !use_pt) {
72 wpa_printf(MSG_DEBUG,
73 "SAE: Cannot use H2E with the selected AP");
74 return ESP_FAIL;
75 }
76 }
77
78
79 if (use_pt != 0) {
80 memcpy(sae_pwd_id, esp_wifi_sta_get_sae_identifier_internal(), SAE_H2E_IDENTIFIER_LEN);
81 if (os_strlen(sae_pwd_id) > 0) {
82 valid_pwd_id = true;
83 }
84 }
85
86 if (use_pt && !g_sae_pt) {
87 g_sae_pt = sae_derive_pt(g_allowed_groups, ssid->ssid, ssid->len, pw, strlen((const char *)pw), valid_pwd_id ? sae_pwd_id : NULL);
88 }
89
90 if (wpa_sta_cur_pmksa_matches_akm()) {
91 wpa_printf(MSG_INFO, "wpa3: Skip SAE and use cached PMK instead");
92 *sae_msg_len = 0;
93 return ESP_FAIL;
94 }
95
96 if (g_sae_commit) {
97 wpabuf_free(g_sae_commit);
98 g_sae_commit = NULL;
99 }
100
101 if (g_sae_token) {
102 len = wpabuf_len(g_sae_token);
103 goto reuse_data;
104 }
105
106 memset(&g_sae_data, 0, sizeof(g_sae_data));
107 if (sae_set_group(&g_sae_data, default_group)) {
108 wpa_printf(MSG_ERROR, "wpa3: could not set SAE group %d", default_group);
109 return ESP_FAIL;
110 }
111
112 esp_wifi_get_macaddr_internal(WIFI_IF_STA, own_addr);
113 if (!bssid) {
114 wpa_printf(MSG_ERROR, "wpa3: cannot prepare SAE commit with no BSSID!");
115 return ESP_FAIL;
116 }
117
118 if (use_pt &&
119 sae_prepare_commit_pt(&g_sae_data, g_sae_pt,
120 own_addr, bssid, NULL, NULL) < 0) {
121 wpa_printf(MSG_ERROR, "wpa3: failed to prepare SAE commit!");
122 return ESP_FAIL;
123 }
124 if (!use_pt &&
125 sae_prepare_commit(own_addr, bssid, pw,
126 strlen((const char *)pw),
127 &g_sae_data) < 0) {
128 wpa_printf(MSG_ERROR, "wpa3: failed to prepare SAE commit!");
129 return ESP_FAIL;
130 }
131
132 #ifdef CONFIG_SAE_PK
133 if (g_sae_data.tmp && use_pt && use_pk) {
134 g_sae_data.pk = 1;
135 os_memcpy(g_sae_data.tmp->own_addr,own_addr, ETH_ALEN );
136 os_memcpy(g_sae_data.tmp->peer_addr, bssid, ETH_ALEN);
137 sae_pk_set_password(&g_sae_data,(const char*) pw);
138 }
139 #endif
140
141 reuse_data:
142 len += SAE_COMMIT_MAX_LEN;
143 g_sae_commit = wpabuf_alloc(len);
144 if (!g_sae_commit) {
145 wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for commit msg");
146 return ESP_FAIL;
147 }
148
149 if (sae_write_commit(&g_sae_data, g_sae_commit, g_sae_token, valid_pwd_id ? sae_pwd_id : NULL) != ESP_OK) {
150 wpa_printf(MSG_ERROR, "wpa3: failed to write SAE commit msg");
151 wpabuf_free(g_sae_commit);
152 g_sae_commit = NULL;
153 return ESP_FAIL;
154 }
155
156 if (g_sae_token) {
157 wpabuf_free(g_sae_token);
158 g_sae_token = NULL;
159 }
160 g_sae_data.state = SAE_COMMITTED;
161
162 return ESP_OK;
163 }
164
wpa3_build_sae_confirm(void)165 static esp_err_t wpa3_build_sae_confirm(void)
166 {
167 if (g_sae_data.state != SAE_COMMITTED)
168 return ESP_FAIL;
169
170 if (g_sae_confirm) {
171 wpabuf_free(g_sae_confirm);
172 g_sae_confirm = NULL;
173 }
174
175 g_sae_confirm = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
176 if (!g_sae_confirm) {
177 wpa_printf(MSG_ERROR, "wpa3: failed to allocate buffer for confirm msg");
178 return ESP_FAIL;
179 }
180
181 if (sae_write_confirm(&g_sae_data, g_sae_confirm) != ESP_OK) {
182 wpa_printf(MSG_ERROR, "wpa3: failed to write SAE confirm msg");
183 wpabuf_free(g_sae_confirm);
184 g_sae_confirm = NULL;
185 return ESP_FAIL;
186 }
187 g_sae_data.state = SAE_CONFIRMED;
188
189 return ESP_OK;
190 }
191
esp_wpa3_free_sae_data(void)192 void esp_wpa3_free_sae_data(void)
193 {
194 if (g_sae_commit) {
195 wpabuf_free(g_sae_commit);
196 g_sae_commit = NULL;
197 }
198
199 if (g_sae_confirm) {
200 wpabuf_free(g_sae_confirm);
201 g_sae_confirm = NULL;
202 }
203 sae_clear_data(&g_sae_data);
204 if (g_sae_pt) {
205 sae_deinit_pt(g_sae_pt);
206 g_sae_pt = NULL;
207 }
208 }
209
wpa3_build_sae_msg(u8 * bssid,u32 sae_msg_type,size_t * sae_msg_len)210 static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, size_t *sae_msg_len)
211 {
212 u8 *buf = NULL;
213
214 switch (sae_msg_type) {
215 case SAE_MSG_COMMIT:
216 /* Do not go for SAE when WPS is ongoing */
217 if (esp_wifi_get_wps_status_internal() != WPS_STATUS_DISABLE) {
218 *sae_msg_len = 0;
219 return NULL;
220 }
221 if (ESP_OK != wpa3_build_sae_commit(bssid, sae_msg_len))
222 return NULL;
223 *sae_msg_len = wpabuf_len(g_sae_commit);
224 buf = wpabuf_mhead_u8(g_sae_commit);
225 break;
226 case SAE_MSG_CONFIRM:
227 if (ESP_OK != wpa3_build_sae_confirm())
228 return NULL;
229 *sae_msg_len = wpabuf_len(g_sae_confirm);
230 buf = wpabuf_mhead_u8(g_sae_confirm);
231 break;
232 default:
233 break;
234 }
235
236 return buf;
237 }
238
wpa3_sae_is_group_enabled(int group)239 static int wpa3_sae_is_group_enabled(int group)
240 {
241 int *groups = NULL;
242 int default_groups[] = { 19, 0 };
243 int i;
244
245 if (!groups) {
246 groups = default_groups;
247 }
248
249 for (i = 0; groups[i] > 0; i++) {
250 if (groups[i] == group) {
251 return 1;
252 }
253 }
254
255 return 0;
256 }
257
wpa3_check_sae_rejected_groups(const struct wpabuf * groups)258 static int wpa3_check_sae_rejected_groups(const struct wpabuf *groups)
259 {
260 size_t i, count, len;
261 const u8 *pos;
262
263 if (!groups) {
264 return 0;
265 }
266
267 pos = wpabuf_head(groups);
268 len = wpabuf_len(groups);
269 if (len & 1) {
270 wpa_printf(MSG_DEBUG,
271 "SAE: Invalid length of the Rejected Groups element payload: %zu",
272 len);
273 return 1;
274 }
275 count = len / 2;
276 for (i = 0; i < count; i++) {
277 int enabled;
278 u16 group;
279
280 group = WPA_GET_LE16(pos);
281 pos += 2;
282 enabled = wpa3_sae_is_group_enabled(group);
283 wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
284 group, enabled ? "enabled" : "disabled");
285 if (enabled) {
286 return 1;
287 }
288 }
289
290 return 0;
291 }
292
wpa3_parse_sae_commit(u8 * buf,u32 len,u16 status)293 static int wpa3_parse_sae_commit(u8 *buf, u32 len, u16 status)
294 {
295 int ret;
296
297 if (g_sae_data.state != SAE_COMMITTED) {
298 wpa_printf(MSG_DEBUG, "wpa3: Discarding commit frame received in state %d", g_sae_data.state);
299 return ESP_ERR_WIFI_DISCARD;
300 }
301
302 if (status == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ) {
303 if (g_sae_token)
304 wpabuf_free(g_sae_token);
305 if (g_sae_data.h2e) {
306 if ((buf[2] != WLAN_EID_EXTENSION) ||
307 (buf[3] == 0) ||
308 (buf[3] > len - 4) ||
309 (buf[4] != WLAN_EID_EXT_ANTI_CLOGGING_TOKEN)) {
310 wpa_printf(MSG_ERROR, "Invalid SAE anti-clogging token container header");
311 return ESP_FAIL;
312 }
313 g_sae_token = wpabuf_alloc_copy(buf + 5, len - 5);
314 } else {
315 g_sae_token = wpabuf_alloc_copy(buf + 2, len - 2);
316 }
317 return ESP_OK;
318 }
319
320 ret = sae_parse_commit(&g_sae_data, buf, len, NULL, 0, g_allowed_groups,
321 (status == WLAN_STATUS_SAE_HASH_TO_ELEMENT || status == WLAN_STATUS_SAE_PK));
322 if (ret == SAE_SILENTLY_DISCARD) {
323 wpa_printf(MSG_DEBUG, "wpa3: Discarding commit frame due to reflection attack");
324 return ESP_ERR_WIFI_DISCARD;
325 } else if (ret) {
326 wpa_printf(MSG_ERROR, "wpa3: could not parse commit(%d)", ret);
327 return ret;
328 }
329 if (g_sae_data.tmp && wpa3_check_sae_rejected_groups(g_sae_data.tmp->peer_rejected_groups)) {
330 return -1;
331 }
332
333 ret = sae_process_commit(&g_sae_data);
334 if (ret) {
335 wpa_printf(MSG_ERROR, "wpa3: could not process commit(%d)", ret);
336 return ret;
337 }
338
339 return ESP_OK;
340 }
341
wpa3_parse_sae_confirm(u8 * buf,u32 len)342 static int wpa3_parse_sae_confirm(u8 *buf, u32 len)
343 {
344 if (g_sae_data.state != SAE_CONFIRMED) {
345 wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE commit in state(%d)!",
346 g_sae_data.state);
347 return ESP_FAIL;
348 }
349
350 if (sae_check_confirm(&g_sae_data, buf, len) != ESP_OK) {
351 wpa_printf(MSG_ERROR, "wpa3: failed to parse SAE confirm");
352 return ESP_FAIL;
353 }
354 g_sae_data.state = SAE_ACCEPTED;
355
356 wpa_set_pmk(g_sae_data.pmk, g_sae_data.pmk_len, g_sae_data.pmkid, true);
357
358 return ESP_OK;
359 }
360
wpa3_parse_sae_msg(u8 * buf,size_t len,u32 sae_msg_type,u16 status)361 static int wpa3_parse_sae_msg(u8 *buf, size_t len, u32 sae_msg_type, u16 status)
362 {
363 int ret = ESP_OK;
364
365 switch (sae_msg_type) {
366 case SAE_MSG_COMMIT:
367 ret = wpa3_parse_sae_commit(buf, len, status);
368 break;
369 case SAE_MSG_CONFIRM:
370 ret = wpa3_parse_sae_confirm(buf, len);
371 esp_wpa3_free_sae_data();
372 break;
373 default:
374 wpa_printf(MSG_ERROR, "wpa3: Invalid SAE msg type(%" PRId32 ")!", sae_msg_type);
375 ret = ESP_FAIL;
376 break;
377 }
378
379 return ret;
380 }
381
esp_wifi_register_wpa3_cb(struct wpa_funcs * wpa_cb)382 void esp_wifi_register_wpa3_cb(struct wpa_funcs *wpa_cb)
383 {
384 wpa_cb->wpa3_build_sae_msg = wpa3_build_sae_msg;
385 wpa_cb->wpa3_parse_sae_msg = wpa3_parse_sae_msg;
386 }
387
esp_wifi_unregister_wpa3_cb(void)388 void esp_wifi_unregister_wpa3_cb(void)
389 {
390 extern struct wpa_funcs *wpa_cb;
391
392 wpa_cb->wpa3_build_sae_msg = NULL;
393 wpa_cb->wpa3_parse_sae_msg = NULL;
394
395 }
396 #endif /* CONFIG_WPA3_SAE */
397
398 #ifdef CONFIG_SAE
399
400 static void *g_wpa3_hostap_task_hdl = NULL;
401 static void *g_wpa3_hostap_evt_queue = NULL;
402 struct k_sem * g_wpa3_hostap_auth_api_lock = NULL;
403
wpa3_hostap_post_evt(uint32_t evt_id,uint32_t data)404 int wpa3_hostap_post_evt(uint32_t evt_id, uint32_t data)
405 {
406 wpa3_hostap_auth_event_t *evt = os_zalloc(sizeof(wpa3_hostap_auth_event_t));
407 if (evt == NULL) {
408 return ESP_FAIL;
409 }
410 evt->id = evt_id;
411 evt->data = data;
412
413 if (g_wpa3_hostap_auth_api_lock) {
414 WPA3_HOSTAP_AUTH_API_LOCK();
415 if (g_wpa3_hostap_evt_queue == NULL) {
416 WPA3_HOSTAP_AUTH_API_UNLOCK();
417 os_free(evt);
418 wpa_printf(MSG_DEBUG, "hostap evt queue NULL");
419 return ESP_FAIL;
420 }
421 } else {
422 os_free(evt);
423 wpa_printf(MSG_DEBUG, "g_wpa3_hostap_auth_api_lock not found");
424 return ESP_FAIL;
425 }
426 if (evt->id == SIG_WPA3_RX_CONFIRM || evt->id == SIG_TASK_DEL) {
427 /* prioritising confirm for completing handshake for committed sta */
428 if (os_queue_send_to_front(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
429 WPA3_HOSTAP_AUTH_API_UNLOCK();
430 wpa_printf(MSG_DEBUG, "failed to add msg to queue front");
431 os_free(evt);
432 return ESP_FAIL;
433 }
434 } else {
435 if (os_queue_send(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
436 WPA3_HOSTAP_AUTH_API_UNLOCK();
437 os_free(evt);
438 wpa_printf(MSG_DEBUG, "failed to send msg to queue");
439 return ESP_FAIL;
440 }
441 }
442 if (evt_id != SIG_TASK_DEL) {
443 /* For SIG_TASK_DEL, WPA3_HOSTAP_AUTH_API_UNLOCK will be after clean up of hostapd_data */
444 WPA3_HOSTAP_AUTH_API_UNLOCK();
445 }
446 return ESP_OK;
447 }
448
wpa3_process_rx_commit(wpa3_hostap_auth_event_t * evt)449 static void wpa3_process_rx_commit(wpa3_hostap_auth_event_t *evt)
450 {
451 struct hostapd_sae_commit_queue *frm;
452 struct hostapd_data *hapd = (struct hostapd_data *)esp_wifi_get_hostap_private_internal();
453 struct sta_info *sta = NULL;
454 int ret;
455 frm = dl_list_first(&hapd->sae_commit_queue,
456 struct hostapd_sae_commit_queue, list);
457 if (!frm) {
458 return;
459 }
460
461 dl_list_del(&frm->list);
462 wpa_printf(MSG_DEBUG, "SAE: Process next available message from queue");
463
464 sta = ap_get_sta(hapd, frm->bssid);
465 if (!sta) {
466 sta = ap_sta_add(hapd, frm->bssid);
467 if (!sta) {
468 wpa_printf(MSG_DEBUG, "ap_sta_add() failed");
469 ret = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
470 if (esp_send_sae_auth_reply(hapd, frm->bssid, frm->bssid, WLAN_AUTH_SAE,
471 frm->auth_transaction, ret, NULL,
472 0) != 0) {
473 wpa_printf(MSG_INFO, "esp_send_sae_auth_reply: send failed");
474 }
475 goto free;
476 }
477 }
478
479 if (sta->lock && os_semphr_take(sta->lock, 0)) {
480 sta->sae_commit_processing = true;
481 ret = handle_auth_sae(hapd, sta, frm->msg, frm->len, frm->bssid, frm->auth_transaction, frm->status);
482
483 if (sta->remove_pending) {
484 ap_free_sta(hapd, sta);
485 goto free;
486 }
487 sta->sae_commit_processing = false;
488 os_semphr_give(sta->lock);
489 uint16_t aid = 0;
490 if (ret != WLAN_STATUS_SUCCESS &&
491 ret != WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ) {
492 esp_wifi_ap_get_sta_aid(frm->bssid, &aid);
493 if (aid == 0) {
494 esp_wifi_ap_deauth_internal(frm->bssid, ret);
495 }
496 }
497 }
498
499 free:
500 os_free(frm);
501 }
502
wpa3_process_rx_confirm(wpa3_hostap_auth_event_t * evt)503 static void wpa3_process_rx_confirm(wpa3_hostap_auth_event_t *evt)
504 {
505 struct hostapd_data *hapd = (struct hostapd_data *)esp_wifi_get_hostap_private_internal();
506 struct sta_info *sta = NULL;
507 int ret = WLAN_STATUS_SUCCESS;
508 struct sae_hostap_confirm_data *frm = (struct sae_hostap_confirm_data *)evt->data;
509 if (!frm) {
510 return;
511 }
512 sta = ap_get_sta(hapd, frm->bssid);
513 if (!sta) {
514 os_free(frm);
515 return;
516 }
517
518 if (sta->lock && os_semphr_take(sta->lock, 0)) {
519 ret = handle_auth_sae(hapd, sta, frm->msg, frm->len, frm->bssid, frm->auth_transaction, frm->status);
520
521 if (sta->remove_pending) {
522 ap_free_sta(hapd, sta);
523 goto done;
524 }
525 if (ret == WLAN_STATUS_SUCCESS) {
526 if (esp_wifi_ap_notify_node_sae_auth_done(frm->bssid) != true) {
527 ap_free_sta(hapd, sta);
528 goto done;
529 }
530 }
531 os_semphr_give(sta->lock);
532 if (ret != WLAN_STATUS_SUCCESS) {
533 uint16_t aid = 0;
534 esp_wifi_ap_get_sta_aid(frm->bssid, &aid);
535 if (aid == 0) {
536 esp_wifi_ap_deauth_internal(frm->bssid, ret);
537 }
538 }
539 }
540 done:
541 os_free(frm);
542 }
543
esp_wpa3_hostap_task(void * pvParameters)544 static void esp_wpa3_hostap_task(void *pvParameters)
545 {
546 wpa3_hostap_auth_event_t *evt;
547 bool task_del = false;
548
549 while (1) {
550 if (os_queue_recv(g_wpa3_hostap_evt_queue, &evt, portMAX_DELAY) == 1) {
551 switch (evt->id) {
552 case SIG_WPA3_RX_COMMIT: {
553 wpa3_process_rx_commit(evt);
554 break;
555 }
556 case SIG_WPA3_RX_CONFIRM: {
557 wpa3_process_rx_confirm(evt);
558 break;
559 }
560 case SIG_TASK_DEL:
561 task_del = true;
562 break;
563 default:
564 break;
565 }
566 os_free(evt);
567
568 if (task_del) {
569 break;
570 }
571 }
572 }
573 uint32_t items_in_queue = os_queue_msg_waiting(g_wpa3_hostap_evt_queue);
574 while(items_in_queue--) {
575 /* Free events posted to queue */
576 os_queue_recv(g_wpa3_hostap_evt_queue, &evt, portMAX_DELAY);
577 if (evt->id == SIG_WPA3_RX_CONFIRM) {
578 os_free((void *)evt->data);
579 }
580 os_free(evt);
581 }
582 os_queue_delete(g_wpa3_hostap_evt_queue);
583 g_wpa3_hostap_evt_queue = NULL;
584
585 if (g_wpa3_hostap_auth_api_lock) {
586 WPA3_HOSTAP_AUTH_API_UNLOCK();
587 }
588 /* At this point, task is deleted*/
589 os_task_delete(NULL);
590 }
591
wpa3_hostap_auth_init(void * data)592 int wpa3_hostap_auth_init(void *data)
593 {
594 if (g_wpa3_hostap_evt_queue) {
595 wpa_printf(MSG_ERROR, "esp_wpa3_hostap_task has already been initialised");
596 return ESP_OK;
597 }
598
599 if (g_wpa3_hostap_auth_api_lock == NULL) {
600 g_wpa3_hostap_auth_api_lock = os_semphr_create(1, 1);
601 if (!g_wpa3_hostap_auth_api_lock) {
602 wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create WPA3 hostap auth API lock");
603 return ESP_FAIL;
604 }
605 }
606
607 g_wpa3_hostap_evt_queue = os_queue_create(10, sizeof(wpa3_hostap_auth_event_t));
608 if (!g_wpa3_hostap_evt_queue) {
609 wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create queue");
610 return ESP_FAIL;
611 }
612
613 if (os_task_create(esp_wpa3_hostap_task, "esp_wpa3_hostap_task",
614 WPA3_HOSTAP_HANDLE_AUTH_TASK_STACK_SIZE, NULL,
615 WPA3_HOSTAP_HANDLE_AUTH_TASK_PRIORITY,
616 &g_wpa3_hostap_task_hdl) != pdPASS) {
617 wpa_printf(MSG_ERROR, "wpa3_hostap_auth_init: failed to create task");
618 os_queue_delete(g_wpa3_hostap_evt_queue);
619 g_wpa3_hostap_evt_queue = NULL;
620 return ESP_FAIL;
621 }
622
623 struct hostapd_data *hapd = (struct hostapd_data *)data;
624 dl_list_init(&hapd->sae_commit_queue);
625 return ESP_OK;
626 }
627
wpa3_hostap_auth_deinit(void)628 bool wpa3_hostap_auth_deinit(void)
629 {
630 if (wpa3_hostap_post_evt(SIG_TASK_DEL, 0) != 0) {
631 wpa_printf(MSG_DEBUG, "failed to send task delete event");
632 return false;
633 } else {
634 return true;
635 }
636 }
637
wpa3_hostap_handle_auth(u8 * buf,size_t len,u32 auth_transaction,u16 status,u8 * bssid)638 static int wpa3_hostap_handle_auth(u8 *buf, size_t len, u32 auth_transaction, u16 status, u8 *bssid)
639 {
640 struct hostapd_data *hapd = (struct hostapd_data *)esp_wifi_get_hostap_private_internal();
641 if (!hapd) {
642 return ESP_FAIL;
643 }
644 struct sta_info *sta = ap_get_sta(hapd, bssid);
645 if (auth_transaction == SAE_MSG_COMMIT) {
646 if (sta && sta->sae_commit_processing) {
647 /* Ignore commit msg as we are already processing commit msg for this station */
648 return ESP_OK;
649 }
650 return auth_sae_queue(hapd, buf, len, bssid, status, auth_transaction);
651 }
652
653 if (sta && auth_transaction == SAE_MSG_CONFIRM) {
654 struct sae_hostap_confirm_data *frm = os_malloc(sizeof(struct sae_hostap_confirm_data) + len);
655 if (!frm) {
656 wpa_printf(MSG_ERROR, "failed to allocate memory for confirm event");
657 return ESP_FAIL;
658 }
659 frm->len = len;
660 os_memcpy(frm->bssid, bssid, ETH_ALEN);
661 frm->auth_transaction = auth_transaction;
662 frm->status = status;
663 os_memcpy(frm->msg, buf, len);
664 if (wpa3_hostap_post_evt(SIG_WPA3_RX_CONFIRM, (u32)frm) != 0) {
665 wpa_printf(MSG_ERROR, "failed to queue confirm build event");
666 os_free(frm);
667 return ESP_FAIL;
668 }
669 }
670 return ESP_OK;
671 }
672
esp_send_sae_auth_reply(struct hostapd_data * hapd,const u8 * dst,const u8 * bssid,u16 auth_alg,u16 auth_transaction,u16 resp,const u8 * ies,size_t ies_len)673 int esp_send_sae_auth_reply(struct hostapd_data *hapd,
674 const u8 *dst, const u8 *bssid,
675 u16 auth_alg, u16 auth_transaction, u16 resp,
676 const u8 *ies, size_t ies_len)
677 {
678 int reply_res = ESP_FAIL;
679 ies_len += 3 * sizeof(uint16_t);
680
681 wifi_mgmt_frm_req_t *req = os_zalloc(sizeof(*req) + ies_len);
682 if (!req) {
683 wpa_printf(MSG_ERROR, "failed to send sae auth reply");
684 return reply_res;
685 }
686 ((uint16_t *)req->data)[0] = htole16(auth_alg);
687 ((uint16_t *)req->data)[1] = htole16(auth_transaction);
688 ((uint16_t *)req->data)[2] = htole16(resp);
689 os_memcpy(&((uint16_t *)req->data)[3], ies, ies_len - 3 * sizeof(uint16_t));
690
691 req->ifx = WIFI_IF_AP;
692 req->subtype = (WLAN_FC_STYPE_AUTH << 4);
693 req->data_len = ies_len;
694 os_memcpy(req->da, bssid, ETH_ALEN);
695
696 if (esp_wifi_send_mgmt_frm_internal(req) != 0) {
697 wpa_printf(MSG_INFO, "%s: send failed", __func__);
698 } else {
699 reply_res = ESP_OK;
700 }
701
702 os_free(req);
703 return reply_res;
704 }
705
esp_wifi_register_wpa3_ap_cb(struct wpa_funcs * wpa_cb)706 void esp_wifi_register_wpa3_ap_cb(struct wpa_funcs *wpa_cb)
707 {
708 wpa_cb->wpa3_hostap_handle_auth = wpa3_hostap_handle_auth;
709 }
710
711 #endif /* CONFIG_SAE */
712