1 /*
2  * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "esp_dpp_i.h"
8 #include "esp_dpp.h"
9 #include "esp_wpa.h"
10 #include "esp_timer.h"
11 #include "esp_event.h"
12 #include "esp_wifi.h"
13 #include "common/ieee802_11_defs.h"
14 
15 static void *s_dpp_task_hdl = NULL;
16 static void *s_dpp_evt_queue = NULL;
17 static void *s_dpp_api_lock = NULL;
18 
19 static bool s_dpp_stop_listening;
20 static int s_dpp_auth_retries;
21 struct esp_dpp_context_t s_dpp_ctx;
22 static wifi_action_rx_cb_t s_action_rx_cb = esp_supp_rx_action;
23 
24 #define DPP_API_LOCK() xSemaphoreTakeRecursive(s_dpp_api_lock, portMAX_DELAY)
25 #define DPP_API_UNLOCK() xSemaphoreGiveRecursive(s_dpp_api_lock)
26 
27 struct action_rx_param {
28     u8 sa[ETH_ALEN];
29     u32 channel;
30     u32 frm_len;
31     u32 vendor_data_len;
32     struct ieee80211_action *action_frm;
33 };
34 
esp_dpp_post_evt(uint32_t evt_id,uint32_t data)35 static int esp_dpp_post_evt(uint32_t evt_id, uint32_t data)
36 {
37     DPP_API_LOCK();
38 
39     dpp_event_t *evt = os_zalloc(sizeof(dpp_event_t));
40     if (evt == NULL) {
41         DPP_API_UNLOCK();
42         return ESP_ERR_NO_MEM;
43     }
44     evt->id = evt_id;
45     evt->data = data;
46     if ( xQueueSend(s_dpp_evt_queue, &evt, 10 / portTICK_PERIOD_MS ) != pdPASS) {
47         DPP_API_UNLOCK();
48         os_free(evt);
49         return ESP_ERR_DPP_FAILURE;
50     }
51     DPP_API_UNLOCK();
52     return ESP_OK;
53 }
54 
esp_dpp_call_cb(esp_supp_dpp_event_t evt,void * data)55 static void esp_dpp_call_cb(esp_supp_dpp_event_t evt, void *data)
56 {
57     s_dpp_ctx.dpp_event_cb(evt, data);
58 }
59 
esp_send_action_frame(uint8_t * dest_mac,const uint8_t * buf,uint32_t len,uint8_t channel,uint32_t wait_time_ms)60 void esp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint32_t len,
61                            uint8_t channel, uint32_t wait_time_ms)
62 {
63     wifi_action_tx_req_t *req = os_zalloc(sizeof(*req) + len);;
64     if (!req) {
65         return;
66     }
67 
68     req->ifx = WIFI_IF_STA;
69     memcpy(req->dest_mac, dest_mac, ETH_ALEN);
70     req->no_ack = false;
71     req->data_len = len;
72     req->rx_cb = s_action_rx_cb;
73     memcpy(req->data, buf, req->data_len);
74 
75     wpa_printf(MSG_DEBUG, "DPP: Mgmt Tx - MAC:" MACSTR ", Channel-%d, WaitT-%d",
76                MAC2STR(dest_mac), channel, wait_time_ms);
77 
78     if (ESP_OK != esp_wifi_action_tx_req(WIFI_OFFCHAN_TX_REQ, channel,
79                                          wait_time_ms, req)) {
80         wpa_printf(MSG_ERROR, "DPP: Failed to perfrm offchannel operation");
81         esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE);
82         os_free(req);
83         return;
84     }
85 
86     os_free(req);
87 }
88 
esp_dpp_rx_auth_req(struct action_rx_param * rx_param,uint8_t * dpp_data)89 static void esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_data)
90 {
91     size_t len = rx_param->vendor_data_len - 2;
92     const u8 *r_bootstrap, *i_bootstrap;
93     u16 r_bootstrap_len, i_bootstrap_len;
94     struct dpp_bootstrap_info *own_bi;
95     int rc;
96 
97     wpa_printf(MSG_INFO, "DPP: Authentication Request from " MACSTR, MAC2STR(rx_param->sa));
98 
99     r_bootstrap = dpp_get_attr(dpp_data, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
100                                &r_bootstrap_len);
101     if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
102         wpa_printf(MSG_INFO, "DPP: Missing or invalid Responder Bootstrapping Key Hash attribute");
103         rc = ESP_ERR_DPP_INVALID_ATTR;
104         goto fail;
105     }
106     wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", r_bootstrap, r_bootstrap_len);
107 
108     i_bootstrap = dpp_get_attr(dpp_data, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
109                                &i_bootstrap_len);
110     if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
111         wpa_printf(MSG_INFO, "DPP: Missing or invalid Initiator Bootstrapping Key Hash attribute");
112         rc = ESP_ERR_DPP_INVALID_ATTR;
113         goto fail;
114     }
115     wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash", i_bootstrap, i_bootstrap_len);
116 
117     own_bi = dpp_bootstrap_get_id(s_dpp_ctx.dpp_global, s_dpp_ctx.id);
118     /* Try to find own and peer bootstrapping key matches based on the
119      * received hash values */
120     if (os_memcmp(own_bi->pubkey_hash, r_bootstrap, SHA256_MAC_LEN)) {
121         wpa_printf(MSG_INFO, "DPP: No matching own bootstrapping key found as responder - ignore message");
122         rc = ESP_ERR_DPP_INVALID_ATTR;
123         goto fail;
124     }
125 
126     s_dpp_ctx.dpp_auth = dpp_auth_req_rx(NULL, DPP_CAPAB_ENROLLEE, 0, NULL,
127                                          own_bi, rx_param->channel,
128                                          (const u8 *)&rx_param->action_frm->u.public_action.v, dpp_data, len);
129     os_memcpy(s_dpp_ctx.dpp_auth->peer_mac_addr, rx_param->sa, ETH_ALEN);
130 
131     esp_send_action_frame(rx_param->sa, wpabuf_head(s_dpp_ctx.dpp_auth->resp_msg),
132                           wpabuf_len(s_dpp_ctx.dpp_auth->resp_msg),
133                           rx_param->channel, OFFCHAN_TX_WAIT_TIME);
134     return;
135 fail:
136     esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)rc);
137 }
138 
gas_query_req_tx(struct dpp_authentication * auth)139 static void gas_query_req_tx(struct dpp_authentication *auth)
140 {
141     struct wpabuf *buf;
142     int supp_op_classes[] = {81, 0};
143 
144     buf = dpp_build_conf_req_helper(auth, NULL, 0, NULL,
145                                     supp_op_classes);
146     if (!buf) {
147         wpa_printf(MSG_DEBUG, "DPP: No configuration request data available");
148         esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE);
149         return;
150     }
151 
152     wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (chan %u)",
153                MAC2STR(auth->peer_mac_addr), auth->curr_chan);
154 
155     esp_send_action_frame(auth->peer_mac_addr, wpabuf_head(buf), wpabuf_len(buf),
156                           auth->curr_chan, OFFCHAN_TX_WAIT_TIME);
157 }
158 
esp_dpp_handle_config_obj(struct dpp_authentication * auth,struct dpp_config_obj * conf)159 static int esp_dpp_handle_config_obj(struct dpp_authentication *auth,
160                                      struct dpp_config_obj *conf)
161 {
162     wifi_config_t *wifi_cfg = &s_dpp_ctx.wifi_cfg;
163 
164     if (conf->ssid_len) {
165         os_memcpy(wifi_cfg->sta.ssid, conf->ssid, conf->ssid_len);
166     }
167 
168     if (dpp_akm_legacy(conf->akm)) {
169         if (conf->passphrase[0])
170             os_memcpy(wifi_cfg->sta.password, conf->passphrase,
171                       sizeof(wifi_cfg->sta.password));
172         if (conf->akm == DPP_AKM_PSK_SAE) {
173             wifi_cfg->sta.pmf_cfg.required = true;
174         }
175     }
176 
177     if (conf->connector) {
178         /* TODO: Save the Connector and consider using a command
179          * to fetch the value instead of sending an event with
180          * it. The Connector could end up being larger than what
181          * most clients are ready to receive as an event
182          * message. */
183         wpa_printf(MSG_INFO, DPP_EVENT_CONNECTOR "%s",
184                    conf->connector);
185     }
186     s_dpp_stop_listening = false;
187     esp_wifi_action_tx_req(WIFI_OFFCHAN_TX_CANCEL, 0, 0, NULL);
188     esp_dpp_call_cb(ESP_SUPP_DPP_CFG_RECVD, wifi_cfg);
189 
190     return 0;
191 }
192 
esp_dpp_rx_auth_conf(struct action_rx_param * rx_param,uint8_t * dpp_data)193 static void esp_dpp_rx_auth_conf(struct action_rx_param *rx_param, uint8_t *dpp_data)
194 {
195     struct dpp_authentication *auth = s_dpp_ctx.dpp_auth;
196     struct ieee80211_public_action *public_action =
197             &rx_param->action_frm->u.public_action;
198     size_t len = rx_param->vendor_data_len - 2;
199     int rc;
200 
201     wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
202                MAC2STR(rx_param->sa));
203 
204     if (!auth) {
205         wpa_printf(MSG_DEBUG, "DPP: No DPP Authentication in progress - drop");
206         rc = ESP_ERR_DPP_FAILURE;
207         goto fail;
208     }
209 
210     if (os_memcmp(rx_param->sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
211         wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
212                    MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
213         rc = ESP_ERR_DPP_FAILURE;
214         goto fail;
215     }
216 
217     if (dpp_auth_conf_rx(auth, (const u8 *)&public_action->v,
218                          dpp_data, len) < 0) {
219         wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
220         rc = ESP_ERR_DPP_FAILURE;
221         goto fail;
222     }
223 
224     /* Send GAS Query Req */
225     gas_query_req_tx(auth);
226 
227     return;
228 
229 fail:
230     esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)rc);
231 }
232 
esp_dpp_rx_auth(struct action_rx_param * rx_param)233 static void esp_dpp_rx_auth(struct action_rx_param *rx_param)
234 {
235     uint8_t crypto_suit, type;
236     uint8_t *tmp;
237 
238     tmp = rx_param->action_frm->u.public_action.v.pa_vendor_spec.vendor_data;
239     crypto_suit = tmp[0];
240     type = tmp[1];
241 
242     if (crypto_suit != 1) {
243         wpa_printf(MSG_ERROR, "DPP: Unsupported crypto suit");
244         esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_NOT_SUPPORTED);
245         return;
246     }
247 
248     switch (type) {
249     case DPP_PA_AUTHENTICATION_REQ:
250         esp_dpp_rx_auth_req(rx_param, &tmp[2]);
251         break;
252     case DPP_PA_AUTHENTICATION_CONF:
253         esp_dpp_rx_auth_conf(rx_param, &tmp[2]);
254         break;
255     }
256 }
257 
gas_query_resp_rx(struct action_rx_param * rx_param)258 static void gas_query_resp_rx(struct action_rx_param *rx_param)
259 {
260     struct dpp_authentication *auth = s_dpp_ctx.dpp_auth;
261     uint8_t *pos = rx_param->action_frm->u.public_action.v.pa_gas_resp.data;
262     uint8_t *resp = &pos[10];
263     int i, res;
264 
265     if (pos[1] == WLAN_EID_VENDOR_SPECIFIC && pos[2] == 5 &&
266             WPA_GET_BE24(&pos[3]) == OUI_WFA && pos[6] == 0x1a && pos[7] == 1) {
267         if (dpp_conf_resp_rx(auth, resp, rx_param->vendor_data_len - 2) < 0) {
268             wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
269             goto fail;
270         }
271 
272         for (i = 0; i < auth->num_conf_obj; i++) {
273             res = esp_dpp_handle_config_obj(auth, &auth->conf_obj[i]);
274             if (res < 0) {
275                 goto fail;
276             }
277         }
278     }
279 
280     return;
281 fail:
282     esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE);
283 }
284 
esp_dpp_rx_action(struct action_rx_param * rx_param)285 static void esp_dpp_rx_action(struct action_rx_param *rx_param)
286 {
287     if (rx_param->action_frm->category == WLAN_ACTION_PUBLIC) {
288         struct ieee80211_public_action *public_action =
289                 &rx_param->action_frm->u.public_action;
290 
291         wpa_printf(MSG_DEBUG, "DPP: Rx Public Action frame: action - %d",
292                    public_action->action);
293 
294         if (public_action->action == WLAN_PA_VENDOR_SPECIFIC &&
295                 WPA_GET_BE24(public_action->v.pa_vendor_spec.oui) == OUI_WFA &&
296                 public_action->v.pa_vendor_spec.wfa_stype == DPP_OUI_TYPE) {
297 
298             rx_param->vendor_data_len = rx_param->frm_len -
299                                         (size_t)(public_action->v.pa_vendor_spec.vendor_data -
300                                                  (u8 *)rx_param->action_frm);
301 
302             if (!s_dpp_stop_listening) {
303                 esp_supp_dpp_stop_listen();
304             }
305 
306             esp_dpp_rx_auth(rx_param);
307         } else if (public_action->action == WLAN_PA_GAS_INITIAL_RESP &&
308                    public_action->v.pa_gas_resp.type == WLAN_EID_ADV_PROTO &&
309                    public_action->v.pa_gas_resp.length == 8 &&
310                    public_action->v.pa_gas_resp.status_code == 0) {
311 
312             rx_param->vendor_data_len = rx_param->frm_len -
313                                         (size_t)(public_action->v.pa_gas_resp.data +
314                                                  public_action->v.pa_gas_resp.length -
315                                                  (u8 *)rx_param->action_frm);
316 
317             gas_query_resp_rx(rx_param);
318         }
319     }
320 
321     os_free(rx_param->action_frm);
322     os_free(rx_param);
323 }
324 
esp_dpp_task(void * pvParameters)325 static void esp_dpp_task(void *pvParameters )
326 {
327     dpp_event_t *evt;
328     bool task_del = false;
329 
330     for (;;) {
331         if (xQueueReceive(s_dpp_evt_queue, &evt, portMAX_DELAY) == pdTRUE) {
332             if (evt->id < SIG_DPP_MAX) {
333                 DPP_API_LOCK();
334             } else {
335                 os_free(evt);
336                 continue;
337             }
338 
339             switch (evt->id) {
340             case SIG_DPP_DEL_TASK:
341                 task_del = true;
342                 break;
343 
344             case SIG_DPP_BOOTSTRAP_GEN: {
345                 char *command = (char *)evt->data;
346                 const char *uri;
347 
348                 s_dpp_ctx.id = dpp_bootstrap_gen(s_dpp_ctx.dpp_global, command);
349                 uri = dpp_bootstrap_get_uri(s_dpp_ctx.dpp_global, s_dpp_ctx.id);
350 
351                 esp_dpp_call_cb(ESP_SUPP_DPP_URI_READY, (void *)uri);
352                 os_free(command);
353             }
354             break;
355 
356             case SIG_DPP_RX_ACTION: {
357                 esp_dpp_rx_action((struct action_rx_param *)evt->data);
358             }
359             break;
360 
361             case SIG_DPP_LISTEN_NEXT_CHANNEL: {
362                 struct dpp_bootstrap_params_t *p = &s_dpp_ctx.bootstrap_params;
363                 static int counter;
364                 int channel;
365 
366                 channel = p->chan_list[counter++ % p->num_chan];
367                 esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_REQ, channel,
368                                            BOOTSTRAP_ROC_WAIT_TIME, s_action_rx_cb);
369             }
370             break;
371 
372             default:
373                 break;
374             }
375 
376             os_free(evt);
377             DPP_API_UNLOCK();
378 
379             if (task_del) {
380                 break;
381             }
382         }
383     }
384 
385     vQueueDelete(s_dpp_evt_queue);
386     s_dpp_evt_queue = NULL;
387 
388     if (s_dpp_api_lock) {
389         vSemaphoreDelete(s_dpp_api_lock);
390         s_dpp_api_lock = NULL;
391     }
392 
393     /* At this point, we completed */
394     vTaskDelete(NULL);
395 }
396 
esp_supp_rx_action(uint8_t * hdr,uint8_t * payload,size_t len,uint8_t channel)397 int esp_supp_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel)
398 {
399     struct ieee80211_hdr *rx_hdr = (struct ieee80211_hdr *)hdr;
400     struct action_rx_param *rx_param;
401     int ret = ESP_ERR_NOT_SUPPORTED;
402 
403     if (WLAN_FC_GET_STYPE(rx_hdr->frame_control) == WLAN_FC_STYPE_ACTION) {
404         rx_param = os_zalloc(sizeof(struct action_rx_param));
405         if (!rx_param) {
406             wpa_printf(MSG_ERROR, "Failed to allocate memory for Rx Action");
407             return ESP_ERR_NO_MEM;
408         }
409         os_memcpy(rx_param->sa, rx_hdr->addr2, ETH_ALEN);
410         rx_param->channel = channel;
411         rx_param->action_frm = os_zalloc(len);
412         if (!rx_param->action_frm) {
413             wpa_printf(MSG_ERROR, "Failed to allocate memory for Rx Action");
414             os_free(rx_param);
415             return ESP_ERR_NO_MEM;
416         }
417         rx_param->frm_len = len;
418         os_memcpy(rx_param->action_frm, payload, len);
419 
420         ret = esp_dpp_post_evt(SIG_DPP_RX_ACTION, (u32)rx_param);
421         if (ESP_OK != ret) {
422             wpa_printf(MSG_ERROR, "Failed to post event to DPP Task(status=%d)", ret);
423             os_free(rx_param->action_frm);
424             os_free(rx_param);
425             return ret;
426         }
427     }
428 
429     return ret;
430 }
431 
offchan_event_handler(void * arg,esp_event_base_t event_base,int32_t event_id,void * event_data)432 static void offchan_event_handler(void *arg, esp_event_base_t event_base,
433                                   int32_t event_id, void *event_data)
434 {
435     if (event_id == WIFI_EVENT_ACTION_TX_STATUS) {
436         wifi_event_action_tx_status_t *evt =
437             (wifi_event_action_tx_status_t *)event_data;
438         wpa_printf(MSG_DEBUG, "Mgmt Tx Status - %d, Cookie - 0x%x",
439                    evt->status, (uint32_t)evt->context);
440 
441         if (evt->status) {
442             esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE);
443         }
444 
445     } else if (event_id == WIFI_EVENT_ROC_DONE) {
446         wifi_event_roc_done_t *evt = (wifi_event_roc_done_t *)event_data;
447 
448         if (!s_dpp_stop_listening && evt->context == (uint32_t)s_action_rx_cb) {
449             esp_dpp_post_evt(SIG_DPP_LISTEN_NEXT_CHANNEL, 0);
450         }
451     }
452 }
453 
esp_dpp_parse_chan_list(const char * chan_list)454 static char *esp_dpp_parse_chan_list(const char *chan_list)
455 {
456     struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params;
457     char *uri_channels = os_zalloc(14 * 6 + 1);
458     const char *pos = chan_list;
459     const char *pos2;
460     char *pos3 = uri_channels;
461     params->num_chan = 0;
462 
463     os_memcpy(pos3, " chan=", strlen(" chan="));
464     pos3 += strlen(" chan=");
465 
466     while (pos && *pos) {
467         int channel;
468         int len = strlen(chan_list);
469 
470         pos2 = pos;
471         while (*pos2 >= '0' && *pos2 <= '9') {
472             pos2++;
473         }
474         if (*pos2 == ',' || *pos2 == ' ' || *pos2 == '\0') {
475             channel = atoi(pos);
476             if (channel < 1 || channel > 14) {
477                 os_free(uri_channels);
478                 return NULL;
479             }
480             params->chan_list[params->num_chan++] = channel;
481             os_memcpy(pos3, "81/", strlen("81/"));
482             pos3 += strlen("81/");
483             os_memcpy(pos3, pos, (pos2 - pos));
484             pos3 += (pos2 - pos);
485             *pos3++ = ',';
486 
487             pos = pos2 + 1;
488         }
489         while (*pos == ',' || *pos == ' ' || *pos == '\0') {
490             pos++;
491         }
492 
493         if (((int)(pos - chan_list) >= len)) {
494             break;
495         }
496     }
497     *(pos3 - 1) = ' ';
498 
499     return uri_channels;
500 }
501 
502 esp_err_t
esp_supp_dpp_bootstrap_gen(const char * chan_list,enum dpp_bootstrap_type type,const char * key,const char * uri_info)503 esp_supp_dpp_bootstrap_gen(const char *chan_list, enum dpp_bootstrap_type type,
504                            const char *key, const char *uri_info)
505 {
506     struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params;
507     char *uri_chan_list = esp_dpp_parse_chan_list(chan_list);
508     char *command = os_zalloc(1200);
509     int ret;
510 
511     if (!uri_chan_list || !command || params->num_chan >= 14 || params->num_chan == 0) {
512         wpa_printf(MSG_ERROR, "Invalid Channel list - %s", chan_list);
513         if (command) {
514             os_free(command);
515         }
516         ret = ESP_ERR_DPP_FAILURE;
517         goto fail;
518     }
519 
520     if (type != DPP_BOOTSTRAP_QR_CODE) {
521         wpa_printf(MSG_INFO, "Bootstrap type %d not supported", type);
522         os_free(command);
523         ret = ESP_ERR_NOT_SUPPORTED;
524         goto fail;
525     }
526     params->type = type;
527     esp_wifi_get_mac(WIFI_IF_STA, params->mac);
528 
529     if (uri_info) {
530         params->info_len = strlen(uri_info);
531         if (params->info_len) {
532             params->info = os_zalloc(params->info_len + 1);
533             if (!params->info) {
534                 os_free(command);
535                 ret = ESP_ERR_NO_MEM;
536                 goto fail;
537             }
538             os_memcpy(params->info, uri_info, params->info_len);
539         }
540     }
541 
542     if (key) {
543         params->key_len = strlen(key);
544         if (params->key_len) {
545             char prefix[] = "30310201010420";
546             char postfix[] = "a00a06082a8648ce3d030107";
547 
548             params->key = os_zalloc(params->key_len +
549                                     sizeof(prefix) + sizeof(postfix));
550             if (!params->key) {
551                 os_free(command);
552                 ret = ESP_ERR_NO_MEM;
553                 goto fail;
554             }
555             sprintf(params->key, "%s%s%s", prefix, key, postfix);
556         }
557     }
558 
559     sprintf(command, "type=qrcode mac=" MACSTR "%s%s%s%s%s",
560             MAC2STR(params->mac), uri_chan_list,
561             params->key_len ? "key=" : "",
562             params->key_len ? params->key : "",
563             params->info_len ? " info=" : "",
564             params->info_len ? params->info : "");
565 
566     ret = esp_dpp_post_evt(SIG_DPP_BOOTSTRAP_GEN, (u32)command);
567     if (ret != ESP_OK) {
568         os_free(command);
569         if (params->info) {
570             os_free(params->info);
571             params->info = NULL;
572         }
573         if (params->key) {
574             os_free(params->key);
575             params->key = NULL;
576         }
577         goto fail;
578     }
579 
580     ret = ESP_OK;
581 fail:
582     if (uri_chan_list) {
583         os_free(uri_chan_list);
584     }
585 
586     return ret;
587 }
588 
esp_supp_dpp_start_listen(void)589 esp_err_t esp_supp_dpp_start_listen(void)
590 {
591     if (esp_wifi_get_user_init_flag_internal() == 0) {
592         wpa_printf(MSG_ERROR, "DPP: ROC not possible before wifi is started");
593         return ESP_ERR_INVALID_STATE;
594     }
595 
596     return esp_dpp_post_evt(SIG_DPP_LISTEN_NEXT_CHANNEL, 0);
597 }
598 
esp_supp_dpp_stop_listen(void)599 void esp_supp_dpp_stop_listen(void)
600 {
601     s_dpp_stop_listening = true;
602     esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_CANCEL, 0, 0, NULL);
603 }
604 
esp_supp_dpp_init(esp_supp_dpp_event_cb_t cb)605 esp_err_t esp_supp_dpp_init(esp_supp_dpp_event_cb_t cb)
606 {
607     struct dpp_global_config cfg = {0};
608     int ret;
609 
610     os_bzero(&s_dpp_ctx, sizeof(s_dpp_ctx));
611     s_dpp_ctx.dpp_event_cb = cb;
612 
613     cfg.cb_ctx = &s_dpp_ctx;
614     cfg.msg_ctx = &s_dpp_ctx;
615     s_dpp_ctx.dpp_global = dpp_global_init(&cfg);
616 
617     s_dpp_stop_listening = false;
618     s_dpp_evt_queue = xQueueCreate(3, sizeof(dpp_event_t));
619     ret = xTaskCreate(esp_dpp_task, "dppT", DPP_TASK_STACK_SIZE, NULL, 2, s_dpp_task_hdl);
620     if (ret != pdPASS) {
621         wpa_printf(MSG_ERROR, "DPP: failed to create task");
622         return ESP_FAIL;
623     }
624 
625     s_dpp_api_lock = xSemaphoreCreateRecursiveMutex();
626     if (!s_dpp_api_lock) {
627         esp_supp_dpp_deinit();
628         wpa_printf(MSG_ERROR, "DPP: dpp_init: failed to create DPP API lock");
629         return ESP_ERR_NO_MEM;
630     }
631 
632     esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_ACTION_TX_STATUS,
633                                &offchan_event_handler, NULL);
634     esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_ROC_DONE,
635                                &offchan_event_handler, NULL);
636 
637     wpa_printf(MSG_INFO, "esp_dpp_task prio:%d, stack:%d\n", 2, DPP_TASK_STACK_SIZE);
638 
639     return ESP_OK;
640 }
641 
esp_supp_dpp_deinit(void)642 void esp_supp_dpp_deinit(void)
643 {
644     struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params;
645 
646     if (params->info) {
647         os_free(params->info);
648         params->info = NULL;
649     }
650     if (params->key) {
651         os_free(params->key);
652         params->key = NULL;
653     }
654 
655     s_dpp_auth_retries = 0;
656     dpp_global_deinit(s_dpp_ctx.dpp_global);
657     esp_dpp_post_evt(SIG_DPP_DEL_TASK, 0);
658 }
659