From ec3c82c1778184cab9def2b116919fdb0f2f104c Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Wed, 15 Apr 2026 21:14:39 +0530 Subject: [PATCH] fix(esp_wifi): Backport some fixes to v6.0 --- .../src/crypto/crypto_mbedtls-ec.c | 74 +++++++-------- .../wpa_supplicant/test_apps/main/test_dpp.c | 93 +++++++++++++------ 2 files changed, 98 insertions(+), 69 deletions(-) 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 f33d001126e..1959abadf77 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 @@ -1610,6 +1610,23 @@ static psa_ecc_family_t group_id_to_psa(mbedtls_ecp_group_id grp_id, size_t *bit } } +static size_t crypto_ecdh_output_size(const crypto_ec_key_wrapper_t *wrapper) +{ + size_t key_bits = 0; + psa_ecc_family_t ecc_family; + + if (!wrapper) { + return 0; + } + + ecc_family = group_id_to_psa(wrapper->curve_id, &key_bits); + if (ecc_family == 0 || key_bits == 0) { + return 0; + } + + return PSA_BITS_TO_BYTES(key_bits); +} + struct crypto_ec_key * crypto_ec_key_set_pub(const struct crypto_ec_group *group, const u8 *buf, size_t len) { @@ -1960,46 +1977,6 @@ struct crypto_bignum *crypto_ec_key_get_private_key(struct crypto_ec_key *key) return (struct crypto_bignum *)wrapper->cached_private_key; } - { - psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_status_t status; - size_t raw_len = 0; - size_t raw_size; - u8 *raw_key = NULL; - mbedtls_mpi *d = NULL; - - status = psa_get_key_attributes(wrapper->key_id, &key_attributes); - if (status == PSA_SUCCESS) { - raw_size = PSA_EXPORT_KEY_OUTPUT_SIZE(psa_get_key_type(&key_attributes), - psa_get_key_bits(&key_attributes)); - psa_reset_key_attributes(&key_attributes); - - raw_key = os_malloc(raw_size); - d = os_calloc(1, sizeof(*d)); - if (raw_key && d) { - status = psa_export_key(wrapper->key_id, raw_key, raw_size, &raw_len); - if (status == PSA_SUCCESS) { - mbedtls_mpi_init(d); - if (mbedtls_mpi_read_binary(d, raw_key, raw_len) == 0) { - wrapper->cached_private_key = d; - forced_memzero(raw_key, raw_size); - os_free(raw_key); - return (struct crypto_bignum *) wrapper->cached_private_key; - } - mbedtls_mpi_free(d); - } - } - - if (d) { - os_free(d); - } - if (raw_key) { - forced_memzero(raw_key, raw_size); - } - os_free(raw_key); - } - } - mbedtls_pk_context *pkey_ctx = os_calloc(1, sizeof(mbedtls_pk_context)); if (!pkey_ctx) { return NULL; @@ -2385,10 +2362,17 @@ int crypto_ecdh(struct crypto_ec_key *key_own, struct crypto_ec_key *key_peer, { crypto_ec_key_wrapper_t *peer_wrapper = (crypto_ec_key_wrapper_t *)key_peer; crypto_ec_key_wrapper_t *own_wrapper = (crypto_ec_key_wrapper_t *)key_own; + size_t secret_buf_size; + if (!peer_wrapper || !own_wrapper) { return -1; } + secret_buf_size = crypto_ecdh_output_size(own_wrapper); + if (secret_buf_size == 0) { + return -1; + } + #if CONFIG_MBEDTLS_HARDWARE_MPI && !CONFIG_MBEDTLS_HARDWARE_ECC *secret_len = 0; @@ -2405,7 +2389,8 @@ int crypto_ecdh(struct crypto_ec_key *key_own, struct crypto_ec_key *key_peer, own_wrapper->key_id, peer_wrapper->cached_public_key_buf, peer_wrapper->cached_public_key_len, - secret, 66, &secret_length); + secret, secret_buf_size, + &secret_length); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "psa_raw_key_agreement failed with %d", status); return -1; @@ -2434,7 +2419,8 @@ int crypto_ecdh(struct crypto_ec_key *key_own, struct crypto_ec_key *key_peer, *secret_len = 0; size_t secret_length = 0; status = psa_raw_key_agreement(PSA_ALG_ECDH, own_wrapper->key_id, - peer_key_buf, peer_key_len, secret, 66, + peer_key_buf, peer_key_len, secret, + secret_buf_size, &secret_length); if (status != PSA_SUCCESS) { wpa_printf(MSG_ERROR, "psa_raw_key_agreement failed with %d", status); @@ -3233,6 +3219,10 @@ void crypto_ec_key_deinit(struct crypto_ec_key *key) } #if CONFIG_MBEDTLS_HARDWARE_MPI && !CONFIG_MBEDTLS_HARDWARE_ECC if (wrapper->cached_public_key_buf) { + if (wrapper->cached_public_key_len) { + forced_memzero(wrapper->cached_public_key_buf, + wrapper->cached_public_key_len); + } os_free(wrapper->cached_public_key_buf); } #endif diff --git a/components/wpa_supplicant/test_apps/main/test_dpp.c b/components/wpa_supplicant/test_apps/main/test_dpp.c index 4f52ad8ace7..58c27e85ed0 100644 --- a/components/wpa_supplicant/test_apps/main/test_dpp.c +++ b/components/wpa_supplicant/test_apps/main/test_dpp.c @@ -18,6 +18,8 @@ #include "common/dpp.h" #include "sdkconfig.h" #include "test_wpa_supplicant_common.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #ifdef CONFIG_ESP_WIFI_TESTING_OPTIONS struct dpp_global { @@ -42,15 +44,18 @@ static void dpp_test_clear_overrides(void) static u32 dpp_test_prod_limit_us(void) { -#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 - return 300000; -#elif SOC_ECC_SUPPORTED +#if CONFIG_MBEDTLS_HARDWARE_ECC return 100000; #else - return 100000; + return 325000; #endif } +static int dpp_test_leak_threshold(void) +{ + return 800; +} + static void dpp_test_log_auth_timing(const char *label, const struct dpp_authentication *auth) { @@ -66,7 +71,7 @@ static void dpp_test_log_auth_timing(const char *label, TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]") { - set_leak_threshold(300); + set_leak_threshold(dpp_test_leak_threshold()); /* Global variables */ char command[1200] = {0}; const u8 *frame; @@ -165,7 +170,6 @@ TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]") len -= 26; auth_instance = dpp_auth_req_rx(NULL, 1, 0, NULL, dpp_bootstrap_get_id(dpp, id), 2412, frame, frame + 6, len - 6); - TEST_ASSERT_NOT_NULL(auth_instance); TEST_ASSERT_NOT_NULL(auth_instance->resp_msg); dpp_test_log_auth_timing("Vector responder", auth_instance); @@ -231,27 +235,41 @@ TEST_CASE("Test DPP responder p256 production timing", "[wpa_dpp][performance]") int responder_id; int initiator_id; u32 limit_us = dpp_test_prod_limit_us(); + u64 total_us = 0; + const char *failure = NULL; - set_leak_threshold(300); + set_leak_threshold(dpp_test_leak_threshold()); os_memset(&dpp_conf, 0, sizeof(dpp_conf)); dpp = dpp_global_init(&dpp_conf); - TEST_ASSERT_NOT_NULL(dpp); + if (!dpp) { + TEST_FAIL_MESSAGE("Failed to initialize DPP global context"); + } responder_id = dpp_bootstrap_gen(dpp, "type=qrcode curve=P-256"); - TEST_ASSERT(responder_id > 0); + if (responder_id <= 0) { + failure = "Failed to generate responder bootstrap"; + goto cleanup; + } initiator_id = dpp_bootstrap_gen(dpp, "type=qrcode curve=P-256"); - TEST_ASSERT(initiator_id > 0); + if (initiator_id <= 0) { + failure = "Failed to generate initiator bootstrap"; + goto cleanup; + } responder_bi = dpp_bootstrap_get_id(dpp, responder_id); initiator_bi = dpp_bootstrap_get_id(dpp, initiator_id); - TEST_ASSERT_NOT_NULL(responder_bi); - TEST_ASSERT_NOT_NULL(initiator_bi); + if (!responder_bi || !initiator_bi) { + failure = "Failed to resolve bootstrap info"; + goto cleanup; + } dpp_test_clear_overrides(); initiator_auth = dpp_auth_init(NULL, responder_bi, initiator_bi, DPP_CAPAB_CONFIGURATOR, 2412, NULL, 0); - TEST_ASSERT_NOT_NULL(initiator_auth); - TEST_ASSERT_NOT_NULL(initiator_auth->req_msg); + if (!initiator_auth || !initiator_auth->req_msg) { + failure = "Failed to initialize DPP initiator authentication"; + goto cleanup; + } frame = wpabuf_head_u8(initiator_auth->req_msg) + 2; len = wpabuf_len(initiator_auth->req_msg) - 2; @@ -259,36 +277,57 @@ TEST_CASE("Test DPP responder p256 production timing", "[wpa_dpp][performance]") NULL, responder_bi, 2412, frame, frame + DPP_HDR_LEN, len - DPP_HDR_LEN); - TEST_ASSERT_NOT_NULL(responder_auth); - TEST_ASSERT_NOT_NULL(responder_auth->resp_msg); + if (!responder_auth || !responder_auth->resp_msg) { + failure = "Failed to process DPP authentication request"; + goto cleanup; + } dpp_test_log_auth_timing("Production responder", responder_auth); + total_us = responder_auth->auth_req_total_us; if (limit_us) { ESP_LOGI("DPP Test", - "Production responder timing gate(us): total=%llu limit=%u", - (unsigned long long) responder_auth->auth_req_total_us, - limit_us); - TEST_ASSERT_MESSAGE(responder_auth->auth_req_total_us <= limit_us, - "DPP responder production timing regression"); + "Production responder timing gate(us): total=%llu limit=%lu", + (unsigned long long) total_us, + (unsigned long) limit_us); } frame = wpabuf_head_u8(responder_auth->resp_msg) + 2; len = wpabuf_len(responder_auth->resp_msg) - 2; conf = dpp_auth_resp_rx(initiator_auth, frame, frame + DPP_HDR_LEN, len - DPP_HDR_LEN); - TEST_ASSERT_NOT_NULL(conf); - TEST_ASSERT_EQUAL_INT(1, initiator_auth->auth_success); + if (!conf) { + failure = "Failed to process DPP authentication response"; + goto cleanup; + } + if (initiator_auth->auth_success != 1) { + failure = "Initiator authentication did not complete successfully"; + goto cleanup; + } frame = wpabuf_head_u8(conf) + 2; len = wpabuf_len(conf) - 2; - TEST_ASSERT_EQUAL_INT(0, dpp_auth_conf_rx(responder_auth, frame, - frame + DPP_HDR_LEN, - len - DPP_HDR_LEN)); - TEST_ASSERT_EQUAL_INT(1, responder_auth->auth_success); + if (dpp_auth_conf_rx(responder_auth, frame, frame + DPP_HDR_LEN, + len - DPP_HDR_LEN) != 0) { + failure = "Failed to process DPP authentication confirmation"; + goto cleanup; + } + if (responder_auth->auth_success != 1) { + failure = "Responder authentication did not complete successfully"; + goto cleanup; + } +cleanup: wpabuf_free(conf); dpp_auth_deinit(responder_auth); dpp_auth_deinit(initiator_auth); dpp_global_deinit(dpp); dpp_test_clear_overrides(); + + if (failure) { + TEST_FAIL_MESSAGE(failure); + } + if (limit_us) { + TEST_ASSERT_MESSAGE(total_us <= limit_us, + "DPP responder production timing regression"); + } } #endif