From a96d680fc550564a8a468d363d982f5ccf3559cf Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Mon, 7 Oct 2024 13:51:14 +0530 Subject: [PATCH] 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;