From 4dac5482e3c9d0b793689de4ab82f48ac829f0ab Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Wed, 9 Apr 2025 14:53:08 +0530 Subject: [PATCH 1/5] fix(esp_wifi): Add eloop blocking call API for public APIs --- components/wpa_supplicant/port/eloop.c | 125 +++++++++++++++++++- components/wpa_supplicant/src/utils/eloop.h | 16 +++ 2 files changed, 136 insertions(+), 5 deletions(-) diff --git a/components/wpa_supplicant/port/eloop.c b/components/wpa_supplicant/port/eloop.c index 758e78151c..b680c54f08 100644 --- a/components/wpa_supplicant/port/eloop.c +++ b/components/wpa_supplicant/port/eloop.c @@ -6,7 +6,7 @@ * See README for more details. */ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,8 @@ #include "esp_wifi_driver.h" #include "rom/ets_sys.h" +bool current_task_is_wifi_task(void); + struct eloop_timeout { struct dl_list list; struct os_reltime time; @@ -29,12 +31,16 @@ struct eloop_timeout { char func_name[100]; int line; #endif + void *sync_semph; + int ret; + eloop_blocking_timeout_handler blocking_handler; }; struct eloop_data { struct dl_list timeout; ETSTimer eloop_timer; bool eloop_started; + void *eloop_semph; }; #define ELOOP_LOCK() os_mutex_lock(eloop_data_lock) @@ -164,6 +170,86 @@ overflow: return 0; } +#ifdef ELOOP_DEBUG +int eloop_register_timeout_blocking_debug(eloop_blocking_timeout_handler handler, void *eloop_data, + void *user_data, const char *func, int line) +#else +int eloop_register_timeout_blocking(eloop_blocking_timeout_handler handler, + void *eloop_data, void *user_data) +#endif +{ + struct eloop_timeout *timeout, *tmp; +#ifdef ELOOP_DEBUG + int count = 0; +#endif + int ret; + + if (current_task_is_wifi_task()) { + assert(false); + return -1; + } + timeout = os_zalloc(sizeof(*timeout)); + if (timeout == NULL) { + return -1; + } + if (os_get_reltime(&timeout->time) < 0) { + os_free(timeout); + return -1; + } + timeout->eloop_data = eloop_data; + timeout->user_data = user_data; + timeout->blocking_handler = handler; +#ifdef ELOOP_DEBUG + os_strlcpy(timeout->func_name, func, 100); + timeout->line = line; +#endif + + ELOOP_LOCK(); + if (!eloop.eloop_semph) { + eloop.eloop_semph = os_semphr_create(1, 0); + } + ELOOP_UNLOCK(); + + if (!eloop.eloop_semph) { + wpa_printf(MSG_INFO, "ELOOP: sync semphr not available"); + os_free(timeout); + return -1; + } + timeout->sync_semph = eloop.eloop_semph; + /* Maintain timeouts in order of increasing time */ + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (os_reltime_before(&timeout->time, &tmp->time)) { + ELOOP_LOCK(); + dl_list_add(tmp->list.prev, &timeout->list); + ELOOP_UNLOCK(); + goto run; + } +#ifdef ELOOP_DEBUG + count++; +#endif + } + ELOOP_LOCK(); + dl_list_add_tail(&eloop.timeout, &timeout->list); + ELOOP_UNLOCK(); + +run: +#ifdef ELOOP_DEBUG + wpa_printf(MSG_DEBUG, "ELOOP: Added one blocking timer from %s:%d to call %p, current order=%d", + timeout->func_name, line, timeout->handler, count); +#endif + ELOOP_LOCK(); + os_timer_disarm(&eloop.eloop_timer); + os_timer_arm(&eloop.eloop_timer, 0, 0); + ELOOP_UNLOCK(); + + wpa_printf(MSG_DEBUG, "ELOOP: waiting for sync semphr"); + os_semphr_take(eloop.eloop_semph, OS_BLOCK); + + ret = timeout->ret; + os_free(timeout); + return ret; +} + static bool timeout_exists(struct eloop_timeout *old) { struct eloop_timeout *timeout, *prev; @@ -177,6 +263,18 @@ static bool timeout_exists(struct eloop_timeout *old) return false; } +static void eloop_remove_blocking_timeout(struct eloop_timeout *timeout) +{ + bool timeout_present = false; + ELOOP_LOCK(); + /* Make sure timeout still exists(Another context may have deleted this) */ + timeout_present = timeout_exists(timeout); + if (timeout_present) { + dl_list_del(&timeout->list); + } + ELOOP_UNLOCK(); +} + static void eloop_remove_timeout(struct eloop_timeout *timeout) { bool timeout_present = false; @@ -359,6 +457,7 @@ void eloop_run(void) if (!os_reltime_before(&now, &timeout->time)) { void *eloop_data = timeout->eloop_data; void *user_data = timeout->user_data; + void *sync_semaphr = timeout->sync_semph; eloop_timeout_handler handler = timeout->handler; #ifdef ELOOP_DEBUG @@ -366,12 +465,28 @@ void eloop_run(void) int line = timeout->line; os_strlcpy(fn_name, timeout->func_name, 100); #endif - eloop_remove_timeout(timeout); + /* will be freed in caller context in blocking call */ + if (!sync_semaphr) { + eloop_remove_timeout(timeout); #ifdef ELOOP_DEBUG - wpa_printf(MSG_DEBUG, "ELOOP: Running timer fn:%p scheduled by %s:%d ", - handler, fn_name, line); + wpa_printf(MSG_DEBUG, "ELOOP: Running timer fn:%p scheduled by %s:%d ", + handler, fn_name, line); #endif - handler(eloop_data, user_data); + handler(eloop_data, user_data); + } else { + eloop_remove_blocking_timeout(timeout); + eloop_blocking_timeout_handler handler2 = + timeout->blocking_handler; +#ifdef ELOOP_DEBUG + wpa_printf(MSG_DEBUG, "ELOOP: Running blocking timer fn:%p scheduled by %s:%d ", + handler2, fn_name, line); +#endif + timeout->ret = handler2(eloop_data, user_data); +#ifdef ELOOP_DEBUG + wpa_printf(MSG_DEBUG, "ELOOP: releasing sync semaphor"); +#endif + os_semphr_give(sync_semaphr); + } } } } diff --git a/components/wpa_supplicant/src/utils/eloop.h b/components/wpa_supplicant/src/utils/eloop.h index 0bc8b5d6b3..35f1740f61 100644 --- a/components/wpa_supplicant/src/utils/eloop.h +++ b/components/wpa_supplicant/src/utils/eloop.h @@ -56,6 +56,9 @@ typedef void (*eloop_event_handler)(void *eloop_ctx, void *user_ctx); */ typedef void (*eloop_timeout_handler)(void *eloop_ctx, void *user_ctx); + +typedef int (*eloop_blocking_timeout_handler)(void *eloop_ctx, void *user_ctx); + /** * eloop_signal_handler - eloop signal event callback type * @sig: Signal number @@ -190,6 +193,19 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs, void *eloop_data, void *user_data); #endif +#ifdef ELOOP_DEBUG +int eloop_register_timeout_blocking_debug(eloop_blocking_timeout_handler handler, void *eloop_data, + void *user_data, const char *func, int line); + +#define eloop_register_timeout_blocking(handler, eloop_data, user_data) \ + eloop_register_timeout_blocking_debug(handler, eloop_data, user_data, __func__, __LINE__) +#else +int eloop_register_timeout_blocking(eloop_blocking_timeout_handler handler, + void *eloop_data, void *user_data); +#endif + + + /** * eloop_cancel_timeout - Cancel timeouts * @handler: Matching callback function From a96d680fc550564a8a468d363d982f5ccf3559cf Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Mon, 7 Oct 2024 13:51:14 +0530 Subject: [PATCH 2/5] fix(esp_wifi): Add various DPP fixes observed during testing --- .../esp_supplicant/include/esp_dpp.h | 3 +- .../src/crypto/crypto_mbedtls-ec.c | 10 +- .../esp_supplicant/src/esp_dpp.c | 174 ++++++++++++++---- .../esp_supplicant/src/esp_dpp_i.h | 2 +- components/wpa_supplicant/src/common/dpp.h | 2 +- 5 files changed, 151 insertions(+), 40 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h b/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h index ec38d3c70f..909cea6f15 100644 --- a/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h +++ b/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h @@ -16,7 +16,7 @@ extern "C" { #endif -#define ESP_DPP_AUTH_TIMEOUT_SECS 1 +#define ESP_DPP_AUTH_TIMEOUT_SECS 2 #define ESP_DPP_MAX_CHAN_COUNT 5 #define ESP_ERR_DPP_FAILURE (ESP_ERR_WIFI_BASE + 151) /*!< Generic failure during DPP Operation */ @@ -24,6 +24,7 @@ extern "C" { #define ESP_ERR_DPP_INVALID_ATTR (ESP_ERR_WIFI_BASE + 153) /*!< Encountered invalid DPP Attribute */ #define ESP_ERR_DPP_AUTH_TIMEOUT (ESP_ERR_WIFI_BASE + 154) /*!< DPP Auth response was not received in time */ #define ESP_ERR_DPP_INVALID_LIST (ESP_ERR_WIFI_BASE + 155) /*!< Channel list given in esp_supp_dpp_bootstrap_gen() is not valid or too big */ +#define ESP_ERR_DPP_CONF_TIMEOUT (ESP_ERR_WIFI_BASE + 155) /*!< DPP Configuration was not recieved in time */ /** @brief Types of Bootstrap Methods for DPP. */ typedef enum dpp_bootstrap_type { diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index 52cec2e4d2..0a498e0664 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -848,17 +848,17 @@ void crypto_ec_key_debug_print(struct crypto_ec_key *key, const char *title) mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(*pkey); u8 x[32], y[32], d[32]; - wpa_printf(MSG_INFO, "curve: %s", + wpa_printf(MSG_DEBUG, "curve: %s", mbedtls_ecp_curve_info_from_grp_id(ecp->MBEDTLS_PRIVATE(grp).id)->name); int len = mbedtls_mpi_size((mbedtls_mpi *)crypto_ec_get_prime((struct crypto_ec *)crypto_ec_get_group_from_key(key))); - wpa_printf(MSG_INFO, "prime len is %d", len); + wpa_printf(MSG_DEBUG, "prime len is %d", len); crypto_ec_point_to_bin((struct crypto_ec *)crypto_ec_get_group_from_key(key), crypto_ec_key_get_public_key(key), x, y); crypto_bignum_to_bin(crypto_ec_key_get_private_key(key), d, len, len); - wpa_hexdump(MSG_INFO, "Q_x:", x, 32); - wpa_hexdump(MSG_INFO, "Q_y:", y, 32); - wpa_hexdump(MSG_INFO, "d: ", d, 32); + wpa_hexdump(MSG_DEBUG, "Q_x:", x, 32); + wpa_hexdump(MSG_DEBUG, "Q_y:", y, 32); + wpa_hexdump(MSG_DEBUG, "d: ", d, 32); #endif } diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c index a28ad57592..72b905f6d7 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c @@ -177,36 +177,59 @@ static void esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_d (const u8 *)&rx_param->action_frm->u.public_action.v, dpp_data, len); os_memcpy(s_dpp_ctx.dpp_auth->peer_mac_addr, rx_param->sa, ETH_ALEN); - wpa_printf(MSG_DEBUG, "DPP: Sending authentication response."); + wpa_printf(MSG_INFO, "DPP: Sending authentication response."); esp_dpp_send_action_frame(rx_param->sa, wpabuf_head(s_dpp_ctx.dpp_auth->resp_msg), wpabuf_len(s_dpp_ctx.dpp_auth->resp_msg), rx_param->channel, OFFCHAN_TX_WAIT_TIME); - eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); - eloop_register_timeout(ESP_DPP_AUTH_TIMEOUT_SECS, 0, esp_dpp_auth_conf_wait_timeout, NULL, NULL); return; fail: esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)rc); } -static void gas_query_req_tx(struct dpp_authentication *auth) +static void gas_query_timeout(void *eloop_data, void *user_ctx) +{ + struct dpp_authentication *auth = user_ctx; + + if (!auth || !auth->auth_success) { + return; + } + + wpa_printf(MSG_DEBUG, "GAS: No response received for GAS query"); + if (auth->conf_req) { + wpabuf_free(auth->conf_req); + auth->conf_req = NULL; + } + esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_CONF_TIMEOUT); +} + +static int gas_query_req_tx(struct dpp_authentication *auth) { struct wpabuf *buf; int supp_op_classes[] = {81, 0}; + int ret; buf = dpp_build_conf_req_helper(auth, NULL, 0, NULL, supp_op_classes); if (!buf) { wpa_printf(MSG_DEBUG, "DPP: No configuration request data available"); esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE); - return; + return ESP_FAIL; } - wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (chan %u)", + wpa_printf(MSG_INFO, "DPP: GAS request to " MACSTR " (chan %u)", MAC2STR(auth->peer_mac_addr), auth->curr_chan); - esp_dpp_send_action_frame(auth->peer_mac_addr, wpabuf_head(buf), wpabuf_len(buf), - auth->curr_chan, OFFCHAN_TX_WAIT_TIME); + ret = esp_dpp_send_action_frame(auth->peer_mac_addr, wpabuf_head(buf), wpabuf_len(buf), + auth->curr_chan, OFFCHAN_TX_WAIT_TIME); + if (ret != ESP_OK) { + wpabuf_free(buf); + } + + auth->conf_req = buf; + eloop_register_timeout(2, 0, gas_query_timeout, NULL, auth); + + return ret; } static int esp_dpp_handle_config_obj(struct dpp_authentication *auth, @@ -253,7 +276,7 @@ static void esp_dpp_rx_auth_conf(struct action_rx_param *rx_param, uint8_t *dpp_ size_t len = rx_param->vendor_data_len - 2; int rc; - wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR, + wpa_printf(MSG_INFO, "DPP: Authentication Confirmation from " MACSTR, MAC2STR(rx_param->sa)); if (!auth) { @@ -279,7 +302,9 @@ static void esp_dpp_rx_auth_conf(struct action_rx_param *rx_param, uint8_t *dpp_ } /* Send GAS Query Req */ - gas_query_req_tx(auth); + if (gas_query_req_tx(auth) != ESP_OK) { + goto fail; + } return; @@ -447,6 +472,7 @@ static void gas_query_resp_rx(struct action_rx_param *rx_param) if (pos[1] == WLAN_EID_VENDOR_SPECIFIC && pos[2] == 5 && WPA_GET_BE24(&pos[3]) == OUI_WFA && pos[6] == 0x1a && pos[7] == 1 && auth) { + eloop_cancel_timeout(gas_query_timeout, NULL, auth); if (dpp_conf_resp_rx(auth, resp, rx_param->vendor_data_len - 2) < 0) { wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); goto fail; @@ -504,6 +530,7 @@ static esp_err_t esp_dpp_rx_action(struct action_rx_param *rx_param) public_action->v.pa_gas_resp.length - (u8 *)rx_param->action_frm); + wpa_printf(MSG_DEBUG, "DPP: Gas response received"); gas_query_resp_rx(rx_param); } } @@ -513,6 +540,32 @@ static esp_err_t esp_dpp_rx_action(struct action_rx_param *rx_param) return ret; } +void esp_dpp_rx_action_eloop(void *data, void *user_ctx) +{ + esp_dpp_rx_action(data); +} + +void esp_dpp_listen_next_channel(void *data, void *user_ctx) +{ + struct dpp_bootstrap_params_t *p = &s_dpp_ctx.bootstrap_params; + static int counter; + int channel; + esp_err_t ret = 0; + + if (p->num_chan <= 0) { + wpa_printf(MSG_ERROR, "Listen channel not set"); + return; + } + channel = p->chan_list[counter++ % p->num_chan]; + ret = esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_REQ, channel, + BOOTSTRAP_ROC_WAIT_TIME, s_action_rx_cb); + if (ret != ESP_OK) { + wpa_printf(MSG_ERROR, "Failed ROC. error : 0x%x", ret); + return; + } + s_dpp_listen_in_progress = true; +} + static void esp_dpp_task(void *pvParameters) { dpp_event_t evt; @@ -648,41 +701,94 @@ int esp_supp_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t chann rx_param->frm_len = len; os_memcpy(rx_param->action_frm, payload, len); - ret = esp_dpp_post_evt(SIG_DPP_RX_ACTION, (u32)rx_param); - if (ESP_OK != ret) { - wpa_printf(MSG_ERROR, "Failed to post event to DPP Task(status=%d)", ret); - os_free(rx_param->action_frm); - os_free(rx_param); - return ret; - } + eloop_register_timeout(0, 0, esp_dpp_rx_action_eloop, rx_param, NULL); } return ret; } +static void esp_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; + + if (!auth || !auth->resp_msg) { + return; + } + + wpa_printf(MSG_DEBUG, + "DPP: Retry Authentication Response after timeout"); + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " chan=%u type=%d", + MAC2STR(auth->peer_mac_addr), auth->curr_chan, + DPP_PA_AUTHENTICATION_RESP); + + esp_dpp_send_action_frame(s_dpp_ctx.dpp_auth->peer_mac_addr, + wpabuf_head(s_dpp_ctx.dpp_auth->resp_msg), + wpabuf_len(s_dpp_ctx.dpp_auth->resp_msg), + auth->curr_chan, OFFCHAN_TX_WAIT_TIME); +} + +static void esp_dpp_auth_resp_retry(void) +{ + struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; + unsigned int wait_time, max_tries = 5; + + if (!auth || !auth->resp_msg) { + return; + } + + auth->auth_resp_tries++; + if (auth->auth_resp_tries >= max_tries) { + wpa_printf(MSG_INFO, "DPP: No confirm received from initiator - stopping exchange"); + esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE); + return; + } + + wait_time = 1; + wpa_printf(MSG_INFO, + "DPP: Schedule retransmission %d of Authentication Response frame in %u s", auth->auth_resp_tries, + wait_time); + eloop_cancel_timeout(esp_dpp_auth_resp_retry_timeout, NULL, NULL); + eloop_register_timeout(wait_time, 0, esp_dpp_auth_resp_retry_timeout, NULL, NULL); +} + static void offchan_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { - if (event_id == WIFI_EVENT_ACTION_TX_STATUS) { - wifi_event_action_tx_status_t *evt = - (wifi_event_action_tx_status_t *)event_data; - if (evt->op_id == s_current_tx_op_id) { - wpa_printf(MSG_DEBUG, - "Mgmt Tx Status - %d, Context - 0x%x Operation ID : %d", evt->status, (uint32_t)evt->context, evt->op_id); + struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; - if (evt->status == WIFI_ACTION_TX_FAILED) { + if (event_id == WIFI_EVENT_ACTION_TX_STATUS) { + wifi_event_action_tx_status_t *evt = event_data; + + wpa_printf(MSG_DEBUG, "Mgmt Tx Status - %d, Cookie - 0x%x", + evt->status, (uint32_t)evt->context); + if (!auth) { + esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE); + return; + } + if (auth->waiting_auth_conf) { + if (evt->status) { + /* failed to send auth response frame */ eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); - if (s_dpp_listen_in_progress) { - esp_supp_dpp_stop_listen(); - } + esp_dpp_auth_resp_retry(); + } else { + eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); + eloop_register_timeout(ESP_DPP_AUTH_TIMEOUT_SECS, 0, esp_dpp_auth_conf_wait_timeout, NULL, NULL); + } + } else if (auth->auth_success) { + if (evt->status) { + /* failed to send gas query frame, retry logic needed? */ esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE); + } else { + eloop_cancel_timeout(gas_query_timeout, NULL, auth); + eloop_register_timeout(2, 0, gas_query_timeout, NULL, auth); } } } else if (event_id == WIFI_EVENT_ROC_DONE) { wifi_event_roc_done_t *evt = (wifi_event_roc_done_t *)event_data; - /*@TODO : Decide flow for when ROC fails*/ - if (s_dpp_listen_in_progress && evt->context == (uint32_t)s_action_rx_cb && evt->status == WIFI_ROC_DONE) { - esp_dpp_post_evt(SIG_DPP_LISTEN_NEXT_CHANNEL, 0); + + if (s_dpp_listen_in_progress && evt->context == (uint32_t)s_action_rx_cb) { + eloop_register_timeout(0, 0, esp_dpp_listen_next_channel, NULL, NULL); } } } @@ -861,7 +967,11 @@ esp_err_t esp_supp_dpp_start_listen(void) return ESP_ERR_INVALID_STATE; } - return esp_dpp_post_evt(SIG_DPP_LISTEN_NEXT_CHANNEL, 0); + /* cancel previous ROC if ongoing */ + esp_supp_dpp_stop_listen(); + + eloop_register_timeout(0, 0, esp_dpp_listen_next_channel, NULL, NULL); + return 0; } esp_err_t esp_supp_dpp_stop_listen(void) @@ -925,7 +1035,7 @@ esp_err_t esp_supp_dpp_init(esp_supp_dpp_event_cb_t cb) goto init_fail; } - ret = os_task_create(esp_dpp_task, "dppT", DPP_TASK_STACK_SIZE, NULL, 2, &s_dpp_task_hdl); + ret = os_task_create(esp_dpp_task, "dppT", DPP_TASK_STACK_SIZE, NULL, 15, &s_dpp_task_hdl); if (ret != TRUE) { wpa_printf(MSG_ERROR, "DPP: failed to create task"); ret = ESP_ERR_NO_MEM; diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h index d3dbc95c37..f7f8f1e6d9 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h @@ -34,7 +34,7 @@ typedef struct { } dpp_event_t; #define BOOTSTRAP_ROC_WAIT_TIME 500 -#define OFFCHAN_TX_WAIT_TIME 500 +#define OFFCHAN_TX_WAIT_TIME 600 struct dpp_bootstrap_params_t { enum dpp_bootstrap_type type; diff --git a/components/wpa_supplicant/src/common/dpp.h b/components/wpa_supplicant/src/common/dpp.h index 84a9416ae9..b4a5fce432 100644 --- a/components/wpa_supplicant/src/common/dpp.h +++ b/components/wpa_supplicant/src/common/dpp.h @@ -261,7 +261,7 @@ struct dpp_authentication { * Authentication exchange */ unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; unsigned int num_freq, freq_idx; - unsigned int curr_chan; + unsigned int curr_chan; unsigned int curr_freq; unsigned int neg_freq; unsigned int num_freq_iters; From bfc86f6094504f38f42b10eed02e7e099a26fdf3 Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Mon, 7 Oct 2024 14:38:56 +0530 Subject: [PATCH 3/5] fix(esp_wifi): Removal of task posting code and use pptask instead --- components/esp_common/src/esp_err_to_name.c | 3 + .../esp_supplicant/include/esp_dpp.h | 3 +- .../src/crypto/crypto_mbedtls-ec.c | 16 +- .../esp_supplicant/src/esp_dpp.c | 761 +++++++++--------- .../esp_supplicant/src/esp_dpp_i.h | 26 +- .../esp_supplicant/src/esp_wpa_main.c | 2 +- components/wpa_supplicant/src/common/dpp.c | 2 +- 7 files changed, 384 insertions(+), 429 deletions(-) diff --git a/components/esp_common/src/esp_err_to_name.c b/components/esp_common/src/esp_err_to_name.c index 1c342e6b2a..606e78124f 100644 --- a/components/esp_common/src/esp_err_to_name.c +++ b/components/esp_common/src/esp_err_to_name.c @@ -474,6 +474,9 @@ static const esp_err_msg_t esp_err_msg_table[] = { ERR_TBL_IT(ESP_ERR_DPP_INVALID_LIST), /* 12443 0x309b Channel list given in esp_supp_dpp_bootstrap_gen() is not valid or too big */ +# endif +# ifdef ESP_ERR_DPP_CONF_TIMEOUT + ERR_TBL_IT(ESP_ERR_DPP_CONF_TIMEOUT), /* 12444 0x309c DPP Configuration was not received in time */ # endif // components/esp_common/include/esp_err.h # ifdef ESP_ERR_MESH_BASE diff --git a/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h b/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h index 909cea6f15..77c694f743 100644 --- a/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h +++ b/components/wpa_supplicant/esp_supplicant/include/esp_dpp.h @@ -16,7 +16,6 @@ extern "C" { #endif -#define ESP_DPP_AUTH_TIMEOUT_SECS 2 #define ESP_DPP_MAX_CHAN_COUNT 5 #define ESP_ERR_DPP_FAILURE (ESP_ERR_WIFI_BASE + 151) /*!< Generic failure during DPP Operation */ @@ -24,7 +23,7 @@ extern "C" { #define ESP_ERR_DPP_INVALID_ATTR (ESP_ERR_WIFI_BASE + 153) /*!< Encountered invalid DPP Attribute */ #define ESP_ERR_DPP_AUTH_TIMEOUT (ESP_ERR_WIFI_BASE + 154) /*!< DPP Auth response was not received in time */ #define ESP_ERR_DPP_INVALID_LIST (ESP_ERR_WIFI_BASE + 155) /*!< Channel list given in esp_supp_dpp_bootstrap_gen() is not valid or too big */ -#define ESP_ERR_DPP_CONF_TIMEOUT (ESP_ERR_WIFI_BASE + 155) /*!< DPP Configuration was not recieved in time */ +#define ESP_ERR_DPP_CONF_TIMEOUT (ESP_ERR_WIFI_BASE + 156) /*!< DPP Configuration was not received in time */ /** @brief Types of Bootstrap Methods for DPP. */ typedef enum dpp_bootstrap_type { diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index 0a498e0664..6751d41b74 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -844,21 +844,23 @@ int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *csign, void crypto_ec_key_debug_print(struct crypto_ec_key *key, const char *title) { -#ifdef DEBUG_PRINT +#if defined(CONFIG_LOG_DEFAULT_LEVEL_DEBUG) || defined(CONFIG_LOG_DEFAULT_LEVEL_VERBOSE) +#if defined(DEBUG_PRINT) mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(*pkey); u8 x[32], y[32], d[32]; - wpa_printf(MSG_DEBUG, "curve: %s", + wpa_printf(MSG_EXCESSIVE, "curve: %s", mbedtls_ecp_curve_info_from_grp_id(ecp->MBEDTLS_PRIVATE(grp).id)->name); int len = mbedtls_mpi_size((mbedtls_mpi *)crypto_ec_get_prime((struct crypto_ec *)crypto_ec_get_group_from_key(key))); - wpa_printf(MSG_DEBUG, "prime len is %d", len); + wpa_printf(MSG_EXCESSIVE, "prime len is %d", len); crypto_ec_point_to_bin((struct crypto_ec *)crypto_ec_get_group_from_key(key), crypto_ec_key_get_public_key(key), x, y); crypto_bignum_to_bin(crypto_ec_key_get_private_key(key), d, len, len); - wpa_hexdump(MSG_DEBUG, "Q_x:", x, 32); - wpa_hexdump(MSG_DEBUG, "Q_y:", y, 32); - wpa_hexdump(MSG_DEBUG, "d: ", d, 32); + wpa_hexdump(MSG_EXCESSIVE, "Q_x:", x, 32); + wpa_hexdump(MSG_EXCESSIVE, "Q_y:", y, 32); + wpa_hexdump(MSG_EXCESSIVE, "d: ", d, 32); +#endif #endif } diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c index 72b905f6d7..d984a49a07 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp.c @@ -21,68 +21,76 @@ #include "rsn_supp/pmksa_cache.h" #ifdef CONFIG_DPP -static void *s_dpp_task_hdl = NULL; -static void *s_dpp_evt_queue = NULL; -static void *s_dpp_api_lock = NULL; - -static bool s_dpp_listen_in_progress; -static struct esp_dpp_context_t s_dpp_ctx; -static wifi_action_rx_cb_t s_action_rx_cb = esp_supp_rx_action; -static uint8_t s_current_tx_op_id; -#define DPP_API_LOCK() os_mutex_lock(s_dpp_api_lock) -#define DPP_API_UNLOCK() os_mutex_unlock(s_dpp_api_lock) struct action_rx_param { u8 sa[ETH_ALEN]; u32 channel; u32 frm_len; u32 vendor_data_len; - struct ieee80211_action *action_frm; + struct ieee80211_action action_frm[]; }; -esp_err_t esp_dpp_post_evt(uint32_t evt_id, uint32_t data) +static void *s_dpp_api_lock = NULL; + +static bool s_dpp_listen_in_progress; +static struct esp_dpp_context_t s_dpp_ctx; +static int esp_supp_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel); +static wifi_action_rx_cb_t s_action_rx_cb = esp_supp_rx_action; +static uint8_t s_current_tx_op_id; +static void tx_status_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data); +static void roc_status_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data); +static esp_err_t dpp_api_lock(void) { - dpp_event_t evt; - esp_err_t ret = ESP_OK; + if (!s_dpp_api_lock) { + s_dpp_api_lock = os_recursive_mutex_create(); + } + if (!s_dpp_api_lock) { + wpa_printf(MSG_ERROR, "DPP: dpp_init: failed to create DPP API lock"); + return ESP_ERR_NO_MEM; + } - evt.id = evt_id; - evt.data = data; + os_mutex_lock(s_dpp_api_lock); + + return ESP_OK; +} + +static esp_err_t dpp_api_unlock(void) +{ if (s_dpp_api_lock) { - DPP_API_LOCK(); - } else { - ret = ESP_ERR_DPP_FAILURE; - goto end; + os_mutex_unlock(s_dpp_api_lock); } - if (os_queue_send(s_dpp_evt_queue, &evt, os_task_ms_to_tick(10)) != TRUE) { - DPP_API_UNLOCK(); - ret = ESP_ERR_DPP_FAILURE; - goto end; - } - if (evt_id != SIG_DPP_DEL_TASK) { - DPP_API_UNLOCK(); - } - wpa_printf(MSG_DEBUG, "DPP: Sent event %d to DPP task", evt_id); - return ret; -end: - wpa_printf(MSG_ERROR, "DPP: Failed to send event %d to DPP task", evt_id); - return ret; + return ESP_OK; } static uint8_t esp_dpp_deinit_auth(void) { - esp_err_t ret = esp_dpp_post_evt(SIG_DPP_DEINIT_AUTH, 0); - if (ESP_OK != ret) { - wpa_printf(MSG_ERROR, "Failed to post DPP auth deinit to DPP Task(status=%d)", ret); - return ret; + if (s_dpp_ctx.dpp_auth) { + dpp_auth_deinit(s_dpp_ctx.dpp_auth); + s_dpp_ctx.dpp_auth = NULL; } + return ESP_OK; } +static void listen_stop_handler(void *data, void *user_ctx) +{ + wifi_roc_req_t req = {0}; + + s_dpp_listen_in_progress = false; + req.ifx = WIFI_IF_STA; + req.type = WIFI_ROC_CANCEL; + + esp_wifi_remain_on_channel(&req); +} + static void esp_dpp_call_cb(esp_supp_dpp_event_t evt, void *data) { if (s_dpp_ctx.dpp_auth) { esp_dpp_deinit_auth(); + listen_stop_handler(NULL, NULL); } s_dpp_ctx.dpp_event_cb(evt, data); } @@ -93,7 +101,7 @@ static void esp_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx) return; } - wpa_printf(MSG_DEBUG, + wpa_printf(MSG_INFO, "DPP: Terminate authentication exchange due to Auth Confirm timeout"); esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_AUTH_TIMEOUT); } @@ -107,14 +115,14 @@ esp_err_t esp_dpp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint3 } req->ifx = WIFI_IF_STA; - memcpy(req->dest_mac, dest_mac, ETH_ALEN); + os_memcpy(req->dest_mac, dest_mac, ETH_ALEN); req->no_ack = false; req->data_len = len; req->rx_cb = s_action_rx_cb; req->channel = channel; req->wait_time_ms = wait_time_ms; req->type = WIFI_OFFCHAN_TX_REQ; - memcpy(req->data, buf, req->data_len); + os_memcpy(req->data, buf, req->data_len); wpa_printf(MSG_DEBUG, "DPP: Mgmt Tx - MAC:" MACSTR ", Channel-%d, WaitT-%d", MAC2STR(dest_mac), channel, wait_time_ms); @@ -132,7 +140,28 @@ esp_err_t esp_dpp_send_action_frame(uint8_t *dest_mac, const uint8_t *buf, uint3 return ESP_OK; } -static void esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_data) +static void esp_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; + + if (!auth || !auth->resp_msg) { + return; + } + + wpa_printf(MSG_DEBUG, + "DPP: Retry Authentication Response after timeout"); + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " chan=%u type=%d", + MAC2STR(auth->peer_mac_addr), auth->curr_chan, + DPP_PA_AUTHENTICATION_RESP); + + esp_dpp_send_action_frame(s_dpp_ctx.dpp_auth->peer_mac_addr, + wpabuf_head(s_dpp_ctx.dpp_auth->resp_msg), + wpabuf_len(s_dpp_ctx.dpp_auth->resp_msg), + auth->curr_chan, 1000 + OFFCHAN_TX_WAIT_TIME); +} + +static esp_err_t esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_data) { size_t len = rx_param->vendor_data_len - 2; const u8 *r_bootstrap, *i_bootstrap; @@ -140,14 +169,15 @@ static void esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_d struct dpp_bootstrap_info *own_bi; int rc; - wpa_printf(MSG_INFO, "DPP: Authentication Request from " MACSTR, MAC2STR(rx_param->sa)); + wpa_printf(MSG_INFO, "DPP: Authentication Request from " MACSTR " chan=%d", + MAC2STR(rx_param->sa), rx_param->channel); r_bootstrap = dpp_get_attr(dpp_data, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, &r_bootstrap_len); if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { wpa_printf(MSG_INFO, "DPP: Missing or invalid Responder Bootstrapping Key Hash attribute"); rc = ESP_ERR_DPP_INVALID_ATTR; - goto fail; + return rc; } wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", r_bootstrap, r_bootstrap_len); @@ -156,7 +186,7 @@ static void esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_d if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) { wpa_printf(MSG_INFO, "DPP: Missing or invalid Initiator Bootstrapping Key Hash attribute"); rc = ESP_ERR_DPP_INVALID_ATTR; - goto fail; + return rc; } wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash", i_bootstrap, i_bootstrap_len); @@ -166,25 +196,25 @@ static void esp_dpp_rx_auth_req(struct action_rx_param *rx_param, uint8_t *dpp_d if (os_memcmp(own_bi->pubkey_hash, r_bootstrap, SHA256_MAC_LEN)) { wpa_printf(MSG_INFO, "DPP: No matching own bootstrapping key found as responder - ignore message"); rc = ESP_ERR_DPP_INVALID_ATTR; - goto fail; + return ESP_ERR_DPP_INVALID_ATTR; } if (s_dpp_ctx.dpp_auth) { wpa_printf(MSG_DEBUG, "DPP: Already in DPP authentication exchange - ignore new one"); - return; + return ESP_OK; } s_dpp_ctx.dpp_auth = dpp_auth_req_rx(NULL, DPP_CAPAB_ENROLLEE, 0, NULL, own_bi, rx_param->channel, (const u8 *)&rx_param->action_frm->u.public_action.v, dpp_data, len); os_memcpy(s_dpp_ctx.dpp_auth->peer_mac_addr, rx_param->sa, ETH_ALEN); - wpa_printf(MSG_INFO, "DPP: Sending authentication response."); + wpa_printf(MSG_INFO, "DPP: Sending authentication response chan(%d)", rx_param->channel); + eloop_cancel_timeout(esp_dpp_auth_resp_retry_timeout, NULL, NULL); + eloop_register_timeout(0, 200000, esp_dpp_auth_resp_retry_timeout, NULL, NULL); esp_dpp_send_action_frame(rx_param->sa, wpabuf_head(s_dpp_ctx.dpp_auth->resp_msg), wpabuf_len(s_dpp_ctx.dpp_auth->resp_msg), - rx_param->channel, OFFCHAN_TX_WAIT_TIME); + rx_param->channel, 1000 + OFFCHAN_TX_WAIT_TIME); - return; -fail: - esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)rc); + return ESP_OK; } static void gas_query_timeout(void *eloop_data, void *user_ctx) @@ -192,6 +222,7 @@ static void gas_query_timeout(void *eloop_data, void *user_ctx) struct dpp_authentication *auth = user_ctx; if (!auth || !auth->auth_success) { + wpa_printf(MSG_INFO, "DPP-GAS: Auth %p state not correct", auth); return; } @@ -212,7 +243,7 @@ static int gas_query_req_tx(struct dpp_authentication *auth) buf = dpp_build_conf_req_helper(auth, NULL, 0, NULL, supp_op_classes); if (!buf) { - wpa_printf(MSG_DEBUG, "DPP: No configuration request data available"); + wpa_printf(MSG_ERROR, "DPP: No configuration request data available"); esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE); return ESP_FAIL; } @@ -221,9 +252,10 @@ static int gas_query_req_tx(struct dpp_authentication *auth) MAC2STR(auth->peer_mac_addr), auth->curr_chan); ret = esp_dpp_send_action_frame(auth->peer_mac_addr, wpabuf_head(buf), wpabuf_len(buf), - auth->curr_chan, OFFCHAN_TX_WAIT_TIME); + auth->curr_chan, 1000 + OFFCHAN_TX_WAIT_TIME); if (ret != ESP_OK) { wpabuf_free(buf); + return ret; } auth->conf_req = buf; @@ -261,14 +293,14 @@ static int esp_dpp_handle_config_obj(struct dpp_authentication *auth, conf->connector); } if (s_dpp_listen_in_progress) { - esp_supp_dpp_stop_listen(); + listen_stop_handler(NULL, NULL); } esp_dpp_call_cb(ESP_SUPP_DPP_CFG_RECVD, wifi_cfg); return 0; } -static void esp_dpp_rx_auth_conf(struct action_rx_param *rx_param, uint8_t *dpp_data) +static int esp_dpp_rx_auth_conf(struct action_rx_param *rx_param, uint8_t *dpp_data) { struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; struct ieee80211_public_action *public_action = @@ -281,35 +313,31 @@ static void esp_dpp_rx_auth_conf(struct action_rx_param *rx_param, uint8_t *dpp_ if (!auth) { wpa_printf(MSG_DEBUG, "DPP: No DPP Authentication in progress - drop"); - rc = ESP_ERR_DPP_FAILURE; - goto fail; + return ESP_ERR_DPP_FAILURE; } if (os_memcmp(rx_param->sa, auth->peer_mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); - rc = ESP_ERR_DPP_FAILURE; - goto fail; + return ESP_ERR_DPP_FAILURE; } eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); if (dpp_auth_conf_rx(auth, (const u8 *)&public_action->v, dpp_data, len) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Authentication failed"); - rc = ESP_ERR_DPP_FAILURE; - goto fail; + wpa_printf(MSG_ERROR, "DPP: Authentication failed"); + return ESP_ERR_DPP_FAILURE; } /* Send GAS Query Req */ - if (gas_query_req_tx(auth) != ESP_OK) { - goto fail; + rc = gas_query_req_tx(auth); + if (rc != ESP_OK) { + wpa_printf(MSG_ERROR, "DPP: GAS query Tx failed"); + return rc; } - return; - -fail: - esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)rc); + return rc; } static esp_err_t esp_dpp_rx_peer_disc_resp(struct action_rx_param *rx_param) @@ -328,7 +356,7 @@ static esp_err_t esp_dpp_rx_peer_disc_resp(struct action_rx_param *rx_param) struct rsn_pmksa_cache_entry *entry = NULL; int i = 0; - if (!rx_param || !rx_param->action_frm) { + if (!rx_param) { return ESP_ERR_INVALID_ARG; } @@ -444,26 +472,25 @@ static esp_err_t esp_dpp_rx_frm(struct action_rx_param *rx_param) if (crypto_suit != 1) { wpa_printf(MSG_ERROR, "DPP: Unsupported crypto suit"); - esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_NOT_SUPPORTED); - ret = ESP_FAIL; - } else { - switch (type) { - case DPP_PA_AUTHENTICATION_REQ: - esp_dpp_rx_auth_req(rx_param, &tmp[2]); - break; - case DPP_PA_AUTHENTICATION_CONF: - esp_dpp_rx_auth_conf(rx_param, &tmp[2]); - break; - case DPP_PA_PEER_DISCOVERY_RESP: - ret = esp_dpp_rx_peer_disc_resp(rx_param); - break; - } + return ESP_FAIL; + } + + switch (type) { + case DPP_PA_AUTHENTICATION_REQ: + ret = esp_dpp_rx_auth_req(rx_param, &tmp[2]); + break; + case DPP_PA_AUTHENTICATION_CONF: + ret = esp_dpp_rx_auth_conf(rx_param, &tmp[2]); + break; + case DPP_PA_PEER_DISCOVERY_RESP: + ret = esp_dpp_rx_peer_disc_resp(rx_param); + break; } return ret; } -static void gas_query_resp_rx(struct action_rx_param *rx_param) +static esp_err_t gas_query_resp_rx(struct action_rx_param *rx_param) { struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; uint8_t *pos = rx_param->action_frm->u.public_action.v.pa_gas_resp.data; @@ -472,77 +499,79 @@ static void gas_query_resp_rx(struct action_rx_param *rx_param) if (pos[1] == WLAN_EID_VENDOR_SPECIFIC && pos[2] == 5 && WPA_GET_BE24(&pos[3]) == OUI_WFA && pos[6] == 0x1a && pos[7] == 1 && auth) { + eloop_cancel_timeout(gas_query_timeout, NULL, auth); if (dpp_conf_resp_rx(auth, resp, rx_param->vendor_data_len - 2) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); + wpa_printf(MSG_INFO, "DPP: Configuration attempt failed"); goto fail; } for (i = 0; i < auth->num_conf_obj; i++) { res = esp_dpp_handle_config_obj(auth, &auth->conf_obj[i]); if (res < 0) { + wpa_printf(MSG_INFO, "DPP: Configuration parsing failed"); goto fail; } } } - return; + return ESP_OK; fail: - esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE); + return ESP_FAIL; } -static esp_err_t esp_dpp_rx_action(struct action_rx_param *rx_param) +static void esp_dpp_rx_action(void *data, void *user_ctx) { - + struct action_rx_param *rx_param = data; + struct ieee80211_public_action *public_action; int ret = ESP_OK; if (!rx_param) { - return ESP_ERR_INVALID_ARG; + return; } - if (rx_param->action_frm->category == WLAN_ACTION_PUBLIC) { - struct ieee80211_public_action *public_action = - &rx_param->action_frm->u.public_action; + /* we don't cater other action frames except public here */ + if (rx_param->action_frm->category != WLAN_ACTION_PUBLIC) { + return; + } - wpa_printf(MSG_DEBUG, "DPP: Rx Public Action frame: action - %d", - public_action->action); + public_action = &rx_param->action_frm->u.public_action; - if (public_action->action == WLAN_PA_VENDOR_SPECIFIC && - WPA_GET_BE24(public_action->v.pa_vendor_spec.oui) == OUI_WFA && - public_action->v.pa_vendor_spec.wfa_stype == DPP_OUI_TYPE) { + wpa_printf(MSG_DEBUG, "DPP: Rx Public Action frame: action - %d", + public_action->action); - rx_param->vendor_data_len = rx_param->frm_len - - (size_t)(public_action->v.pa_vendor_spec.vendor_data - - (u8 *)rx_param->action_frm); + if (public_action->action == WLAN_PA_VENDOR_SPECIFIC && + WPA_GET_BE24(public_action->v.pa_vendor_spec.oui) == OUI_WFA && + public_action->v.pa_vendor_spec.wfa_stype == DPP_OUI_TYPE) { - if (s_dpp_listen_in_progress) { - esp_supp_dpp_stop_listen(); - } + rx_param->vendor_data_len = rx_param->frm_len - + (size_t)(public_action->v.pa_vendor_spec.vendor_data - + (u8 *)rx_param->action_frm); - ret = esp_dpp_rx_frm(rx_param); - } else if (public_action->action == WLAN_PA_GAS_INITIAL_RESP && - public_action->v.pa_gas_resp.type == WLAN_EID_ADV_PROTO && - public_action->v.pa_gas_resp.length == 8 && - public_action->v.pa_gas_resp.status_code == 0) { - - rx_param->vendor_data_len = rx_param->frm_len - - (size_t)(public_action->v.pa_gas_resp.data + - public_action->v.pa_gas_resp.length - - (u8 *)rx_param->action_frm); - - wpa_printf(MSG_DEBUG, "DPP: Gas response received"); - gas_query_resp_rx(rx_param); + if (s_dpp_listen_in_progress) { + listen_stop_handler(NULL, NULL); } + + ret = esp_dpp_rx_frm(rx_param); + } else if (public_action->action == WLAN_PA_GAS_INITIAL_RESP && + public_action->v.pa_gas_resp.type == WLAN_EID_ADV_PROTO && + public_action->v.pa_gas_resp.length == 8 && + public_action->v.pa_gas_resp.status_code == 0) { + + rx_param->vendor_data_len = rx_param->frm_len - + (size_t)(public_action->v.pa_gas_resp.data + + public_action->v.pa_gas_resp.length - + (u8 *)rx_param->action_frm); + + wpa_printf(MSG_DEBUG, "DPP: Gas response received"); + ret = gas_query_resp_rx(rx_param); } - os_free(rx_param->action_frm); os_free(rx_param); - return ret; -} -void esp_dpp_rx_action_eloop(void *data, void *user_ctx) -{ - esp_dpp_rx_action(data); + if (ret != ESP_OK) { + esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE); + } } void esp_dpp_listen_next_channel(void *data, void *user_ctx) @@ -551,187 +580,116 @@ void esp_dpp_listen_next_channel(void *data, void *user_ctx) static int counter; int channel; esp_err_t ret = 0; + wifi_roc_req_t req = {0}; if (p->num_chan <= 0) { wpa_printf(MSG_ERROR, "Listen channel not set"); return; } channel = p->chan_list[counter++ % p->num_chan]; - ret = esp_wifi_remain_on_channel(WIFI_IF_STA, WIFI_ROC_REQ, channel, - BOOTSTRAP_ROC_WAIT_TIME, s_action_rx_cb); + + wpa_printf(MSG_DEBUG, "DPP: Starting ROC on channel %d", channel); + + req.ifx = WIFI_IF_STA; + req.type = WIFI_ROC_REQ; + req.channel = channel; + req.wait_time_ms = BOOTSTRAP_ROC_WAIT_TIME; + req.rx_cb = s_action_rx_cb; + ret = esp_wifi_remain_on_channel(&req); if (ret != ESP_OK) { wpa_printf(MSG_ERROR, "Failed ROC. error : 0x%x", ret); return; } - s_dpp_listen_in_progress = true; } -static void esp_dpp_task(void *pvParameters) +static void esp_dpp_bootstrap_gen(void *data, void *user_ctx) { - dpp_event_t evt; - bool task_del = false; + char *command = data; + const char *uri; - for (;;) { - if (os_queue_recv(s_dpp_evt_queue, &evt, OS_BLOCK) == TRUE) { - if (evt.id >= SIG_DPP_MAX) { - continue; - } + s_dpp_ctx.id = dpp_bootstrap_gen(s_dpp_ctx.dpp_global, command); - switch (evt.id) { - case SIG_DPP_DEL_TASK: - struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params; - eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); - if (params->info) { - os_free(params->info); - params->info = NULL; - } - - if (s_dpp_ctx.dpp_global) { - dpp_global_deinit(s_dpp_ctx.dpp_global); - s_dpp_ctx.dpp_global = NULL; - } - if (s_dpp_ctx.dpp_auth) { - dpp_auth_deinit(s_dpp_ctx.dpp_auth); - s_dpp_ctx.dpp_auth = NULL; - } - task_del = true; - break; - - case SIG_DPP_BOOTSTRAP_GEN: { - char *command = (char *)evt.data; - const char *uri; - - s_dpp_ctx.id = dpp_bootstrap_gen(s_dpp_ctx.dpp_global, command); - uri = dpp_bootstrap_get_uri(s_dpp_ctx.dpp_global, s_dpp_ctx.id); - - esp_dpp_call_cb(ESP_SUPP_DPP_URI_READY, (void *)uri); - os_free(command); - } - break; - - case SIG_DPP_RX_ACTION: { - esp_dpp_rx_action((struct action_rx_param *)evt.data); - } - break; - - case SIG_DPP_LISTEN_NEXT_CHANNEL: { - struct dpp_bootstrap_params_t *p = &s_dpp_ctx.bootstrap_params; - static int counter; - esp_err_t ret = 0; - - if (p->num_chan <= 0) { - wpa_printf(MSG_ERROR, "Listen channel not set"); - break; - } - - wifi_roc_req_t req = {0}; - req.ifx = WIFI_IF_STA; - req.type = WIFI_ROC_REQ; - req.channel = p->chan_list[counter++ % p->num_chan]; - req.wait_time_ms = BOOTSTRAP_ROC_WAIT_TIME; - req.rx_cb = s_action_rx_cb; - req.done_cb = NULL; - wpa_printf(MSG_DEBUG, "Listening on channel=%d", req.channel); - ret = esp_wifi_remain_on_channel(&req); - if (ret != ESP_OK) { - wpa_printf(MSG_ERROR, "Failed ROC. error : 0x%x", ret); - break; - } - wpa_printf(MSG_DEBUG, "Started DPP listen operation %d", req.op_id); - s_dpp_listen_in_progress = true; - } - break; - - case SIG_DPP_START_NET_INTRO: { - esp_dpp_start_net_intro_protocol((uint8_t*)evt.data); - } - break; - - case SIG_DPP_DEINIT_AUTH: { - if (s_dpp_ctx.dpp_auth) { - dpp_auth_deinit(s_dpp_ctx.dpp_auth); - s_dpp_ctx.dpp_auth = NULL; - } - wpa_printf(MSG_DEBUG, "DPP auth deinintialized"); - } - break; - - default: - break; - } - - if (task_del) { - break; - } + if (s_dpp_ctx.id < 0) { + struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params; + if (params->info) { + os_free(params->info); + params->info = NULL; } } + uri = dpp_bootstrap_get_uri(s_dpp_ctx.dpp_global, s_dpp_ctx.id); - os_queue_delete(s_dpp_evt_queue); - s_dpp_evt_queue = NULL; - - if (s_dpp_api_lock) { - os_mutex_delete(s_dpp_api_lock); - s_dpp_api_lock = NULL; - } - - /* At this point, we completed */ - os_task_delete(NULL); + esp_dpp_call_cb(ESP_SUPP_DPP_URI_READY, (void *)uri); + os_free(command); + dpp_api_lock(); + s_dpp_ctx.bootstrap_done = true; + dpp_api_unlock(); } -int esp_supp_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel) +static int esp_dpp_deinit(void *data, void *user_ctx) +{ + struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params; + + wpa_printf(MSG_DEBUG, "DPP: Deinitializing DPP"); + /* Cancel all registered timeouts */ + eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); + + esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_ACTION_TX_STATUS, + &tx_status_handler); + esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_ROC_DONE, + &roc_status_handler); + + if (params->info) { + os_free(params->info); + params->info = NULL; + } + + if (s_dpp_ctx.dpp_global) { + dpp_global_deinit(s_dpp_ctx.dpp_global); + s_dpp_ctx.dpp_global = NULL; + } + if (s_dpp_ctx.dpp_auth) { + dpp_auth_deinit(s_dpp_ctx.dpp_auth); + s_dpp_ctx.dpp_auth = NULL; + } + s_dpp_ctx.dpp_init_done = false; + s_dpp_ctx.bootstrap_done = false; + + return 0; +} + +static int esp_supp_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel) { struct ieee80211_hdr *rx_hdr = (struct ieee80211_hdr *)hdr; struct action_rx_param *rx_param; int ret = ESP_ERR_NOT_SUPPORTED; + struct ieee80211_action *frm = (struct ieee80211_action *)payload; if (WLAN_FC_GET_STYPE(rx_hdr->frame_control) == WLAN_FC_STYPE_ACTION) { - rx_param = os_zalloc(sizeof(struct action_rx_param)); + if (frm->category != WLAN_ACTION_PUBLIC) { + wpa_printf(MSG_DEBUG, "Not public action frame"); + return -1; + } + + rx_param = os_zalloc(sizeof(struct action_rx_param) + len); if (!rx_param) { wpa_printf(MSG_ERROR, "Failed to allocate memory for Rx Action"); return ESP_ERR_NO_MEM; } os_memcpy(rx_param->sa, rx_hdr->addr2, ETH_ALEN); rx_param->channel = channel; - rx_param->action_frm = os_zalloc(len); - if (!rx_param->action_frm) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for Rx Action"); - os_free(rx_param); - return ESP_ERR_NO_MEM; - } rx_param->frm_len = len; os_memcpy(rx_param->action_frm, payload, len); - eloop_register_timeout(0, 0, esp_dpp_rx_action_eloop, rx_param, NULL); + eloop_register_timeout(0, 0, esp_dpp_rx_action, rx_param, NULL); } return ret; } -static void esp_dpp_auth_resp_retry_timeout(void *eloop_ctx, void *timeout_ctx) +static void esp_dpp_auth_resp_retry(void *eloop_ctx, void *timeout_ctx) { struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; - - if (!auth || !auth->resp_msg) { - return; - } - - wpa_printf(MSG_DEBUG, - "DPP: Retry Authentication Response after timeout"); - wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR - " chan=%u type=%d", - MAC2STR(auth->peer_mac_addr), auth->curr_chan, - DPP_PA_AUTHENTICATION_RESP); - - esp_dpp_send_action_frame(s_dpp_ctx.dpp_auth->peer_mac_addr, - wpabuf_head(s_dpp_ctx.dpp_auth->resp_msg), - wpabuf_len(s_dpp_ctx.dpp_auth->resp_msg), - auth->curr_chan, OFFCHAN_TX_WAIT_TIME); -} - -static void esp_dpp_auth_resp_retry(void) -{ - struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; - unsigned int wait_time, max_tries = 5; + unsigned int max_tries = 5; if (!auth || !auth->resp_msg) { return; @@ -744,52 +702,60 @@ static void esp_dpp_auth_resp_retry(void) return; } - wait_time = 1; wpa_printf(MSG_INFO, - "DPP: Schedule retransmission %d of Authentication Response frame in %u s", auth->auth_resp_tries, - wait_time); + "DPP: Retransmiting Authentication Response frame"); eloop_cancel_timeout(esp_dpp_auth_resp_retry_timeout, NULL, NULL); - eloop_register_timeout(wait_time, 0, esp_dpp_auth_resp_retry_timeout, NULL, NULL); + esp_dpp_auth_resp_retry_timeout(NULL, NULL); } -static void offchan_event_handler(void *arg, esp_event_base_t event_base, - int32_t event_id, void *event_data) +static void tx_status_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) { struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; - if (event_id == WIFI_EVENT_ACTION_TX_STATUS) { - wifi_event_action_tx_status_t *evt = event_data; + wifi_event_action_tx_status_t *evt = event_data; - wpa_printf(MSG_DEBUG, "Mgmt Tx Status - %d, Cookie - 0x%x", - evt->status, (uint32_t)evt->context); - if (!auth) { + wpa_printf(MSG_DEBUG, "Mgmt Tx Status - %d, Cookie - 0x%x", + evt->status, (uint32_t)evt->context); + + if (evt->op_id != s_current_tx_op_id) { + wpa_printf(MSG_DEBUG, "DPP: status not for recent frame op_id=%u, s_current_tx_op_id=%u", + evt->op_id, s_current_tx_op_id); + return; + } + if (!auth) { + esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_FAILURE); + return; + } + if (auth->waiting_auth_conf) { + eloop_cancel_timeout(esp_dpp_auth_resp_retry_timeout, NULL, NULL); + if (evt->status) { + /* failed to send auth response frame */ + eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); + eloop_register_timeout(1, 0, esp_dpp_auth_resp_retry, NULL, NULL); + } else { + eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); + eloop_register_timeout(ESP_DPP_AUTH_TIMEOUT_SECS, 0, esp_dpp_auth_conf_wait_timeout, NULL, NULL); + } + } else if (auth->auth_success) { + if (evt->status) { + /* failed to send gas query frame, retry logic needed? */ + wpa_printf(MSG_WARNING, "DPP: failed to send GAS query frame"); esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE); - return; + } else { + eloop_cancel_timeout(gas_query_timeout, NULL, auth); + eloop_register_timeout(ESP_GAS_TIMEOUT_SECS, 0, gas_query_timeout, NULL, auth); } - if (auth->waiting_auth_conf) { - if (evt->status) { - /* failed to send auth response frame */ - eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); - esp_dpp_auth_resp_retry(); - } else { - eloop_cancel_timeout(esp_dpp_auth_conf_wait_timeout, NULL, NULL); - eloop_register_timeout(ESP_DPP_AUTH_TIMEOUT_SECS, 0, esp_dpp_auth_conf_wait_timeout, NULL, NULL); - } - } else if (auth->auth_success) { - if (evt->status) { - /* failed to send gas query frame, retry logic needed? */ - esp_dpp_call_cb(ESP_SUPP_DPP_FAIL, (void *)ESP_ERR_DPP_TX_FAILURE); - } else { - eloop_cancel_timeout(gas_query_timeout, NULL, auth); - eloop_register_timeout(2, 0, gas_query_timeout, NULL, auth); - } - } - } else if (event_id == WIFI_EVENT_ROC_DONE) { - wifi_event_roc_done_t *evt = (wifi_event_roc_done_t *)event_data; + } +} - if (s_dpp_listen_in_progress && evt->context == (uint32_t)s_action_rx_cb) { - eloop_register_timeout(0, 0, esp_dpp_listen_next_channel, NULL, NULL); - } +static void roc_status_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + wifi_event_roc_done_t *evt = (wifi_event_roc_done_t *)event_data; + + if (s_dpp_listen_in_progress && evt->context == (uint32_t)s_action_rx_cb) { + eloop_register_timeout(0, 0, esp_dpp_listen_next_channel, NULL, NULL); } } @@ -879,20 +845,28 @@ esp_err_t esp_supp_dpp_bootstrap_gen(const char *chan_list, enum dpp_bootstrap_type type, const char *key, const char *uri_info) { - if (!s_dpp_ctx.dpp_global) { + int ret = dpp_api_lock(); + if (ret != ESP_OK) { + return ret; + } + if (!s_dpp_ctx.dpp_init_done) { + dpp_api_unlock(); wpa_printf(MSG_ERROR, "DPP: failed to bootstrap as dpp not initialized."); return ESP_FAIL; } + dpp_api_unlock(); + struct dpp_bootstrap_params_t *params = &s_dpp_ctx.bootstrap_params; char *uri_chan_list = esp_dpp_parse_chan_list(chan_list); + wpa_printf(MSG_DEBUG, "DPP: Starting bootstrap genration"); if (params->num_chan > ESP_DPP_MAX_CHAN_COUNT) { os_free(uri_chan_list); + wpa_printf(MSG_ERROR, "DPP: Invalid channel list"); return ESP_ERR_DPP_INVALID_LIST; } char *command = os_zalloc(1200); - int ret; if (!uri_chan_list || !command || params->num_chan > ESP_DPP_MAX_CHAN_COUNT || params->num_chan == 0) { wpa_printf(MSG_ERROR, "Invalid Channel list - %s", chan_list); @@ -931,15 +905,7 @@ esp_supp_dpp_bootstrap_gen(const char *chan_list, enum dpp_bootstrap_type type, params->info_len ? " info=" : "", params->info_len ? params->info : ""); - ret = esp_dpp_post_evt(SIG_DPP_BOOTSTRAP_GEN, (u32)command); - if (ret != ESP_OK) { - os_free(command); - if (params->info) { - os_free(params->info); - params->info = NULL; - } - goto fail; - } + eloop_register_timeout(0, 0, esp_dpp_bootstrap_gen, command, NULL); ret = ESP_OK; fail: @@ -952,49 +918,93 @@ fail: esp_err_t esp_supp_dpp_start_listen(void) { - if (s_dpp_listen_in_progress) { - wpa_printf(MSG_ERROR, "DPP: Failed to start listen as listen is already in progress."); - return ESP_FAIL; + int ret = dpp_api_lock(); + if (ret != ESP_OK) { + return ret; } - - if (!s_dpp_ctx.dpp_global || s_dpp_ctx.id < 1) { + if (!s_dpp_ctx.dpp_init_done || !s_dpp_ctx.bootstrap_done) { wpa_printf(MSG_ERROR, "DPP: failed to start listen as dpp not initialized or bootstrapped."); + dpp_api_unlock(); return ESP_FAIL; } + dpp_api_unlock(); if (esp_wifi_get_user_init_flag_internal() == 0) { wpa_printf(MSG_ERROR, "DPP: ROC not possible before wifi is started"); return ESP_ERR_INVALID_STATE; } + wpa_printf(MSG_DEBUG, "DPP: Starting ROC"); /* cancel previous ROC if ongoing */ esp_supp_dpp_stop_listen(); - + s_dpp_listen_in_progress = true; eloop_register_timeout(0, 0, esp_dpp_listen_next_channel, NULL, NULL); return 0; } esp_err_t esp_supp_dpp_stop_listen(void) { - s_dpp_listen_in_progress = false; - wifi_roc_req_t req = {0}; - req.ifx = WIFI_IF_STA; - req.type = WIFI_ROC_CANCEL; - esp_err_t ret = esp_wifi_remain_on_channel(&req); + eloop_register_timeout(0, 0, listen_stop_handler, NULL, NULL); + return ESP_OK; +} + +/* this is called from public API, need protection */ +bool is_dpp_enabled(void) +{ + int ret; + ret = dpp_api_lock(); if (ret != ESP_OK) { - wpa_printf(MSG_ERROR, "DPP: ROC cancel failed"); + return false; } + ret = s_dpp_ctx.dpp_init_done; + dpp_api_unlock(); + return ret; } -bool is_dpp_enabled(void) +/* Caller supposed to have dpp_api_lock() before calling this in blocking context */ +static int esp_dpp_init(void *eloop_data, void *user_ctx) { - return (s_dpp_ctx.dpp_global ? true : false); + struct dpp_global_config cfg = {0}; + int ret; + esp_supp_dpp_event_cb_t cb = user_ctx; + + cfg.cb_ctx = &s_dpp_ctx; + cfg.msg_ctx = &s_dpp_ctx; + os_bzero(&s_dpp_ctx, sizeof(s_dpp_ctx)); + + s_dpp_ctx.dpp_global = dpp_global_init(&cfg); + if (!s_dpp_ctx.dpp_global) { + wpa_printf(MSG_ERROR, "DPP: failed to allocate memory for dpp_global"); + ret = ESP_ERR_NO_MEM; + goto init_fail; + } + + s_dpp_listen_in_progress = false; + s_dpp_ctx.dpp_event_cb = cb; + + esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_ACTION_TX_STATUS, + &tx_status_handler, NULL); + esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_ROC_DONE, + &roc_status_handler, NULL); + + wpa_printf(MSG_INFO, "DPP: dpp init done"); + s_dpp_ctx.dpp_init_done = true; + + return ESP_OK; +init_fail: + if (s_dpp_ctx.dpp_global) { + dpp_global_deinit(s_dpp_ctx.dpp_global); + s_dpp_ctx.dpp_global = NULL; + } + return ret; + } esp_err_t esp_supp_dpp_init(esp_supp_dpp_event_cb_t cb) { esp_err_t ret = ESP_OK; + wifi_mode_t mode = 0; if (esp_wifi_get_mode(&mode) || ((mode != WIFI_MODE_STA) && (mode != WIFI_MODE_APSTA))) { wpa_printf(MSG_ERROR, "DPP: failed to init as not in station mode."); @@ -1005,102 +1015,59 @@ esp_err_t esp_supp_dpp_init(esp_supp_dpp_event_cb_t cb) wpa_printf(MSG_ERROR, "DPP: failed to init since WPS is enabled"); return ESP_FAIL; } - if (s_dpp_ctx.dpp_global) { + + ret = dpp_api_lock(); + if (ret != ESP_OK) { + return ret; + } + if (s_dpp_ctx.dpp_init_done) { wpa_printf(MSG_ERROR, "DPP: failed to init as init already done. Please deinit first and retry."); + dpp_api_unlock(); return ESP_FAIL; } - - os_bzero(&s_dpp_ctx, sizeof(s_dpp_ctx)); - struct dpp_global_config cfg = {0}; - cfg.cb_ctx = &s_dpp_ctx; - cfg.msg_ctx = &s_dpp_ctx; - s_dpp_ctx.dpp_global = dpp_global_init(&cfg); - if (!s_dpp_ctx.dpp_global) { - wpa_printf(MSG_ERROR, "DPP: failed to allocate memory for dpp_global"); - ret = ESP_ERR_NO_MEM; - goto init_fail; - } - - s_dpp_api_lock = os_recursive_mutex_create(); - if (!s_dpp_api_lock) { - wpa_printf(MSG_ERROR, "DPP: dpp_init: failed to create DPP API lock"); - ret = ESP_ERR_NO_MEM; - goto init_fail; - } - - s_dpp_evt_queue = os_queue_create(3, sizeof(dpp_event_t)); - if (!s_dpp_evt_queue) { - wpa_printf(MSG_ERROR, "DPP: dpp_init: failed to create DPP API queue"); - ret = ESP_ERR_NO_MEM; - goto init_fail; - } - - ret = os_task_create(esp_dpp_task, "dppT", DPP_TASK_STACK_SIZE, NULL, 15, &s_dpp_task_hdl); - if (ret != TRUE) { - wpa_printf(MSG_ERROR, "DPP: failed to create task"); - ret = ESP_ERR_NO_MEM; - goto init_fail; - } - - s_dpp_listen_in_progress = false; - s_dpp_ctx.dpp_event_cb = cb; - - esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_ACTION_TX_STATUS, - &offchan_event_handler, NULL); - esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_ROC_DONE, - &offchan_event_handler, NULL); - - wpa_printf(MSG_INFO, "esp_dpp_task prio:%d, stack:%d", 2, DPP_TASK_STACK_SIZE); - - return ESP_OK; -init_fail: - if (s_dpp_ctx.dpp_global) { - dpp_global_deinit(s_dpp_ctx.dpp_global); - s_dpp_ctx.dpp_global = NULL; - } - if (s_dpp_api_lock) { - os_mutex_delete(s_dpp_api_lock); - s_dpp_api_lock = NULL; - } - if (s_dpp_evt_queue) { - os_queue_delete(s_dpp_evt_queue); - s_dpp_evt_queue = NULL; - } + ret = eloop_register_timeout_blocking(esp_dpp_init, NULL, cb); + dpp_api_unlock(); return ret; } esp_err_t esp_dpp_start_net_intro_protocol(uint8_t *bssid) { struct dpp_authentication *auth = s_dpp_ctx.dpp_auth; - struct wpabuf *buf; + struct wpabuf *buf = NULL; + int ret = ESP_OK; + for (int i = 0; i < auth->num_conf_obj; i++) { os_memcpy(auth->peer_mac_addr, bssid, ETH_ALEN); buf = dpp_build_peer_disc_req(auth, &auth->conf_obj[i]); - if (buf) { - if (esp_dpp_send_action_frame(bssid, wpabuf_head(buf), wpabuf_len(buf), auth->curr_chan, OFFCHAN_TX_WAIT_TIME) != ESP_OK) { - wpabuf_free(buf); - return ESP_FAIL; - } - } else { + if (!buf) { return ESP_ERR_NO_MEM; } + + if (esp_dpp_send_action_frame(bssid, wpabuf_head(buf), wpabuf_len(buf), + auth->curr_chan, OFFCHAN_TX_WAIT_TIME) != ESP_OK) { + ret = ESP_FAIL; + } + + wpabuf_free(buf); } - return ESP_OK; + + return ret; } esp_err_t esp_supp_dpp_deinit(void) { - - esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_ACTION_TX_STATUS, - &offchan_event_handler); - esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_ROC_DONE, - &offchan_event_handler); - if (s_dpp_ctx.dpp_global) { - if (esp_dpp_post_evt(SIG_DPP_DEL_TASK, 0)) { - wpa_printf(MSG_ERROR, "DPP Deinit Failed"); - } + int ret = dpp_api_lock(); + if (ret != ESP_OK) { + return ret; } + if (!s_dpp_ctx.dpp_init_done) { + wpa_printf(MSG_DEBUG, "DPP: Already disabled"); + dpp_api_unlock(); + return ESP_OK; + } + dpp_api_unlock(); + eloop_register_timeout_blocking(esp_dpp_deinit, NULL, NULL); return ESP_OK; } #endif diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h index f7f8f1e6d9..651dfdbcc3 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,25 +14,10 @@ #include "esp_dpp.h" #include "esp_wifi_driver.h" -#define DPP_TASK_STACK_SIZE (6144 + TASK_STACK_SIZE_ADD) +#define ESP_DPP_AUTH_TIMEOUT_SECS 2 +#define ESP_GAS_TIMEOUT_SECS 2 #define ESP_DPP_PMK_CACHE_DEFAULT_TIMEOUT 86400 * 7 /*!< 7 days */ -enum SIG_DPP { - SIG_DPP_RESET = 0, - SIG_DPP_BOOTSTRAP_GEN, - SIG_DPP_RX_ACTION, - SIG_DPP_LISTEN_NEXT_CHANNEL, - SIG_DPP_DEL_TASK, - SIG_DPP_START_NET_INTRO, - SIG_DPP_DEINIT_AUTH, - SIG_DPP_MAX, -}; - -typedef struct { - uint32_t id; - uint32_t data; -} dpp_event_t; - #define BOOTSTRAP_ROC_WAIT_TIME 500 #define OFFCHAN_TX_WAIT_TIME 600 @@ -53,11 +38,10 @@ struct esp_dpp_context_t { struct dpp_global *dpp_global; wifi_config_t wifi_cfg; int id; + bool dpp_init_done; + bool bootstrap_done; }; -int esp_supp_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel); -esp_err_t esp_dpp_post_evt(uint32_t evt_id, uint32_t data); - #ifdef CONFIG_TESTING_OPTIONS int dpp_test_gen_invalid_key(struct wpabuf *msg, const struct dpp_curve_params *curve); char * dpp_corrupt_connector_signature(const char *connector); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c index 24cbc34a21..80f48cb824 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -213,7 +213,7 @@ int dpp_connect(uint8_t *bssid, bool pdr_done) int res = 0; if (!pdr_done) { if (esp_wifi_sta_get_prof_authmode_internal() == WPA3_AUTH_DPP) { - esp_dpp_post_evt(SIG_DPP_START_NET_INTRO, (u32)bssid); + esp_dpp_start_net_intro_protocol(bssid); } } else { res = wpa_config_bss(bssid); diff --git a/components/wpa_supplicant/src/common/dpp.c b/components/wpa_supplicant/src/common/dpp.c index 7fa67d10fa..fd7a1f9848 100644 --- a/components/wpa_supplicant/src/common/dpp.c +++ b/components/wpa_supplicant/src/common/dpp.c @@ -84,7 +84,7 @@ void dpp_debug_print_point(const char *title, struct crypto_ec *e, static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) { - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); + wpa_printf(MSG_INFO, "%s", txt); } struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type, From 859d18a1236b84a7730e1d2286e19d12ae35542c Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Mon, 14 Apr 2025 16:14:30 +0530 Subject: [PATCH 4/5] fix(esp_wifi): Fixed some concurrency issues in eloop deinit --- components/wpa_supplicant/port/eloop.c | 48 ++++++++++++++++++-------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/components/wpa_supplicant/port/eloop.c b/components/wpa_supplicant/port/eloop.c index b680c54f08..297644b0af 100644 --- a/components/wpa_supplicant/port/eloop.c +++ b/components/wpa_supplicant/port/eloop.c @@ -18,6 +18,7 @@ #include "eloop.h" #include "esp_wifi_driver.h" #include "rom/ets_sys.h" +#include bool current_task_is_wifi_task(void); @@ -39,7 +40,8 @@ struct eloop_timeout { struct eloop_data { struct dl_list timeout; ETSTimer eloop_timer; - bool eloop_started; + atomic_bool eloop_started; + atomic_bool timeout_running; void *eloop_semph; }; @@ -80,7 +82,8 @@ int eloop_init(void) wpa_printf(MSG_ERROR, "failed to create eloop data loop"); return -1; } - eloop.eloop_started = true; + atomic_store(&eloop.eloop_started, true); + atomic_store(&eloop.timeout_running, false); return 0; } @@ -101,6 +104,9 @@ int eloop_register_timeout(unsigned int secs, unsigned int usecs, int count = 0; #endif + if (!atomic_load(&eloop.eloop_started)) { + return -1; + } timeout = os_zalloc(sizeof(*timeout)); if (timeout == NULL) { return -1; @@ -188,6 +194,10 @@ int eloop_register_timeout_blocking(eloop_blocking_timeout_handler handler, assert(false); return -1; } + + if (!atomic_load(&eloop.eloop_started)) { + return -1; + } timeout = os_zalloc(sizeof(*timeout)); if (timeout == NULL) { return -1; @@ -429,6 +439,11 @@ void eloop_run(void) { struct os_reltime tv, now; + if (!atomic_load(&eloop.eloop_started)) { + return; + } + atomic_store(&eloop.timeout_running, true); + while (!dl_list_empty(&eloop.timeout)) { struct eloop_timeout *timeout; @@ -446,15 +461,7 @@ void eloop_run(void) os_timer_arm(&eloop.eloop_timer, ms, 0); ELOOP_UNLOCK(); goto out; - } - } - - /* check if some registered timeouts have occurred */ - timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, - list); - if (timeout) { - os_get_reltime(&now); - if (!os_reltime_before(&now, &timeout->time)) { + } else { void *eloop_data = timeout->eloop_data; void *user_data = timeout->user_data; void *sync_semaphr = timeout->sync_semph; @@ -491,20 +498,28 @@ void eloop_run(void) } } out: + atomic_store(&eloop.timeout_running, false); return; } void eloop_destroy(void) { struct eloop_timeout *timeout, *prev; - struct os_reltime now; - if (!eloop.eloop_started) { + if (!atomic_load(&eloop.eloop_started)) { return; } - os_get_reltime(&now); + + atomic_store(&eloop.eloop_started, false); + + while (atomic_load(&eloop.timeout_running)) { + vTaskDelay(100 / portTICK_PERIOD_MS); // Yield CPU + } dl_list_for_each_safe(timeout, prev, &eloop.timeout, struct eloop_timeout, list) { +#ifdef ELOOP_DEBUG + struct os_reltime now; + os_get_reltime(&now); int sec, usec; sec = timeout->time.sec - now.sec; usec = timeout->time.usec - now.usec; @@ -516,12 +531,17 @@ void eloop_destroy(void) "eloop_data=%p user_data=%p handler=%p", sec, usec, timeout->eloop_data, timeout->user_data, timeout->handler); +#endif eloop_remove_timeout(timeout); } if (eloop_data_lock) { os_mutex_delete(eloop_data_lock); eloop_data_lock = NULL; } + if (eloop.eloop_semph) { + os_semphr_delete(eloop.eloop_semph); + eloop.eloop_semph = NULL; + } os_timer_disarm(&eloop.eloop_timer); os_timer_done(&eloop.eloop_timer); os_memset(&eloop, 0, sizeof(eloop)); From 6e1b2aa23ff35904e697a0ac59f7441127948b72 Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Mon, 14 Apr 2025 20:29:24 +0530 Subject: [PATCH 5/5] ci(esp_wifi): Extend eloop test to verify wifi deinit properly --- .../wpa_supplicant/test_apps/main/test_eloop.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/components/wpa_supplicant/test_apps/main/test_eloop.c b/components/wpa_supplicant/test_apps/main/test_eloop.c index ea2b115ef4..c32b635f7d 100644 --- a/components/wpa_supplicant/test_apps/main/test_eloop.c +++ b/components/wpa_supplicant/test_apps/main/test_eloop.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -25,7 +25,6 @@ static int executed_order[6]; static int t; static struct os_reltime ts; - /* there is only single instance of esp_timer so no need of protection */ static void callback(void *a, void *b) { @@ -80,6 +79,15 @@ TEST_CASE("Test eloop timers run", "[eloop]") os_sleep(20, 0); /* check the execution order, this will also check whether they were fired at correct time */ TEST_ASSERT(memcmp(execution_order, executed_order, 6 * sizeof(int)) == 0); + + /* Add timers to check deinit happens gracefully */ + for (int i = 0; i < 6; i++) { + eloop_register_timeout(timeouts_sec[i], timeouts_usec[i], + callback, &index[i], NULL); + } + + /* Stop wifi before all the timers have run */ + os_sleep(2, 0); TEST_ESP_OK(esp_wifi_stop()); TEST_ESP_OK(esp_wifi_deinit()); os_sleep(3, 0);