1 /*
2  * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <inttypes.h>
9 
10 #include "utils/includes.h"
11 #include "common.h"
12 #include "eloop.h"
13 #include "rsn_supp/wpa.h"
14 #include "utils/common.h"
15 #include "common/eapol_common.h"
16 #include "utils/wpa_debug.h"
17 #include "common/ieee802_11_defs.h"
18 #include "crypto/dh_group5.h"
19 #include "wps/wps_i.h"
20 #include "wps/wps_dev_attr.h"
21 #include "eap_peer/eap_defs.h"
22 #include "eap_peer/eap_common.h"
23 #include "esp_wifi_driver.h"
24 #include "esp_event.h"
25 #include "esp_wifi.h"
26 #include "esp_err.h"
27 #include "esp_private/wifi.h"
28 #include "esp_wps_i.h"
29 #include "esp_dpp_i.h"
30 #include "esp_wps.h"
31 #include "eap_common/eap_wsc_common.h"
32 #include "esp_wpas_glue.h"
33 
34 void *s_wps_api_lock = NULL;  /* Used in WPS/WPS-REG public API only, never be freed */
35 void *s_wps_api_sem = NULL;   /* Sync semaphore used between WPS/WPS-REG public API caller task and WPS task, never be freed */
36 bool s_wps_enabled = false;
37 #ifdef USE_WPS_TASK
38 struct wps_rx_param {
39     u8 sa[ETH_ALEN];
40     u8 *buf;
41     int len;
42     STAILQ_ENTRY(wps_rx_param) bqentry;
43 };
44 static STAILQ_HEAD(,wps_rx_param) s_wps_rxq;
45 
46 struct wps_sm_funcs *s_wps_sm_cb = NULL;
47 static void *s_wps_task_hdl = NULL;
48 static void *s_wps_queue = NULL;
49 static void *s_wps_data_lock = NULL;
50 static void *s_wps_task_create_sem = NULL;
51 static uint8_t s_wps_sig_cnt[SIG_WPS_NUM] = {0};
52 
53 #endif
54 
55 void wifi_wps_scan_done(void *arg, ETS_STATUS status);
56 void wifi_wps_scan(void *data, void *user_ctx);
57 int wifi_station_wps_start(void);
58 int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len);
59 void wifi_wps_start_internal(void);
60 int wifi_wps_enable_internal(const esp_wps_config_t *config);
61 int wifi_wps_disable_internal(void);
62 void wifi_station_wps_timeout_internal(void);
63 void wifi_station_wps_msg_timeout_internal(void);
64 void wifi_station_wps_success_internal(void);
65 void wifi_wps_scan_internal(void);
66 void wifi_station_wps_eapol_start_handle_internal(void);
67 void wps_add_discard_ap(u8 *bssid);
68 
69 void wifi_station_wps_msg_timeout(void *data, void *user_ctx);
70 void wifi_station_wps_eapol_start_handle(void *data, void *user_ctx);
71 void wifi_station_wps_success(void *data, void *user_ctx);
72 void wifi_station_wps_timeout(void *data, void *user_ctx);
73 int wps_delete_timer(void);
74 
75 struct wps_sm *gWpsSm = NULL;
76 static wps_factory_information_t *s_factory_info = NULL;
77 
wps_rxq_init(void)78 static void wps_rxq_init(void)
79 {
80     DATA_MUTEX_TAKE();
81     STAILQ_INIT(&s_wps_rxq);
82     DATA_MUTEX_GIVE();
83 }
84 
wps_rxq_enqueue(struct wps_rx_param * param)85 static void wps_rxq_enqueue(struct wps_rx_param *param)
86 {
87     DATA_MUTEX_TAKE();
88     STAILQ_INSERT_TAIL(&s_wps_rxq,param, bqentry);
89     DATA_MUTEX_GIVE();
90 }
91 
wps_rxq_dequeue(void)92 static struct wps_rx_param * wps_rxq_dequeue(void)
93 {
94     struct wps_rx_param *param = NULL;
95     DATA_MUTEX_TAKE();
96     if ((param = STAILQ_FIRST(&s_wps_rxq)) != NULL) {
97         STAILQ_REMOVE_HEAD(&s_wps_rxq, bqentry);
98         STAILQ_NEXT(param,bqentry) = NULL;
99     }
100     DATA_MUTEX_GIVE();
101     return param;
102 }
103 
wps_rxq_deinit(void)104 static void wps_rxq_deinit(void)
105 {
106     struct wps_rx_param *param = NULL;
107     DATA_MUTEX_TAKE();
108     while ((param = STAILQ_FIRST(&s_wps_rxq)) != NULL) {
109         STAILQ_REMOVE_HEAD(&s_wps_rxq, bqentry);
110         STAILQ_NEXT(param,bqentry) = NULL;
111         os_free(param->buf);
112         os_free(param);
113     }
114     DATA_MUTEX_GIVE();
115 }
116 
117 #ifdef USE_WPS_TASK
wps_task(void * pvParameters)118 void wps_task(void *pvParameters )
119 {
120     ETSEvent *e;
121     wps_ioctl_param_t *param;
122     bool del_task = false;
123 
124     os_semphr_give(s_wps_task_create_sem);
125 
126     wpa_printf(MSG_DEBUG, "wps_Task enter");
127     for (;;) {
128         if ( TRUE == os_queue_recv(s_wps_queue, &e, OS_BLOCK) ) {
129 
130             if ( (e->sig >= SIG_WPS_ENABLE) && (e->sig < SIG_WPS_NUM) ) {
131                 DATA_MUTEX_TAKE();
132                 if (s_wps_sig_cnt[e->sig]) {
133                     s_wps_sig_cnt[e->sig]--;
134                 } else {
135                     wpa_printf(MSG_ERROR, "wpsT: invalid sig cnt, sig=%" PRId32 " cnt=%d", e->sig, s_wps_sig_cnt[e->sig]);
136                 }
137                 DATA_MUTEX_GIVE();
138             }
139 
140             wpa_printf(MSG_DEBUG, "wpsT: rx sig=%" PRId32 "", e->sig);
141 
142             switch (e->sig) {
143             case SIG_WPS_ENABLE:
144             case SIG_WPS_DISABLE:
145             case SIG_WPS_START:
146                 param = (wps_ioctl_param_t *)e->par;
147                 if (!param) {
148                     wpa_printf(MSG_ERROR, "wpsT: invalid param sig=%" PRId32 "", e->sig);
149                     os_semphr_give(s_wps_api_sem);
150                     break;
151                 }
152 
153                 if (e->sig == SIG_WPS_ENABLE) {
154                     param->ret = wifi_wps_enable_internal((esp_wps_config_t *)(param->arg));
155                 } else if (e->sig == SIG_WPS_DISABLE) {
156                     DATA_MUTEX_TAKE();
157                     param->ret = wifi_wps_disable_internal();
158                     del_task = true;
159                     s_wps_task_hdl = NULL;
160                     DATA_MUTEX_GIVE();
161                 } else {
162                     param->ret = wifi_station_wps_start();
163                 }
164 
165                 os_semphr_give(s_wps_api_sem);
166                 break;
167 
168             case SIG_WPS_RX: {
169                 struct wps_rx_param *param = NULL;
170                 while ((param = wps_rxq_dequeue()) != NULL) {
171                     wps_sm_rx_eapol_internal(param->sa, param->buf, param->len);
172                     os_free(param->buf);
173                     os_free(param);
174                 }
175                 break;
176             }
177 
178             case SIG_WPS_TIMER_TIMEOUT:
179                 wifi_station_wps_timeout_internal();
180                 break;
181 
182             case SIG_WPS_TIMER_MSG_TIMEOUT:
183                 wifi_station_wps_msg_timeout_internal();
184                 break;
185 
186             case SIG_WPS_TIMER_SUCCESS_CB:
187                 wifi_station_wps_success_internal();
188                 break;
189 
190             case SIG_WPS_TIMER_SCAN:
191                 wifi_wps_scan_internal();
192                 break;
193 
194             case SIG_WPS_TIMER_EAPOL_START:
195                 wifi_station_wps_eapol_start_handle_internal();
196                 break;
197 
198             default:
199                 wpa_printf(MSG_ERROR, "wpsT: invalid sig=%" PRId32 "", e->sig);
200                 break;
201             }
202             os_free(e);
203 
204             if (del_task) {
205                 wpa_printf(MSG_DEBUG, "wpsT: delete task");
206                 break;
207             }
208         }
209     }
210     os_task_delete(NULL);
211 }
212 
213 /* wps_post() is thread-safe
214  *
215  */
wps_post(uint32_t sig,uint32_t par)216 int wps_post(uint32_t sig, uint32_t par)
217 {
218     wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " cnt=%d", sig, s_wps_sig_cnt[sig]);
219 
220     DATA_MUTEX_TAKE();
221 
222     if (!s_wps_task_hdl) {
223         wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " failed as wps task has been deinited", sig);
224         DATA_MUTEX_GIVE();
225         return ESP_FAIL;
226     }
227     if (s_wps_sig_cnt[sig]) {
228         wpa_printf(MSG_DEBUG, "wps post: sig=%" PRId32 " processing", sig);
229         DATA_MUTEX_GIVE();
230         return ESP_OK;
231     } else {
232         ETSEvent *evt = (ETSEvent *)os_malloc(sizeof(ETSEvent));
233 
234         if (evt == NULL) {
235             wpa_printf(MSG_ERROR, "WPS: E N M");
236             DATA_MUTEX_GIVE();
237             return ESP_FAIL;
238         }
239 
240         s_wps_sig_cnt[sig]++;
241         evt->sig = sig;
242         evt->par = par;
243         DATA_MUTEX_GIVE();
244 
245         if (os_queue_send(s_wps_queue, &evt, os_task_ms_to_tick(10)) != TRUE) {
246             wpa_printf(MSG_ERROR, "WPS: Q S E");
247             DATA_MUTEX_TAKE();
248             s_wps_sig_cnt[sig]--;
249             DATA_MUTEX_GIVE();
250             return ESP_FAIL;
251         }
252     }
253     return ESP_OK;
254 }
255 #endif
256 
257 /*
258 * wps_sm_ether_send - Send Ethernet frame
259 * @wpa_s: Pointer to wpa_supplicant data
260 * @proto: Ethertype in host byte order
261 * @buf: Frame payload starting from IEEE 802.1X header
262 * @len: Frame payload length
263 * Returns: >=0 on success, <0 on failure
264 */
wps_sm_ether_send(struct wps_sm * sm,u16 proto,const u8 * data,size_t data_len)265 static inline int wps_sm_ether_send(struct wps_sm *sm, u16 proto,
266                                     const u8 *data, size_t data_len)
267 {
268     u8 bssid[ETH_ALEN];
269     int ret = esp_wifi_get_assoc_bssid_internal(bssid);
270 
271     if (ret != 0) {
272         wpa_printf(MSG_ERROR, "bssid is empty!");
273         return -1;
274     }
275 
276     return wpa_ether_send(sm, bssid, proto, data, data_len);
277 }
278 
279 
wps_sm_alloc_eapol(struct wps_sm * sm,u8 type,const void * data,u16 data_len,size_t * msg_len,void ** data_pos)280 u8 *wps_sm_alloc_eapol(struct wps_sm *sm, u8 type,
281                        const void *data, u16 data_len,
282                        size_t *msg_len, void **data_pos)
283 {
284     return wpa_alloc_eapol(sm, type, data, data_len, msg_len, data_pos);
285 }
286 
287 
wps_sm_free_eapol(u8 * buffer)288 void wps_sm_free_eapol(u8 *buffer)
289 {
290     return wpa_free_eapol(buffer);
291 }
292 
293 static void
wps_build_ic_appie_wps_pr(void)294 wps_build_ic_appie_wps_pr(void)
295 {
296     struct wpabuf *extra_ie = NULL;
297     struct wpabuf *wps_ie;
298     struct wps_sm *sm = gWpsSm;
299     u16 pw_id;
300 
301     wpa_printf(MSG_DEBUG, "wps build: wps pr");
302 
303     if (wps_get_type() == WPS_TYPE_PBC) {
304         pw_id = DEV_PW_PUSHBUTTON;
305     } else {
306         pw_id = DEV_PW_DEFAULT;
307     }
308     wps_ie = wps_build_probe_req_ie(pw_id, sm->dev, sm->uuid,
309                                     WPS_REQ_ENROLLEE, 0, NULL);
310 
311     if (!wps_ie) {
312         return;
313     }
314 
315     if (wpabuf_resize(&extra_ie, wpabuf_len(wps_ie)) == 0) {
316         wpabuf_put_buf(extra_ie, wps_ie);
317     } else {
318         wpabuf_free(wps_ie);
319         return;
320     }
321     wpabuf_free(wps_ie);
322 
323     esp_wifi_set_appie_internal(WIFI_APPIE_WPS_PR, (uint8_t *)wpabuf_head(extra_ie), extra_ie->used, 0);
324     wpabuf_free(extra_ie);
325 }
326 
327 static void
wps_build_ic_appie_wps_ar(void)328 wps_build_ic_appie_wps_ar(void)
329 {
330     struct wpabuf *buf = wps_build_assoc_req_ie(WPS_REQ_ENROLLEE);
331 
332     wpa_printf(MSG_DEBUG, "wps build: wps ar");
333 
334     if (buf) {
335         esp_wifi_set_appie_internal(WIFI_APPIE_WPS_AR, (uint8_t *)wpabuf_head(buf), buf->used, 0);
336         wpabuf_free(buf);
337     }
338 }
339 
ap_supports_sae(struct wps_scan_ie * scan)340 static bool ap_supports_sae(struct wps_scan_ie *scan)
341 {
342     struct wpa_ie_data rsn_info;
343 
344     if (!scan->rsn) {
345         return false;
346     }
347 
348     wpa_parse_wpa_ie_rsn(scan->rsn, scan->rsn[1] + 2, &rsn_info);
349 
350     if (rsn_info.key_mgmt & WPA_KEY_MGMT_SAE) {
351         return true;
352     }
353 
354     return false;
355 }
356 
357 static bool
wps_parse_scan_result(struct wps_scan_ie * scan)358 wps_parse_scan_result(struct wps_scan_ie *scan)
359 {
360     struct wps_sm *sm = gWpsSm;
361     wifi_mode_t op_mode = 0;
362 
363     if (!sm->is_wps_scan || !scan->bssid) {
364         return false;
365     }
366 
367     if (wps_get_type() == WPS_TYPE_DISABLE
368             || (wps_get_status() != WPS_STATUS_DISABLE
369                 && wps_get_status() != WPS_STATUS_SCANNING)
370        ) {
371         return false;
372     }
373 
374     esp_wifi_get_mode(&op_mode);
375     if ((op_mode != ESP32_WIFI_MODE_STA)
376 #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
377         && (op_mode != ESP32_WIFI_MODE_APSTA)
378 #endif
379        ) {
380         return false;
381     }
382 
383     if (!scan->rsn && !scan->wpa && (scan->capinfo & WLAN_CAPABILITY_PRIVACY)) {
384         wpa_printf(MSG_DEBUG, "WEP not suppported in WPS");
385         return false;
386     }
387 
388     if (sm->ignore_sel_reg && !is_zero_ether_addr(sm->bssid)) {
389         /* We have selected candidate for this scan */
390         return false;
391     }
392 
393     if (scan->wps) {
394         bool ap_found = false;
395         struct wpabuf *buf = wpabuf_alloc_copy(scan->wps + 6, scan->wps[1] - 4);
396         int count;
397 
398         if ((wps_get_type() == WPS_TYPE_PBC && wps_is_selected_pbc_registrar(buf)) ||
399             (wps_get_type() == WPS_TYPE_PIN && wps_is_addr_authorized(buf, sm->ownaddr, 1))) {
400             /* Found one AP with selected registrar true */
401             sm->ignore_sel_reg = false;
402             sm->discard_ap_cnt = 0;
403             ap_found = true;
404         }
405         if (wps_get_type() == WPS_TYPE_PIN && sm->ignore_sel_reg) {
406             /* AP is in discard list? */
407             for (count = 0; count < WPS_MAX_DIS_AP_NUM; count++) {
408                 if (os_memcmp(sm->dis_ap_list[count].bssid, scan->bssid, ETH_ALEN) == 0) {
409                     wpa_printf(MSG_INFO, "discard ap bssid "MACSTR, MAC2STR(scan->bssid));
410                     wpabuf_free(buf);
411                     return false;
412                 }
413             }
414         }
415 
416         if (ap_found || sm->ignore_sel_reg) {
417             wpabuf_free(buf);
418             if (scan->ssid[1] > SSID_MAX_LEN) {
419                 return false;
420             }
421             esp_wifi_enable_sta_privacy_internal();
422             os_memset(sm->creds[0].ssid, 0, SSID_MAX_LEN);
423             os_memcpy(sm->creds[0].ssid, (char *)&scan->ssid[2], (int)scan->ssid[1]);
424             sm->creds[0].ssid_len = scan->ssid[1];
425             if (scan->bssid && memcmp(sm->bssid, scan->bssid, ETH_ALEN) != 0) {
426                 wpa_printf(MSG_INFO, "sm BSSid: "MACSTR " scan BSSID " MACSTR,
427                            MAC2STR(sm->bssid), MAC2STR(scan->bssid));
428                 sm->discover_ssid_cnt++;
429                 os_memcpy(sm->bssid, scan->bssid, ETH_ALEN);
430                 if (ap_supports_sae(scan)) {
431                     wpa_printf(MSG_INFO, "AP supports SAE, get password in passphrase");
432                     sm->dev->config_methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY;
433                     sm->wps->wps->config_methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY;
434                     /* Reset assoc req, probe reset not needed */
435                     wps_build_ic_appie_wps_ar();
436                 }
437             }
438             wpa_printf(MSG_DEBUG, "wps discover [%s]", (char *)sm->creds[0].ssid);
439             sm->channel = scan->chan;
440 
441             return true;
442         }
443         wpabuf_free(buf);
444     }
445 
446     return false;
447 }
448 
wps_send_eap_identity_rsp(u8 id)449 int wps_send_eap_identity_rsp(u8 id)
450 {
451     struct wps_sm *sm = gWpsSm;
452     struct wpabuf *eap_buf = NULL;
453     u8 *buf = NULL;
454     int len;
455     int ret = ESP_OK;
456 
457     wpa_printf(MSG_DEBUG, "wps send eapol id rsp");
458     eap_buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, sm->identity_len,
459                             EAP_CODE_RESPONSE, id);
460     if (!eap_buf) {
461         wpa_printf(MSG_ERROR, "eap buf allocation failed");
462         ret = ESP_FAIL;
463         goto _err;
464     }
465 
466 
467     wpabuf_put_data(eap_buf, sm->identity, sm->identity_len);
468 
469     buf = wps_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head_u8(eap_buf), wpabuf_len(eap_buf), (size_t *)&len, NULL);
470     if (!buf) {
471         wpa_printf(MSG_ERROR, "buf allocation failed");
472         ret = ESP_ERR_NO_MEM;
473         goto _err;
474     }
475 
476     ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len);
477     if (ret) {
478         wpa_printf(MSG_ERROR, "wps sm ether send failed ret=%d", ret);
479         ret = ESP_FAIL;
480         goto _err;
481     }
482 
483 _err:
484     wps_sm_free_eapol(buf);
485     wpabuf_free(eap_buf);
486     return ret;
487 }
488 
wps_send_frag_ack(u8 id)489 int wps_send_frag_ack(u8 id)
490 {
491     struct wps_sm *sm = gWpsSm;
492     struct wpabuf *eap_buf = NULL;
493     u8 *buf;
494     int len;
495     int ret = 0;
496 
497     wpa_printf(MSG_DEBUG, "send frag ack id:%d", id);
498 
499     if (!sm) {
500         return ESP_FAIL;
501     }
502 
503     eap_buf = eap_wsc_build_frag_ack(id, EAP_CODE_RESPONSE);
504     if (!eap_buf) {
505         ret = ESP_ERR_NO_MEM;
506         goto _err;
507     }
508 
509     buf = wps_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head_u8(eap_buf), wpabuf_len(eap_buf), (size_t *)&len, NULL);
510     if (!buf) {
511         ret = ESP_ERR_NO_MEM;
512         goto _err;
513     }
514 
515     ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len);
516     wps_sm_free_eapol(buf);
517     if (ret) {
518         ret = ESP_ERR_NO_MEM;
519         goto _err;
520     }
521 
522 _err:
523     wpabuf_free(eap_buf);
524     return ret;
525 }
526 
wps_enrollee_process_msg_frag(struct wpabuf ** buf,int tot_len,u8 * frag_data,int frag_len,u8 flag)527 int wps_enrollee_process_msg_frag(struct wpabuf **buf, int tot_len, u8 *frag_data, int frag_len, u8 flag)
528 {
529     struct wps_sm *sm = gWpsSm;
530     u8 identifier;
531 
532     if (!sm) {
533         return ESP_FAIL;
534     }
535 
536     identifier = sm->current_identifier;
537 
538     if (buf == NULL || frag_data == NULL) {
539         wpa_printf(MSG_ERROR, "fun:%s. line:%d, frag buf or frag data is null", __FUNCTION__, __LINE__);
540         return ESP_FAIL;
541     }
542 
543     if (*buf == NULL) {
544         if (0 == (flag & WPS_MSG_FLAG_LEN) || tot_len < frag_len) {
545             wpa_printf(MSG_ERROR, "fun:%s. line:%d, flag error:%02x", __FUNCTION__, __LINE__, flag);
546             return ESP_FAIL;
547         }
548 
549         *buf = wpabuf_alloc(tot_len);
550         if (*buf == NULL) {
551             return ESP_ERR_NO_MEM;
552         }
553 
554         wpabuf_put_data(*buf, frag_data, frag_len);
555         return wps_send_frag_ack(identifier);
556     }
557 
558     if (flag & WPS_MSG_FLAG_LEN) {
559         wpa_printf(MSG_ERROR, "fun:%s. line:%d, flag error:%02x", __FUNCTION__, __LINE__, flag);
560         return ESP_FAIL;
561     }
562 
563     wpabuf_put_data(*buf, frag_data, frag_len);
564 
565     if (flag & WPS_MSG_FLAG_MORE) {
566         return wps_send_frag_ack(identifier);
567     }
568 
569     return ESP_OK;
570 }
571 
wps_process_wps_mX_req(u8 * ubuf,int len,enum wps_process_res * res)572 int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res)
573 {
574     struct wps_sm *sm = gWpsSm;
575     static struct wpabuf *wps_buf = NULL;
576     struct eap_expand *expd;
577     int tlen = 0;
578     u8 *tbuf;
579     u8 flag;
580     int frag_len;
581     u16 be_tot_len = 0;
582 
583     if (!sm || !res) {
584         return ESP_FAIL;
585     }
586 
587     expd = (struct eap_expand *) ubuf;
588     wpa_printf(MSG_DEBUG, "wps process mX req: len %d, tlen %d", len, tlen);
589 
590     if (sm->state == WAIT_START) {
591         if (expd->opcode != WSC_Start) {
592             wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d "
593                        "in WAIT_START state", expd->opcode);
594             return ESP_ERR_INVALID_STATE;
595         }
596         wpa_printf(MSG_DEBUG, "EAP-WSC: Received start");
597         sm->state = WPA_MESG;
598     } else if (expd->opcode == WSC_Start) {
599         wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d",
600                    expd->opcode);
601         return ESP_ERR_INVALID_STATE;
602     }
603 
604     flag = *(u8 *)(ubuf + sizeof(struct eap_expand));
605     if (flag & WPS_MSG_FLAG_LEN) {
606         tbuf = ubuf + sizeof(struct eap_expand) + 1 + 2;//two bytes total length
607         frag_len = len - (sizeof(struct eap_expand) + 1 + 2);
608         be_tot_len = *(u16 *)(ubuf + sizeof(struct eap_expand) + 1);
609         tlen = ((be_tot_len & 0xff) << 8) | ((be_tot_len >> 8) & 0xff);
610     } else {
611         tbuf = ubuf + sizeof(struct eap_expand) + 1;
612         frag_len = len - (sizeof(struct eap_expand) + 1);
613         tlen = frag_len;
614     }
615 
616     if ((flag & WPS_MSG_FLAG_MORE) || wps_buf != NULL) {//frag msg
617         if (tlen > 50000) {
618             wpa_printf(MSG_ERROR, "EAP-WSC: Invalid Message Length");
619             return ESP_FAIL;
620 	}
621         wpa_printf(MSG_DEBUG, "rx frag msg id:%d, flag:%d, frag_len: %d, tot_len: %d, be_tot_len:%d", sm->current_identifier, flag, frag_len, tlen, be_tot_len);
622         if (ESP_OK != wps_enrollee_process_msg_frag(&wps_buf, tlen, tbuf, frag_len, flag)) {
623             if (wps_buf) {
624                 wpabuf_free(wps_buf);
625                 wps_buf = NULL;
626             }
627             return ESP_FAIL;
628         }
629         if (flag & WPS_MSG_FLAG_MORE) {
630             *res = WPS_FRAGMENT;
631             return ESP_OK;
632         }
633     } else { //not frag msg
634         if (wps_buf) {//if something wrong, frag msg buf is not freed, free first
635             wpa_printf(MSG_ERROR, "something is wrong, frag buf is not freed");
636             wpabuf_free(wps_buf);
637             wps_buf = NULL;
638         }
639         wps_buf = wpabuf_alloc_copy(tbuf, tlen);
640     }
641 
642     if (!wps_buf) {
643         return ESP_FAIL;
644     }
645 
646     eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL);
647 
648     *res = wps_enrollee_process_msg(sm->wps, expd->opcode, wps_buf);
649 
650     if (*res == WPS_FAILURE) {
651         sm->state = WPA_FAIL;
652     }
653 
654     if (wps_buf) {
655         wpabuf_free(wps_buf);
656         wps_buf = NULL;
657     }
658     return ESP_OK;
659 }
660 
wps_send_wps_mX_rsp(u8 id)661 int wps_send_wps_mX_rsp(u8 id)
662 {
663     struct wps_sm *sm = gWpsSm;
664     struct wpabuf *eap_buf = NULL;
665     struct wpabuf *wps_buf = NULL;
666     u8 *buf;
667     int len;
668     int ret = 0;
669     enum wsc_op_code opcode;
670 
671     wpa_printf(MSG_DEBUG, "wps send wps mX rsp");
672 
673     if (!sm) {
674         return ESP_FAIL;
675     }
676 
677     wps_buf = wps_enrollee_get_msg(sm->wps, &opcode);
678     if (!wps_buf) {
679         ret = ESP_FAIL;
680         goto _err;
681     }
682 
683     eap_buf = eap_msg_alloc(EAP_VENDOR_WFA, 0x00000001, wpabuf_len(wps_buf) + 2, EAP_CODE_RESPONSE, id);
684     if (!eap_buf) {
685         ret = ESP_FAIL;
686         goto _err;
687     }
688 
689     wpabuf_put_u8(eap_buf, opcode);
690     wpabuf_put_u8(eap_buf, 0x00); /* flags */
691     wpabuf_put_data(eap_buf, wpabuf_head_u8(wps_buf), wpabuf_len(wps_buf));
692 
693     wpabuf_free(wps_buf);
694 
695     buf = wps_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAP_PACKET, wpabuf_head_u8(eap_buf), wpabuf_len(eap_buf), (size_t *)&len, NULL);
696     if (!buf) {
697         ret = ESP_FAIL;
698         goto _err;
699     }
700 
701     ret = wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len);
702     wps_sm_free_eapol(buf);
703     if (ret) {
704         ret = ESP_FAIL;
705         goto _err;
706     }
707 
708 _err:
709     wpabuf_free(eap_buf);
710     return ret;
711 }
712 
713 
714 
wps_tx_start(void)715 int wps_tx_start(void)
716 {
717     struct wps_sm *sm = gWpsSm;
718     u8 *buf;
719     int len;
720 
721     if (!sm) {
722         return ESP_FAIL;
723     }
724 
725     wpa_printf(MSG_DEBUG,  "WPS: Send EAPOL START.");
726     buf = wps_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, (u8 *)"", 0, (size_t *)&len, NULL);
727     if (!buf) {
728         return ESP_ERR_NO_MEM;
729     }
730 
731     wps_sm_ether_send(sm, ETH_P_EAPOL, buf, len);
732     wps_sm_free_eapol(buf);
733 
734     eloop_register_timeout(3, 0, wifi_station_wps_eapol_start_handle, NULL, NULL);
735 
736     return ESP_OK;
737 }
738 
wps_start_pending(void)739 int wps_start_pending(void)
740 {
741     if (!gWpsSm) {
742         return ESP_FAIL;
743     }
744 
745     wpa_printf(MSG_DEBUG, "wps start pending");
746     return wps_tx_start();
747 }
748 
wps_stop_connection_timers(struct wps_sm * sm)749 static void wps_stop_connection_timers(struct wps_sm *sm)
750 {
751     esp_wifi_disarm_sta_connection_timer_internal();
752     eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL);
753     eloop_cancel_timeout(wifi_station_wps_success, NULL, NULL);
754 }
755 
wps_sm_init(struct wps_sm * sm)756 static int wps_sm_init(struct wps_sm *sm)
757 {
758     if (!sm) {
759         return -1;
760     }
761     sm->ignore_sel_reg = false;
762     sm->discard_ap_cnt = 0;
763     sm->scan_cnt = 0;
764     sm->discover_ssid_cnt = 0;
765     os_bzero(sm->bssid, ETH_ALEN);
766     os_bzero(sm->creds, sizeof(sm->creds));
767     sm->ap_cred_cnt = 0;
768 
769     return 0;
770 }
771 
wps_stop_process(wifi_event_sta_wps_fail_reason_t reason_code)772 int wps_stop_process(wifi_event_sta_wps_fail_reason_t reason_code)
773 {
774     struct wps_sm *sm = gWpsSm;
775 
776     if (!gWpsSm) {
777         return ESP_FAIL;
778     }
779 
780     wps_set_status(WPS_STATUS_DISABLE);
781     wps_sm_init(sm);
782 
783     sm->wps->state = SEND_M1;
784     wps_stop_connection_timers(sm);
785     esp_wifi_disconnect();
786 
787     sm->state = WPA_FAIL;
788     wpa_printf(MSG_DEBUG, "Write wps_fail_information");
789 
790     esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_FAILED, &reason_code, sizeof(reason_code), OS_BLOCK);
791 
792     return ESP_OK;
793 }
794 
wps_finish(void)795 int wps_finish(void)
796 {
797     struct wps_sm *sm = gWpsSm;
798     int ret = ESP_FAIL;
799 
800     if (!gWpsSm) {
801         return ESP_FAIL;
802     }
803 
804     if (sm->wps->state == WPS_FINISHED) {
805         wpa_printf(MSG_DEBUG, "wps finished------>");
806         wps_set_status(WPS_STATUS_SUCCESS);
807         /* WPS finished, dequeue all timers */
808         wps_delete_timer();
809 
810         esp_wifi_unset_appie_internal(WIFI_APPIE_WPS_PR);
811         esp_wifi_unset_appie_internal(WIFI_APPIE_WPS_AR);
812         esp_wifi_set_wps_cb_internal(NULL);
813 
814         if (sm->ap_cred_cnt == 1) {
815             wifi_config_t *config = os_zalloc(sizeof(wifi_config_t));
816 
817             if (config == NULL) {
818                 return ESP_FAIL;
819             }
820 
821             esp_wifi_get_config(WIFI_IF_STA, config);
822             esp_wifi_disconnect();
823             os_memcpy(config->sta.ssid, sm->creds[0].ssid, sm->creds[0].ssid_len);
824             os_memcpy(config->sta.password, sm->creds[0].key, sm->creds[0].key_len);
825             os_memcpy(config->sta.bssid, sm->bssid, ETH_ALEN);
826 #ifndef CONFIG_WPS_STRICT
827             /* Some APs support AES in WPA IE, enable connection with them */
828             if (sm->creds[0].auth_type == WPS_AUTH_WPAPSK &&
829                     (sm->creds[0].encr_type & WPS_ENCR_AES)) {
830                 config->sta.threshold.authmode = WIFI_AUTH_WPA_PSK;
831             }
832 #endif
833             config->sta.bssid_set = 0;
834             config->sta.sae_pwe_h2e = 0;
835             esp_wifi_set_config(WIFI_IF_STA, config);
836             esp_wifi_connect();
837 
838             os_free(config);
839         }
840         eloop_cancel_timeout(wifi_station_wps_success, NULL, NULL);
841 	eloop_register_timeout(1, 0, wifi_station_wps_success, NULL, NULL);
842 
843         ret = 0;
844     } else {
845         wpa_printf(MSG_ERROR, "wps failed-----> ignore_sel_reg=%d", sm->ignore_sel_reg);
846         if (sm->ignore_sel_reg) {
847             sm->discover_ssid_cnt = 0;
848             esp_wifi_disconnect();
849             os_bzero(sm->creds, sizeof(sm->creds));
850             wps_add_discard_ap(sm->bssid);
851         } else {
852             ret = wps_stop_process(WPS_FAIL_REASON_NORMAL);
853         }
854     }
855 
856     return ret;
857 }
858 
wps_sm_notify_deauth(void)859 static void wps_sm_notify_deauth(void)
860 {
861     if (gWpsSm && gWpsSm->wps->state != WPS_FINISHED) {
862         wps_stop_process(WPS_FAIL_REASON_RECV_DEAUTH);
863     }
864 }
865 
866 /* Add current ap to discard ap list */
wps_add_discard_ap(u8 * bssid)867 void wps_add_discard_ap(u8 *bssid)
868 {
869     struct wps_sm *sm = gWpsSm;
870     u8 cnt = sm->discard_ap_cnt;
871 
872     if (!gWpsSm || !bssid) {
873         return;
874     }
875 
876     if (sm->discard_ap_cnt < WPS_MAX_DIS_AP_NUM) {
877         sm->discard_ap_cnt++;
878     } else {
879         for (cnt = 0; cnt < WPS_MAX_DIS_AP_NUM - 2; cnt++) {
880             os_memcpy(sm->dis_ap_list[cnt].bssid, sm->dis_ap_list[cnt + 1].bssid, 6);
881         }
882         sm->discard_ap_cnt = WPS_MAX_DIS_AP_NUM;
883     }
884     os_memcpy(sm->dis_ap_list[cnt].bssid, bssid, ETH_ALEN);
885     wpa_printf(MSG_INFO, "Added BSSID:"MACSTR" to discard list cnt=%d" , MAC2STR(bssid), sm->discard_ap_cnt);
886 }
887 
wps_start_msg_timer(void)888 int wps_start_msg_timer(void)
889 {
890     struct wps_sm *sm = gWpsSm;
891     uint32_t msg_timeout;
892     int ret = ESP_FAIL;
893 
894     if (!gWpsSm) {
895         return ESP_FAIL;
896     }
897 
898     if (sm->wps->state == WPS_FINISHED) {
899         msg_timeout = 100;
900         wpa_printf(MSG_DEBUG, "start msg timer WPS_FINISHED %" PRId32 " ms", msg_timeout);
901 	eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL);
902 	eloop_register_timeout(0, msg_timeout*1000, wifi_station_wps_msg_timeout, NULL, NULL);
903         ret = 0;
904     } else if (sm->wps->state == RECV_M2) {
905         msg_timeout = 5;
906         wpa_printf(MSG_DEBUG, "start msg timer RECV_M2 %" PRId32 " s", msg_timeout);
907 	eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL);
908 	eloop_register_timeout(msg_timeout, 0, wifi_station_wps_msg_timeout, NULL, NULL);
909         ret = 0;
910     }
911     return ret;
912 }
913 
914 /**
915  * wps_sm_rx_eapol - Process received WPA EAPOL frames
916  * @sm: Pointer to WPA state machine data from wpa_sm_init()
917  * @src_addr: Source MAC address of the EAPOL packet
918  * @buf: Pointer to the beginning of the EAPOL data (EAPOL header)
919  * @len: Length of the EAPOL frame
920  * Returns: 1 = WPA EAPOL-Key processed, ESP_OK = not a WPA EAPOL-Key, ESP_FAIL failure
921  *
922  * This function is called for each received EAPOL frame. Other than EAPOL-Key
923  * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is
924  * only processing WPA and WPA2 EAPOL-Key frames.
925  *
926  * The received EAPOL-Key packets are validated and valid packets are replied
927  * to. In addition, key material (PTK, GTK) is configured at the end of a
928  * successful key handshake.
929  * buf begin from version, so remove mac header ,snap header and ether_type
930  */
wps_sm_rx_eapol(u8 * src_addr,u8 * buf,u32 len)931 int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
932 {
933     if (!gWpsSm) {
934         return ESP_FAIL;
935     }
936 
937 #ifdef USE_WPS_TASK
938     {
939         struct wps_rx_param *param = os_zalloc(sizeof(struct wps_rx_param));   /* free in task */
940 
941         if (!param) {
942             return ESP_ERR_NO_MEM;
943         }
944 
945         param->buf = os_zalloc(len);   /* free in task */
946         if (!param->buf) {
947             os_free(param);
948             return ESP_ERR_NO_MEM;
949         }
950         os_memcpy(param->buf, buf, len);
951         param->len = len;
952         os_memcpy(param->sa, src_addr, ETH_ALEN);
953 
954         wps_rxq_enqueue(param);
955         return wps_post(SIG_WPS_RX, 0);
956     }
957 #else
958     return wps_sm_rx_eapol_internal(src_addr, buf, len);
959 #endif
960 }
961 
wps_sm_rx_eapol_internal(u8 * src_addr,u8 * buf,u32 len)962 int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len)
963 {
964     struct wps_sm *sm = gWpsSm;
965     u32 plen, data_len, eap_len;
966     struct ieee802_1x_hdr *hdr;
967     struct eap_hdr *ehdr;
968     u8 *tmp;
969     u8 eap_code;
970     u8 eap_type;
971     int ret = ESP_FAIL;
972     enum wps_process_res res = WPS_DONE;
973 
974     if (!gWpsSm) {
975         return ESP_FAIL;
976     }
977 
978     if (len < sizeof(*hdr) + sizeof(*ehdr)) {
979         wpa_printf(MSG_DEBUG,  "WPA: EAPOL frame too short to be a WPA "
980                    "EAPOL-Key (len %lu, expecting at least %lu)",
981                    (unsigned long) len,
982                    (unsigned long) sizeof(*hdr) + sizeof(*ehdr));
983         return ESP_OK;
984     }
985 
986     tmp = buf;
987 
988     hdr = (struct ieee802_1x_hdr *) tmp;
989     ehdr = (struct eap_hdr *) (hdr + 1);
990     plen = be_to_host16(hdr->length);
991     data_len = plen + sizeof(*hdr);
992     eap_len = be_to_host16(ehdr->length);
993 
994     wpa_printf(MSG_DEBUG, "IEEE 802.1X RX: version=%d type=%d length=%" PRId32 "",
995                hdr->version, hdr->type, plen);
996 
997     if (hdr->version < EAPOL_VERSION) {
998         /* TODO: backwards compatibility */
999     }
1000     if (hdr->type != IEEE802_1X_TYPE_EAP_PACKET) {
1001         wpa_printf(MSG_DEBUG, "WPS: EAP frame (type %u) discarded, "
1002                    "not a EAP PACKET frame", hdr->type);
1003         ret = 0;
1004         goto out;
1005     }
1006     if (plen > len - sizeof(*hdr) || plen < sizeof(*ehdr)) {
1007         wpa_printf(MSG_DEBUG, "WPA: EAPOL frame payload size %lu "
1008                    "invalid (frame size %lu)",
1009                    (unsigned long) plen, (unsigned long) len);
1010         ret = 0;
1011         goto out;
1012     }
1013 
1014     wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-EAP PACKET", tmp, len);
1015 
1016     if (data_len < len) {
1017         wpa_printf(MSG_DEBUG, "WPA: ignoring %lu bytes after the IEEE "
1018                    "802.1X data", (unsigned long) len - data_len);
1019     }
1020 
1021     if (eap_len != plen) {
1022         wpa_printf(MSG_DEBUG, "WPA: EAPOL length %lu "
1023                    "invalid (eapol length %lu)",
1024                    (unsigned long) eap_len, (unsigned long) plen);
1025         ret = 0;
1026         goto out;
1027     }
1028 
1029     eap_code = ehdr->code;
1030     switch (eap_code) {
1031     case EAP_CODE_SUCCESS:
1032         wpa_printf(MSG_DEBUG, "error: receive eapol success frame!");
1033         ret = 0;
1034         break;
1035     case EAP_CODE_FAILURE:
1036         wpa_printf(MSG_DEBUG, "receive eap code failure!");
1037         ret = wps_finish();
1038         break;
1039     case EAP_CODE_RESPONSE:
1040         wpa_printf(MSG_DEBUG, "error: receive eapol response frame!");
1041         ret = 0;
1042         break;
1043     case EAP_CODE_REQUEST: {
1044         eap_type = ((u8 *)ehdr)[sizeof(*ehdr)];
1045         switch (eap_type) {
1046         case EAP_TYPE_IDENTITY:
1047             wpa_printf(MSG_DEBUG, "=========identity===========");
1048             sm->current_identifier = ehdr->identifier;
1049             eloop_cancel_timeout(wifi_station_wps_eapol_start_handle, NULL, NULL);
1050             wpa_printf(MSG_DEBUG,  "WPS: Build EAP Identity.");
1051             ret = wps_send_eap_identity_rsp(ehdr->identifier);
1052             eloop_register_timeout(3, 0, wifi_station_wps_eapol_start_handle, NULL, NULL);
1053             break;
1054         case EAP_TYPE_EXPANDED:
1055             wpa_printf(MSG_DEBUG, "=========expanded plen[%" PRId32 "], %d===========", plen, sizeof(*ehdr));
1056             sm->current_identifier = ehdr->identifier;
1057 
1058             tmp = (u8 *)(ehdr + 1) + 1;
1059             ret = wps_process_wps_mX_req(tmp, plen - sizeof(*ehdr) - 1, &res);
1060             if (res == WPS_FRAGMENT) {
1061                 wpa_printf(MSG_DEBUG, "wps frag, silently exit", res);
1062                 ret = ESP_OK;
1063                 break;
1064             }
1065             if (ret == ESP_OK && res != WPS_FAILURE) {
1066                 ret = wps_send_wps_mX_rsp(ehdr->identifier);
1067 
1068                 if (ret == ESP_OK) {
1069                     wpa_printf(MSG_DEBUG, "sm->wps->state = %d", sm->wps->state);
1070                     wps_start_msg_timer();
1071                 }
1072             } else if (ret == ESP_ERR_INVALID_STATE) {
1073                 ret = ESP_OK;
1074             } else {
1075                 ret = ESP_FAIL;
1076             }
1077             break;
1078         default:
1079             break;
1080         }
1081         break;
1082     }
1083     default:
1084         break;
1085     }
1086 out:
1087     if (ret != 0 && sm->ignore_sel_reg) {
1088         wifi_wps_scan(NULL, NULL);
1089     } else if ((ret != 0 || res == WPS_FAILURE)) {
1090         wifi_event_sta_wps_fail_reason_t reason_code = WPS_FAIL_REASON_NORMAL;
1091         wpa_printf(MSG_DEBUG, "wpa rx eapol internal: fail ret=%d", ret);
1092         wps_set_status(WPS_STATUS_DISABLE);
1093         esp_wifi_disarm_sta_connection_timer_internal();
1094         eloop_cancel_timeout(wifi_station_wps_timeout, NULL, NULL);
1095 
1096         esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_FAILED, &reason_code, sizeof(reason_code), OS_BLOCK);
1097 
1098         return ret;
1099     }
1100 
1101     return ret;
1102 }
1103 
wps_set_default_factory(void)1104 int wps_set_default_factory(void)
1105 {
1106     if (!s_factory_info) {
1107         s_factory_info = os_zalloc(sizeof(wps_factory_information_t));
1108         if (!s_factory_info) {
1109             wpa_printf(MSG_ERROR, "wps factory info malloc failed");
1110             return ESP_ERR_NO_MEM;
1111         }
1112     }
1113 
1114     os_snprintf(s_factory_info->manufacturer, WPS_MAX_MANUFACTURER_LEN, "ESPRESSIF");
1115     os_snprintf(s_factory_info->model_name, WPS_MAX_MODEL_NUMBER_LEN, "ESPRESSIF IOT");
1116     os_snprintf(s_factory_info->model_number, WPS_MAX_MODEL_NAME_LEN, "%s", CONFIG_SOC_SERIES);
1117     os_snprintf(s_factory_info->device_name, WPS_MAX_DEVICE_NAME_LEN, "%s STATION", CONFIG_SOC_SERIES);
1118 
1119     return ESP_OK;
1120 }
1121 
wps_set_factory_info(const esp_wps_config_t * config)1122 int wps_set_factory_info(const esp_wps_config_t *config)
1123 {
1124     int ret;
1125 
1126     ret = wps_set_default_factory();
1127     if (ret != 0) {
1128         return ret;
1129     }
1130 
1131     if (config->factory_info.manufacturer[0] != 0) {
1132         os_memcpy(s_factory_info->manufacturer, config->factory_info.manufacturer, WPS_MAX_MANUFACTURER_LEN - 1);
1133     }
1134 
1135     if (config->factory_info.model_number[0] != 0) {
1136         os_memcpy(s_factory_info->model_number, config->factory_info.model_number, WPS_MAX_MODEL_NUMBER_LEN - 1);
1137     }
1138 
1139     if (config->factory_info.model_name[0] != 0) {
1140         os_memcpy(s_factory_info->model_name, config->factory_info.model_name, WPS_MAX_MODEL_NAME_LEN - 1);
1141     }
1142 
1143     if (config->factory_info.device_name[0] != 0) {
1144         os_memcpy(s_factory_info->device_name, config->factory_info.device_name, WPS_MAX_DEVICE_NAME_LEN - 1);
1145     }
1146 
1147     wpa_printf(MSG_INFO, "manufacturer: %s, model number: %s, model name: %s, device name: %s", s_factory_info->manufacturer,
1148                s_factory_info->model_number, s_factory_info->model_name, s_factory_info->device_name);
1149 
1150     return ESP_OK;
1151 }
1152 
1153 
wps_dev_init(void)1154 int wps_dev_init(void)
1155 {
1156     int ret = 0;
1157     struct wps_sm *sm = gWpsSm;
1158     struct wps_device_data *dev = NULL;
1159 
1160     if (!sm) {
1161         ret = ESP_FAIL;
1162         goto _out;
1163     }
1164 
1165     dev = &sm->wps_ctx->dev;
1166     sm->dev = dev;
1167 
1168     if (!dev) {
1169         ret = ESP_FAIL;
1170         goto _out;
1171     }
1172     dev->config_methods = WPS_CONFIG_VIRT_PUSHBUTTON;
1173 #ifdef CONFIG_ESP_WIFI_WPS_PASSPHRASE
1174     dev->config_methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY;
1175 #endif
1176     dev->rf_bands = WPS_RF_24GHZ;
1177 
1178     WPA_PUT_BE16(dev->pri_dev_type, WPS_DEV_PHONE);
1179     WPA_PUT_BE32(dev->pri_dev_type + 2, WPS_DEV_OUI_WFA);
1180     WPA_PUT_BE16(dev->pri_dev_type + 6, WPS_DEV_PHONE_SINGLE_MODE);
1181 
1182     if (!s_factory_info) {
1183         ret = wps_set_default_factory();
1184         if (ret != 0) {
1185             goto _out;
1186         }
1187     }
1188 
1189     dev->manufacturer = os_zalloc(WPS_MAX_MANUFACTURER_LEN);
1190     if (!dev->manufacturer) {
1191         ret = ESP_FAIL;
1192         goto _out;
1193     }
1194     os_snprintf(dev->manufacturer, WPS_MAX_MANUFACTURER_LEN, "%s", s_factory_info->manufacturer);
1195 
1196     dev->model_name = os_zalloc(WPS_MAX_MODEL_NAME_LEN);
1197     if (!dev->model_name) {
1198         ret = ESP_FAIL;
1199         goto _out;
1200     }
1201     os_snprintf(dev->model_name, WPS_MAX_MODEL_NAME_LEN, "%s", s_factory_info->model_name);
1202 
1203     dev->model_number = os_zalloc(WPS_MAX_MODEL_NAME_LEN);
1204     if (!dev->model_number) {
1205         ret = ESP_FAIL;
1206         goto _out;
1207     }
1208     os_snprintf(dev->model_number, WPS_MAX_MODEL_NAME_LEN, "%s", s_factory_info->model_number);
1209 
1210     dev->device_name = os_zalloc(WPS_MAX_DEVICE_NAME_LEN);
1211     if (!dev->device_name) {
1212         ret = ESP_FAIL;
1213         goto _out;
1214     }
1215     os_snprintf(dev->device_name, WPS_MAX_DEVICE_NAME_LEN, "%s", s_factory_info->device_name);
1216 
1217     dev->serial_number = os_zalloc(16);
1218     if (!dev->serial_number) {
1219         ret = ESP_FAIL;
1220         goto _out;
1221     }
1222     os_snprintf(dev->serial_number, 16, "%02x%02x%02x%02x%02x%02x",
1223             sm->ownaddr[0], sm->ownaddr[1], sm->ownaddr[2],
1224             sm->ownaddr[3], sm->ownaddr[4], sm->ownaddr[5]);
1225 
1226     uuid_gen_mac_addr(sm->ownaddr, sm->uuid);
1227     os_memcpy(dev->mac_addr, sm->ownaddr, ETH_ALEN);
1228 
1229     return ESP_OK;
1230 
1231 _out:
1232     wps_dev_deinit(dev);
1233     return ret;
1234 }
1235 
1236 
wps_dev_deinit(struct wps_device_data * dev)1237 int wps_dev_deinit(struct wps_device_data *dev)
1238 {
1239     int ret = 0;
1240 
1241     if (!dev) {
1242         return ESP_FAIL;
1243     }
1244     wps_device_data_free(dev);
1245 
1246     if (s_factory_info) {
1247         os_free(s_factory_info);
1248         s_factory_info = NULL;
1249     }
1250 
1251     return ret;
1252 }
1253 
1254 void
wifi_station_wps_timeout_internal(void)1255 wifi_station_wps_timeout_internal(void)
1256 {
1257     struct wps_sm *sm = gWpsSm;
1258 
1259     if (!sm) {
1260         return;
1261     }
1262 
1263     esp_wifi_disarm_sta_connection_timer_internal();
1264 
1265     wps_set_status(WPS_STATUS_DISABLE);
1266 
1267     esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_TIMEOUT, 0, 0, OS_BLOCK);
1268 }
1269 
wifi_station_wps_timeout(void * data,void * user_ctx)1270 void wifi_station_wps_timeout(void *data, void *user_ctx)
1271 {
1272 #ifdef USE_WPS_TASK
1273     wps_post(SIG_WPS_TIMER_TIMEOUT, 0);
1274     return;
1275 #else
1276     wifi_station_wps_timeout_internal();
1277 #endif
1278 }
1279 
1280 void
wifi_station_wps_msg_timeout_internal(void)1281 wifi_station_wps_msg_timeout_internal(void)
1282 {
1283     struct wps_sm *sm = gWpsSm;
1284     if (!sm) {
1285         return;
1286     }
1287 
1288     if (sm->wps->state == WPS_FINISHED) {
1289         wpa_printf(MSG_DEBUG, "wps msg timeout WPS_FINISHED");
1290         wps_finish();
1291         return;
1292     } else if (sm->wps->state == RECV_M2) {
1293         wpa_printf(MSG_DEBUG, "wps msg timeout RECV_M2");
1294         if (!sm->ignore_sel_reg) {
1295             wps_stop_process(WPS_FAIL_REASON_RECV_M2D);
1296         }
1297     }
1298     if (sm->ignore_sel_reg) {
1299         esp_wifi_disconnect();
1300         wps_add_discard_ap(sm->bssid);
1301         os_bzero(sm->creds, sizeof(sm->creds));
1302         os_bzero(sm->bssid, ETH_ALEN);
1303         sm->discover_ssid_cnt = 0;
1304         wifi_wps_scan(NULL, NULL);
1305     }
1306 }
1307 
wifi_station_wps_msg_timeout(void * data,void * user_ctx)1308 void wifi_station_wps_msg_timeout(void *data, void *user_ctx)
1309 {
1310 #ifdef USE_WPS_TASK
1311     wps_post(SIG_WPS_TIMER_MSG_TIMEOUT, 0);
1312     return;
1313 #else
1314     wifi_station_wps_msg_timeout_internal();
1315 #endif
1316 }
1317 
wifi_station_wps_success_internal(void)1318 void wifi_station_wps_success_internal(void)
1319 {
1320     wifi_event_sta_wps_er_success_t evt = {0};
1321     struct wps_sm *sm = gWpsSm;
1322     int i;
1323 
1324     /*
1325      * For only one AP credential don't send event data, wps_finish() has already set
1326      * the config. This is for backward compatibility.
1327      */
1328     if (sm->ap_cred_cnt > 1) {
1329         evt.ap_cred_cnt = sm->ap_cred_cnt;
1330         for (i = 0; i < MAX_WPS_AP_CRED; i++) {
1331             os_memcpy(evt.ap_cred[i].ssid, sm->creds[i].ssid, sm->creds[i].ssid_len);
1332             os_memcpy(evt.ap_cred[i].passphrase, sm->creds[i].key, sm->creds[i].key_len);
1333         }
1334         esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_SUCCESS, &evt,
1335                                 sizeof(evt), OS_BLOCK);
1336     } else {
1337         esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_SUCCESS,
1338                                 0, 0, OS_BLOCK);
1339     }
1340 }
1341 
wifi_station_wps_success(void * data,void * user_ctx)1342 void wifi_station_wps_success(void *data, void *user_ctx)
1343 {
1344 #ifdef USE_WPS_TASK
1345     wps_post(SIG_WPS_TIMER_SUCCESS_CB, 0);
1346     return;
1347 #else
1348     wifi_station_wps_success_internal();
1349 #endif
1350 }
1351 
wifi_station_wps_eapol_start_handle_internal(void)1352 void wifi_station_wps_eapol_start_handle_internal(void)
1353 {
1354     wpa_printf(MSG_DEBUG, "Resend EAPOL-Start.");
1355     wps_tx_start();
1356 }
1357 
wifi_station_wps_eapol_start_handle(void * data,void * user_ctx)1358 void wifi_station_wps_eapol_start_handle(void *data, void *user_ctx)
1359 {
1360 #ifdef USE_WPS_TASK
1361     wps_post(SIG_WPS_TIMER_EAPOL_START, 0);
1362     return;
1363 #else
1364     wifi_station_wps_eapol_start_handle_internal();
1365 #endif
1366 }
1367 
save_credentials_cb(void * ctx,const struct wps_credential * cred)1368 static int save_credentials_cb(void *ctx, const struct wps_credential *cred)
1369 {
1370     struct wps_credential *creds;
1371     if (!gWpsSm || !cred || gWpsSm->ap_cred_cnt >= MAX_CRED_COUNT) {
1372         return ESP_FAIL;
1373     }
1374 
1375     creds = &gWpsSm->creds[gWpsSm->ap_cred_cnt];
1376     memcpy(creds, cred, sizeof(*creds));
1377 
1378     gWpsSm->ap_cred_cnt++;
1379 
1380     wpa_hexdump_ascii(MSG_DEBUG, "ssid ", cred->ssid, cred->ssid_len);
1381     wpa_hexdump_ascii(MSG_DEBUG, "key ", cred->key, cred->key_len);
1382 
1383     return ESP_OK;
1384 }
1385 
wps_init_cfg_pin(struct wps_config * cfg)1386 int wps_init_cfg_pin(struct wps_config *cfg)
1387 {
1388     if (wps_get_type() != WPS_TYPE_PIN) {
1389         cfg->pbc = 1;
1390         return 0;
1391     }
1392 
1393     cfg->pbc = 0;
1394 
1395     if ((os_strncmp((char *)cfg->pin, "00000000", 8) == 0) || !wps_pin_str_valid((char *)cfg->pin)) {
1396         unsigned int spin = 0;
1397 
1398         cfg->dev_pw_id = DEV_PW_DEFAULT;
1399         cfg->pin_len = 8;
1400         if (wps_generate_pin(&spin) < 0) {
1401             return -1;
1402 	}
1403         wpa_printf(MSG_INFO, "Provided PIN %s is not valid, generated a new PIN %08d", (char *)cfg->pin, spin);
1404         os_snprintf((char *)cfg->pin, 9, "%08d", spin);
1405     }
1406 
1407     return 0;
1408 }
1409 
wps_get_wps_sm_cb(void)1410 struct wps_sm_funcs* wps_get_wps_sm_cb(void)
1411 {
1412     return s_wps_sm_cb;
1413 }
1414 
wifi_station_wps_init(const esp_wps_config_t * config)1415 static int wifi_station_wps_init(const esp_wps_config_t *config)
1416 {
1417     struct wps_funcs *wps_cb;
1418     struct wps_sm *sm = NULL;
1419     struct wps_config cfg = {0};
1420 
1421     if (gWpsSm) {
1422         goto _out;
1423     }
1424 
1425     wpa_printf(MSG_DEBUG, "wifi sta wps init");
1426 
1427     gWpsSm = os_zalloc(sizeof(struct wps_sm));   /* alloc Wps_sm */
1428     if (!gWpsSm) {
1429         goto _out;
1430     }
1431 
1432     sm = gWpsSm;
1433 
1434     esp_wifi_get_macaddr_internal(WIFI_IF_STA, sm->ownaddr);
1435     os_memcpy(gWpaSm.own_addr, sm->ownaddr, ETH_ALEN);
1436 
1437     sm->identity_len = WSC_ID_ENROLLEE_LEN;
1438     os_memcpy(sm->identity, WSC_ID_ENROLLEE, sm->identity_len);
1439 
1440     sm->wps_ctx = os_zalloc(sizeof(struct wps_context)); /* alloc wps_ctx */
1441     if (!sm->wps_ctx) {
1442         goto _err;
1443     }
1444 
1445     if (wps_dev_init() != 0) {
1446         goto _err;
1447     }
1448 
1449     cfg.wps = sm->wps_ctx;
1450 
1451     os_memcpy((void *)cfg.pin, config->pin, 8);
1452     if (wps_init_cfg_pin(&cfg) < 0) {
1453         goto _err;
1454     }
1455 
1456     os_memcpy(cfg.wps->uuid, sm->uuid, WPS_UUID_LEN);
1457     cfg.wps->config_methods = sm->wps_ctx->dev.config_methods;
1458     if ((sm->wps = wps_init(&cfg)) == NULL) {         /* alloc wps_data */
1459         goto _err;
1460     }
1461 
1462     /* Report PIN */
1463     if (wps_get_type() == WPS_TYPE_PIN) {
1464         wifi_event_sta_wps_er_pin_t evt;
1465         os_memcpy(evt.pin_code, sm->wps->dev_password, 8);
1466         esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_PIN, &evt, sizeof(evt), OS_BLOCK);
1467     }
1468 
1469     sm->wps->wps->cred_cb = save_credentials_cb;
1470     /**************80211 reference***************/
1471 
1472     if (esp_wifi_get_appie_internal(WIFI_APPIE_WPS_PR) == NULL) {            /* alloc probe req wps ie */
1473         wps_build_ic_appie_wps_pr();
1474     }
1475 
1476     if (esp_wifi_get_appie_internal(WIFI_APPIE_WPS_AR) == NULL) {           /* alloc assoc req wps ie */
1477         wps_build_ic_appie_wps_ar();
1478     }
1479 
1480     eloop_cancel_timeout(wifi_station_wps_timeout, NULL, NULL);
1481     eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL);
1482     eloop_cancel_timeout(wifi_station_wps_success, NULL, NULL);
1483     eloop_cancel_timeout(wifi_wps_scan, NULL, NULL);
1484     eloop_cancel_timeout(wifi_station_wps_eapol_start_handle, NULL, NULL);
1485 
1486     wps_cb = os_malloc(sizeof(struct wps_funcs));
1487     if (wps_cb == NULL) {
1488         goto _err;
1489     }
1490     wps_cb->wps_parse_scan_result = wps_parse_scan_result;
1491     wps_cb->wifi_station_wps_start = wifi_station_wps_start;
1492     wps_cb->wps_sm_rx_eapol = wps_sm_rx_eapol;
1493     wps_cb->wps_start_pending = wps_start_pending;
1494     esp_wifi_set_wps_cb_internal(wps_cb);
1495 
1496     s_wps_sm_cb = os_malloc(sizeof(struct wps_sm_funcs));
1497     if (s_wps_sm_cb == NULL) {
1498         goto _err;
1499     }
1500     s_wps_sm_cb->wps_sm_notify_deauth = wps_sm_notify_deauth;
1501 
1502     return ESP_OK;
1503 
1504 _err:
1505     esp_wifi_unset_appie_internal(WIFI_APPIE_WPS_PR);
1506     esp_wifi_unset_appie_internal(WIFI_APPIE_WPS_AR);
1507 
1508     if (sm->dev) {
1509         wps_dev_deinit(sm->dev);
1510         sm->dev = NULL;
1511     }
1512     if (sm->wps_ctx) {
1513         if (sm->wps_ctx->dh_privkey) {
1514             wpabuf_free(sm->wps_ctx->dh_privkey);
1515         }
1516         os_free(sm->wps_ctx);
1517         sm->wps_ctx = NULL;
1518     }
1519     if (sm->wps) {
1520         wps_deinit(sm->wps);
1521         sm->wps = NULL;
1522     }
1523     os_free(gWpsSm);
1524     gWpsSm = NULL;
1525     return ESP_FAIL;
1526 _out:
1527     return ESP_FAIL;
1528 }
1529 
wps_delete_timer(void)1530 int wps_delete_timer(void)
1531 {
1532     struct wps_sm *sm = gWpsSm;
1533 
1534     if (!sm) {
1535         return ESP_OK;
1536     }
1537 
1538     eloop_cancel_timeout(wifi_station_wps_success, NULL, NULL);
1539     eloop_cancel_timeout(wifi_station_wps_timeout, NULL, NULL);
1540     eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL);
1541     eloop_cancel_timeout(wifi_wps_scan, NULL, NULL);
1542     eloop_cancel_timeout(wifi_station_wps_eapol_start_handle, NULL, NULL);
1543     esp_wifi_disarm_sta_connection_timer_internal();
1544     return ESP_OK;
1545 }
1546 
1547 int
wifi_station_wps_deinit(void)1548 wifi_station_wps_deinit(void)
1549 {
1550     struct wps_sm *sm = gWpsSm;
1551 
1552     if (gWpsSm == NULL) {
1553         return ESP_FAIL;
1554     }
1555 
1556     esp_wifi_unset_appie_internal(WIFI_APPIE_WPS_PR);
1557     esp_wifi_unset_appie_internal(WIFI_APPIE_WPS_AR);
1558     esp_wifi_set_wps_cb_internal(NULL);
1559 
1560     if (sm->dev) {
1561         wps_dev_deinit(sm->dev);
1562         sm->dev = NULL;
1563     }
1564     if (sm->wps_ctx) {
1565         if (sm->wps_ctx->dh_privkey) {
1566             wpabuf_free(sm->wps_ctx->dh_privkey);
1567         }
1568         os_free(sm->wps_ctx);
1569         sm->wps_ctx = NULL;
1570     }
1571     if (sm->wps) {
1572         wps_deinit(sm->wps);
1573         sm->wps = NULL;
1574     }
1575     if (s_wps_sm_cb) {
1576         os_free(s_wps_sm_cb);
1577         s_wps_sm_cb = NULL;
1578     }
1579 
1580     os_free(gWpsSm);
1581     gWpsSm = NULL;
1582 
1583     return ESP_OK;
1584 }
1585 
1586 struct wps_sm *
wps_sm_get(void)1587 wps_sm_get(void)
1588 {
1589     return gWpsSm;
1590 }
1591 
1592 void
wifi_wps_scan_done(void * arg,ETS_STATUS status)1593 wifi_wps_scan_done(void *arg, ETS_STATUS status)
1594 {
1595     struct wps_sm *sm = gWpsSm;
1596     wifi_config_t wifi_config = {0};
1597 
1598     wpa_printf(MSG_INFO, "WPS: scan done");
1599     if (wps_get_type() == WPS_TYPE_DISABLE) {
1600         return;
1601     }
1602 
1603     if (!sm) {
1604         return;
1605     }
1606 
1607     if (sm->discover_ssid_cnt == 1) {
1608         wps_set_status(WPS_STATUS_PENDING);
1609     } else if (sm->discover_ssid_cnt == 0)  {
1610         wps_set_status(WPS_STATUS_SCANNING);
1611     } else {
1612         if (wps_get_type() == WPS_TYPE_PBC) {
1613             wpa_printf(MSG_INFO, "PBC session overlap!");
1614             wps_set_status(WPS_STATUS_DISABLE);
1615             esp_event_post(WIFI_EVENT, WIFI_EVENT_STA_WPS_ER_PBC_OVERLAP, 0, 0, OS_BLOCK);
1616         } else {
1617             wps_set_status(WPS_STATUS_PENDING);
1618         }
1619     }
1620 
1621     wpa_printf(MSG_DEBUG, "wps scan_done discover_ssid_cnt = %d", sm->discover_ssid_cnt);
1622 
1623     sm->discover_ssid_cnt = 0;
1624 
1625     if (wps_get_status() == WPS_STATUS_PENDING) {
1626         esp_wifi_disconnect();
1627 
1628         os_memcpy(wifi_config.sta.bssid, sm->bssid, ETH_ALEN);
1629         os_memcpy(wifi_config.sta.ssid, (char *)sm->creds[0].ssid, sm->creds[0].ssid_len);
1630         wifi_config.sta.bssid_set = 1;
1631         wifi_config.sta.channel = sm->channel;
1632         wpa_printf(MSG_INFO, "WPS: connecting to %s, bssid=" MACSTR,
1633                    (char *)sm->creds[0].ssid, MAC2STR(wifi_config.sta.bssid));
1634         esp_wifi_set_config(0, &wifi_config);
1635 
1636         wpa_printf(MSG_DEBUG, "WPS: neg start");
1637         wifi_config.sta.failure_retry_cnt = 2;
1638         esp_wifi_connect();
1639         sm->state = WAIT_START;
1640         eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL);
1641         eloop_register_timeout(2, 0, wifi_station_wps_msg_timeout, NULL, NULL);
1642     } else if (wps_get_status() == WPS_STATUS_SCANNING) {
1643         if (wps_get_type() == WPS_TYPE_PIN && sm->scan_cnt > WPS_IGNORE_SEL_REG_MAX_CNT) {
1644             wpa_printf(MSG_INFO, "WPS: ignore selected registrar after %d scans", sm->scan_cnt);
1645             sm->ignore_sel_reg = true;
1646         }
1647         eloop_cancel_timeout(wifi_wps_scan, NULL, NULL);
1648         eloop_register_timeout(0, 100*1000, wifi_wps_scan, NULL, NULL);
1649     } else {
1650         return;
1651     }
1652 }
1653 
1654 void
wifi_wps_scan_internal(void)1655 wifi_wps_scan_internal(void)
1656 {
1657     struct wps_sm *sm = gWpsSm;
1658 
1659     sm->scan_cnt++;
1660     wpa_printf(MSG_DEBUG, "wifi_wps_scan : %d", sm->scan_cnt);
1661 
1662     typedef void (* scan_done_cb_t)(void *arg, ETS_STATUS status);
1663     extern int esp_wifi_promiscuous_scan_start(wifi_scan_config_t *config, scan_done_cb_t cb);
1664     esp_wifi_promiscuous_scan_start(NULL, wifi_wps_scan_done);
1665 }
1666 
wifi_wps_scan(void * data,void * user_ctx)1667 void wifi_wps_scan(void *data, void *user_ctx)
1668 {
1669 #ifdef USE_WPS_TASK
1670     wps_post(SIG_WPS_TIMER_SCAN, 0);
1671     return;
1672 #else
1673     wifi_wps_scan_internal();
1674 #endif
1675 }
1676 
wps_rf_band_cb(void * ctx)1677 static int wps_rf_band_cb(void *ctx)
1678 {
1679 	return WPS_RF_24GHZ;
1680 }
1681 
wifi_station_wps_start(void)1682 int wifi_station_wps_start(void)
1683 {
1684     struct wps_sm *sm = wps_sm_get();
1685 
1686     if (!sm) {
1687         wpa_printf(MSG_ERROR, "WPS: wps is not initialized");
1688         return ESP_FAIL;
1689     }
1690 
1691     eloop_register_timeout(120, 0, wifi_station_wps_timeout, NULL, NULL);
1692 
1693     switch (wps_get_status()) {
1694     case WPS_STATUS_DISABLE: {
1695         sm->is_wps_scan = true;
1696 
1697         wps_build_public_key(sm->wps, NULL);
1698         if (sm->wps->wps->dh_privkey) {
1699             wpabuf_free(sm->wps->wps->dh_privkey);
1700         }
1701         sm->wps->wps->dh_privkey = sm->wps->dh_privkey;
1702         sm->wps->wps->dh_ctx = sm->wps->dh_ctx;
1703         sm->wps->wps->dh_pubkey = sm->wps->dh_pubkey_e;
1704         sm->wps->wps->rf_band_cb = wps_rf_band_cb;
1705         sm->wps->dh_privkey = NULL;
1706         wifi_wps_scan(NULL, NULL);
1707         break;
1708     }
1709     case WPS_STATUS_SCANNING:
1710         sm->scan_cnt = 0;
1711         eloop_cancel_timeout(wifi_station_wps_timeout, NULL, NULL);
1712         eloop_register_timeout(120, 0, wifi_station_wps_timeout, NULL, NULL);
1713         break;
1714     default:
1715         break;
1716     }
1717     sm->discard_ap_cnt = 0;
1718     os_memset(&sm->dis_ap_list, 0, WPS_MAX_DIS_AP_NUM * sizeof(struct discard_ap_list_t));
1719     esp_wifi_set_wps_start_flag_internal(true);
1720     return ESP_OK;
1721 }
1722 
wps_task_deinit(void)1723 int wps_task_deinit(void)
1724 {
1725     wpa_printf(MSG_DEBUG, "wps task deinit");
1726 
1727     if (s_wps_api_sem) {
1728         os_semphr_delete(s_wps_api_sem);
1729         s_wps_api_sem = NULL;
1730         wpa_printf(MSG_DEBUG, "wps task deinit: free api sem");
1731     }
1732 
1733     if (s_wps_task_create_sem) {
1734         os_semphr_delete(s_wps_task_create_sem);
1735         s_wps_task_create_sem = NULL;
1736         wpa_printf(MSG_DEBUG, "wps task deinit: free task create sem");
1737     }
1738 
1739     if (s_wps_queue) {
1740         os_queue_delete(s_wps_queue);
1741         s_wps_queue = NULL;
1742         wpa_printf(MSG_DEBUG, "wps task deinit: free queue");
1743     }
1744 
1745     if (STAILQ_FIRST(&s_wps_rxq) != NULL){
1746         wps_rxq_deinit();
1747     }
1748 
1749     if (s_wps_data_lock) {
1750         os_mutex_delete(s_wps_data_lock);
1751         s_wps_data_lock = NULL;
1752     }
1753 
1754     return ESP_OK;
1755 }
1756 
wps_task_init(void)1757 int wps_task_init(void)
1758 {
1759     int ret = 0;
1760 
1761     /* Call wps_task_deinit() first in case esp_wifi_wps_disable() fails
1762      */
1763     wps_task_deinit();
1764 
1765     if (!s_wps_data_lock) {
1766         s_wps_data_lock = os_recursive_mutex_create();
1767         if (!s_wps_data_lock) {
1768             wpa_printf(MSG_ERROR, "wps task init: failed to alloc data lock");
1769             goto _wps_no_mem;
1770         }
1771     }
1772 
1773     s_wps_api_sem = os_semphr_create(1, 0);
1774     if (!s_wps_api_sem) {
1775         wpa_printf(MSG_ERROR, "wps task init: failed to create api sem");
1776         goto _wps_no_mem;
1777     }
1778 
1779     s_wps_task_create_sem = os_semphr_create(1, 0);
1780     if (!s_wps_task_create_sem) {
1781         wpa_printf(MSG_ERROR, "wps task init: failed to create task sem");
1782         goto _wps_no_mem;
1783     }
1784 
1785     os_bzero(s_wps_sig_cnt, SIG_WPS_NUM);
1786     s_wps_queue = os_queue_create(SIG_WPS_NUM, sizeof(ETSEvent));
1787     if (!s_wps_queue) {
1788         wpa_printf(MSG_ERROR, "wps task init: failed to alloc queue");
1789         goto _wps_no_mem;
1790     }
1791 
1792     wps_rxq_init();
1793 
1794     ret = os_task_create(wps_task, "wpsT", WPS_TASK_STACK_SIZE, NULL, 2, &s_wps_task_hdl);
1795     if (TRUE != ret) {
1796         wpa_printf(MSG_ERROR, "wps enable: failed to create task");
1797         goto _wps_no_mem;
1798     }
1799 
1800     os_semphr_take(s_wps_task_create_sem, OS_BLOCK);
1801     os_semphr_delete(s_wps_task_create_sem);
1802     s_wps_task_create_sem = NULL;
1803 
1804     wpa_printf(MSG_DEBUG, "wifi wps enable: task prio:%d, stack:%d", 2, WPS_TASK_STACK_SIZE);
1805     return ESP_OK;
1806 
1807 _wps_no_mem:
1808     wps_task_deinit();
1809     return ESP_ERR_NO_MEM;
1810 }
1811 
wps_post_block(uint32_t sig,void * arg)1812 int wps_post_block(uint32_t sig, void *arg)
1813 {
1814     wps_ioctl_param_t param;
1815 
1816     param.ret = ESP_FAIL;
1817     param.arg = arg;
1818 
1819     if (ESP_OK != wps_post(sig, (uint32_t)&param)) {
1820         return ESP_FAIL;
1821     }
1822 
1823     if (TRUE == os_semphr_take(s_wps_api_sem, OS_BLOCK)) {
1824         return param.ret;
1825     } else {
1826         return ESP_FAIL;
1827     }
1828 }
1829 
wps_check_wifi_mode(void)1830 int wps_check_wifi_mode(void)
1831 {
1832     wifi_mode_t mode;
1833     int ret;
1834 
1835     ret = esp_wifi_get_mode(&mode);
1836     if (ESP_OK != ret) {
1837         wpa_printf(MSG_ERROR, "wps check wifi mode: failed to get wifi mode ret=%d", ret);
1838         return ESP_FAIL;
1839     }
1840 
1841     if (
1842 #ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
1843         mode == ESP32_WIFI_MODE_AP ||
1844 #endif
1845         mode == ESP32_WIFI_MODE_NULL) {
1846         wpa_printf(MSG_ERROR, "wps check wifi mode: wrong wifi mode=%d ", mode);
1847         return ESP_ERR_WIFI_MODE;
1848     }
1849 
1850     return ESP_OK;
1851 }
1852 
esp_wifi_wps_enable(const esp_wps_config_t * config)1853 int esp_wifi_wps_enable(const esp_wps_config_t *config)
1854 {
1855     int ret = ESP_OK;
1856     struct wps_sm *sm = gWpsSm;
1857 
1858     if (esp_wifi_get_user_init_flag_internal() == 0) {
1859         wpa_printf(MSG_ERROR, "wps enable: wifi not started cannot disable wpsreg");
1860         return ESP_ERR_WIFI_STATE;
1861     }
1862 
1863     if (ESP_OK != wps_check_wifi_mode()) {
1864         return ESP_ERR_WIFI_MODE;
1865     }
1866 
1867     if (is_dpp_enabled()) {
1868         wpa_printf(MSG_ERROR, "wps enabled failed since DPP is initialized");
1869         return ESP_FAIL;
1870     }
1871 
1872     API_MUTEX_TAKE();
1873     if (s_wps_enabled) {
1874         if (sm && os_memcmp(sm->identity, WSC_ID_REGISTRAR, sm->identity_len) == 0) {
1875             wpa_printf(MSG_ERROR, "wps enable: wpsreg already enabled cannot enable wps enrollee");
1876             ret = ESP_ERR_WIFI_MODE;
1877         } else {
1878             wpa_printf(MSG_DEBUG, "wps enable: already enabled");
1879         }
1880         API_MUTEX_GIVE();
1881         return ret;
1882     }
1883 
1884 #ifdef USE_WPS_TASK
1885     ret = wps_task_init();
1886     if (ESP_OK != ret) {
1887         API_MUTEX_GIVE();
1888         return ret;
1889     }
1890 
1891     ret = wps_post_block(SIG_WPS_ENABLE, (esp_wps_config_t *)config);
1892     if (ESP_OK != ret) {
1893         wps_task_deinit();
1894         API_MUTEX_GIVE();
1895         return ret;
1896     }
1897 
1898     s_wps_enabled = true;
1899     wpa_printf(MSG_DEBUG, "wifi wps task: prio:%d, stack:%d", 2, WPS_TASK_STACK_SIZE);
1900     API_MUTEX_GIVE();
1901     return ret;
1902 #else
1903     ret = wifi_wps_enable_internal(config);
1904     API_MUTEX_GIVE();
1905     return ret;
1906 #endif
1907 }
1908 
is_wps_enabled(void)1909 bool is_wps_enabled(void)
1910 {
1911     return s_wps_enabled;
1912 }
1913 
wifi_wps_enable_internal(const esp_wps_config_t * config)1914 int wifi_wps_enable_internal(const esp_wps_config_t *config)
1915 {
1916     int ret = 0;
1917     struct wpa_sm *wpa_sm = &gWpaSm;
1918 
1919     wpa_printf(MSG_DEBUG, "ESP WPS crypto initialize!");
1920     if (config->wps_type == WPS_TYPE_DISABLE) {
1921         wpa_printf(MSG_ERROR, "wps enable: invalid wps type");
1922         return ESP_ERR_WIFI_WPS_TYPE;
1923     }
1924     if (is_dpp_enabled()) {
1925         wpa_printf(MSG_ERROR, "wps enabled failed since DPP is initialized");
1926         return ESP_FAIL;
1927     }
1928     wpa_printf(MSG_DEBUG, "Set factory information.");
1929     ret = wps_set_factory_info(config);
1930     if (ret != 0) {
1931         return ret;
1932     }
1933 
1934     wpa_printf(MSG_INFO, "wifi_wps_enable");
1935 
1936     wps_set_type(config->wps_type);
1937     wps_set_status(WPS_STATUS_DISABLE);
1938 
1939     ret = wifi_station_wps_init(config);
1940 
1941     if (ret != 0) {
1942         wps_set_type(WPS_TYPE_DISABLE);
1943         wps_set_status(WPS_STATUS_DISABLE);
1944         return ESP_FAIL;
1945     }
1946     wpa_sm->wpa_sm_wps_disable = esp_wifi_wps_disable;
1947     return ESP_OK;
1948 }
1949 
wifi_wps_disable_internal(void)1950 int wifi_wps_disable_internal(void)
1951 {
1952     wps_set_status(WPS_STATUS_DISABLE);
1953 
1954     /* Call wps_delete_timer to delete all WPS timer, no timer will call wps_post()
1955      * to post message to wps_task once this function returns.
1956      */
1957     wps_delete_timer();
1958     wifi_station_wps_deinit();
1959     return ESP_OK;
1960 }
1961 
esp_wifi_wps_disable(void)1962 int esp_wifi_wps_disable(void)
1963 {
1964     int ret = 0;
1965     int wps_status;
1966     struct wps_sm *wps_sm = gWpsSm;
1967     struct wpa_sm *wpa_sm = &gWpaSm;
1968 
1969     if (wps_sm && os_memcmp(wps_sm->identity, WSC_ID_REGISTRAR, wps_sm->identity_len) == 0) {
1970         return ESP_ERR_WIFI_MODE;
1971     }
1972 
1973     API_MUTEX_TAKE();
1974 
1975     if (!s_wps_enabled) {
1976         wpa_printf(MSG_DEBUG, "wps disable: already disabled");
1977         API_MUTEX_GIVE();
1978         return ESP_OK;
1979     }
1980 
1981     wps_status = wps_get_status();
1982     wpa_printf(MSG_INFO, "wifi_wps_disable");
1983     wps_set_type(WPS_TYPE_DISABLE); /* Notify WiFi task */
1984 
1985 #ifdef USE_WPS_TASK
1986     ret = wps_post_block(SIG_WPS_DISABLE, 0);
1987 #else
1988     ret = wifi_wps_disable_internal();
1989 #endif
1990 
1991     if (ESP_OK != ret) {
1992         wpa_printf(MSG_ERROR, "wps disable: failed to disable wps, ret=%d", ret);
1993     }
1994 
1995     /* Only disconnect in case of WPS pending/done */
1996     if ((wps_status == WPS_STATUS_PENDING) || (wps_status == WPS_STATUS_SUCCESS)) {
1997         esp_wifi_disconnect();
1998     }
1999     esp_wifi_set_wps_start_flag_internal(false);
2000     wps_task_deinit();
2001     s_wps_enabled = false;
2002     API_MUTEX_GIVE();
2003     wpa_sm->wpa_sm_wps_disable = NULL;
2004     return ESP_OK;
2005 }
2006 
esp_wifi_wps_start(int timeout_ms)2007 int esp_wifi_wps_start(int timeout_ms)
2008 {
2009     if (ESP_OK != wps_check_wifi_mode()) {
2010         return ESP_ERR_WIFI_MODE;
2011     }
2012 
2013     API_MUTEX_TAKE();
2014 
2015     if (!s_wps_enabled) {
2016         wpa_printf(MSG_ERROR, "wps start: wps not enabled");
2017         API_MUTEX_GIVE();
2018         return ESP_ERR_WIFI_WPS_SM;
2019     }
2020 
2021     if (wps_get_type() == WPS_TYPE_DISABLE || (wps_get_status() != WPS_STATUS_DISABLE && wps_get_status() != WPS_STATUS_SCANNING)) {
2022         API_MUTEX_GIVE();
2023         return ESP_ERR_WIFI_WPS_TYPE;
2024     }
2025 
2026     if (esp_wifi_get_user_init_flag_internal() == 0) {
2027         API_MUTEX_GIVE();
2028         return ESP_ERR_WIFI_STATE;
2029     }
2030 
2031     wpa_printf(MSG_DEBUG, "wps scan");
2032 #ifdef USE_WPS_TASK
2033     wps_post_block(SIG_WPS_START, 0);
2034 #else
2035     ic_pp_post(SIG_PP_WPS, 0);
2036 #endif
2037     API_MUTEX_GIVE();
2038     return ESP_OK;
2039 }
2040