fix(esp_wifi): Optimize crypto operations for DPP

This commit is contained in:
Kapil Gupta
2026-04-12 09:00:25 +05:30
parent 37e7f60dcf
commit 85c164c2b7
12 changed files with 1231 additions and 167 deletions
@@ -4,12 +4,10 @@
* SPDX-License-Identifier: Apache-2.0
*/
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#ifdef ESP_PLATFORM
#include "esp_system.h"
#include "mbedtls/bignum.h"
#include "mbedtls/esp_mbedtls_random.h"
#include "soc/soc_caps.h"
#endif
#include "utils/includes.h"
#include "utils/common.h"
@@ -35,39 +33,6 @@ static int mpi_is_secp256r1_prime(const mbedtls_mpi *p)
return os_memcmp(p_be, p256_p_be, sizeof(p_be)) == 0;
}
static int p256_words_is_one(const u32 *a)
{
size_t i;
if (a[0] != 1) {
return 0;
}
for (i = 1; i < P256_WORDS; i++) {
if (a[i] != 0) {
return 0;
}
}
return 1;
}
static int p256_words_cmp(const u32 *a, const u32 *b)
{
int i;
for (i = P256_WORDS - 1; i >= 0; i--) {
if (a[i] < b[i]) {
return -1;
}
if (a[i] > b[i]) {
return 1;
}
}
return 0;
}
static size_t p256_words_ctz(const u32 *a)
{
size_t i;
File diff suppressed because it is too large Load Diff
@@ -4,10 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef ESP_PLATFORM
#include "mbedtls/bignum.h"
#include "mbedtls/esp_mbedtls_random.h"
#endif
#include "utils/includes.h"
#include "utils/common.h"
@@ -6,9 +6,7 @@
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#ifdef ESP_PLATFORM
#include "esp_system.h"
#endif
#include "sdkconfig.h"
#include <errno.h>
#include "utils/includes.h"
@@ -50,6 +50,39 @@ static inline int p256_words_is_zero(const u32 *a)
return 1;
}
static inline int p256_words_is_one(const u32 *a)
{
size_t i;
if (a[0] != 1U) {
return 0;
}
for (i = 1; i < P256_WORDS; i++) {
if (a[i] != 0U) {
return 0;
}
}
return 1;
}
static inline int p256_words_cmp(const u32 *x, const u32 *y)
{
int i;
for (i = P256_WORDS - 1; i >= 0; i--) {
if (x[i] > y[i]) {
return 1;
}
if (x[i] < y[i]) {
return -1;
}
}
return 0;
}
static inline size_t p256_words_bitlen(const u32 *a)
{
int i;
@@ -44,6 +44,35 @@ struct dpp_global {
extern struct dpp_curve_params dpp_curves[];
#ifdef CONFIG_TESTING_OPTIONS
static u64 dpp_time_us(void)
{
struct os_reltime now;
if (os_get_reltime(&now) < 0)
return 0;
return ((u64) now.sec * 1000000) + now.usec;
}
static void dpp_auth_req_set_timing(struct dpp_authentication *auth,
u64 start_us, u64 parse_done_us)
{
u64 end_us;
if (!auth || !start_us || !parse_done_us || parse_done_us < start_us)
return;
end_us = dpp_time_us();
if (!end_us || end_us < parse_done_us)
return;
auth->auth_req_parse_us = parse_done_us - start_us;
auth->auth_resp_form_us = end_us - parse_done_us;
auth->auth_req_total_us = end_us - start_us;
}
#endif /* CONFIG_TESTING_OPTIONS */
#define TRANSACTION_ID_ATTR_SET_LEN 5
#define CONNECTOR_ATTR_SET_LEN 4
@@ -1707,6 +1736,10 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
u16 i_capab_len;
u16 i_bootstrap_len;
struct dpp_authentication *auth = NULL;
#ifdef CONFIG_TESTING_OPTIONS
u64 start_us = dpp_time_us();
u64 parse_done_us = 0;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_TESTING_OPTIONS
if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) {
@@ -1892,9 +1925,15 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
wpa_printf(MSG_DEBUG,
"DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time");
#ifdef CONFIG_TESTING_OPTIONS
parse_done_us = dpp_time_us();
#endif /* CONFIG_TESTING_OPTIONS */
if (dpp_auth_build_resp_status(auth,
DPP_STATUS_RESPONSE_PENDING) < 0)
goto fail;
#ifdef CONFIG_TESTING_OPTIONS
dpp_auth_req_set_timing(auth, start_us, parse_done_us);
#endif /* CONFIG_TESTING_OPTIONS */
i_bootstrap = dpp_get_attr(attr_start, attr_len,
DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
&i_bootstrap_len);
@@ -1912,8 +1951,14 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual,
"%s", hex);
return auth;
}
#ifdef CONFIG_TESTING_OPTIONS
parse_done_us = dpp_time_us();
#endif /* CONFIG_TESTING_OPTIONS */
if (dpp_auth_build_resp_ok(auth) < 0)
goto fail;
#ifdef CONFIG_TESTING_OPTIONS
dpp_auth_req_set_timing(auth, start_us, parse_done_us);
#endif /* CONFIG_TESTING_OPTIONS */
return auth;
@@ -1926,8 +1971,14 @@ not_compatible:
auth->configurator = 0;
auth->peer_protocol_key = pi;
pi = NULL;
#ifdef CONFIG_TESTING_OPTIONS
parse_done_us = dpp_time_us();
#endif /* CONFIG_TESTING_OPTIONS */
if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0)
goto fail;
#ifdef CONFIG_TESTING_OPTIONS
dpp_auth_req_set_timing(auth, start_us, parse_done_us);
#endif /* CONFIG_TESTING_OPTIONS */
auth->remove_on_tx_status = 1;
return auth;
@@ -311,11 +311,15 @@ struct dpp_authentication {
int send_conn_status;
int conn_status_requested;
int akm_use_selector;
#ifdef CONFIG_TESTING_OPTIONS
char *config_obj_override;
char *discovery_override;
char *groups_override;
unsigned int ignore_netaccesskey_mismatch:1;
u64 auth_req_parse_us;
u64 auth_resp_form_us;
u64 auth_req_total_us;
#endif /* CONFIG_TESTING_OPTIONS */
};
@@ -35,8 +35,6 @@ const struct dpp_curve_params dpp_curves[] = {
#endif
{ NULL, 0, 0, 0, 0, NULL, 0, NULL }
};
const struct dpp_curve_params * dpp_get_curve_name(const char *name)
{
int i;
@@ -15,6 +15,10 @@ idf_component_register(SRCS
idf_component_get_property(esp_supplicant_dir wpa_supplicant COMPONENT_DIR)
if(CONFIG_ESP_WIFI_TESTING_OPTIONS)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_TESTING_OPTIONS)
endif()
# Calculate MD5 value of header file esp_wifi_driver.h
file(MD5 ${esp_supplicant_dir}/esp_supplicant/src/esp_wifi_driver.h WIFI_SUPPLICANT_MD5)
string(SUBSTRING "${WIFI_SUPPLICANT_MD5}" 0 7 WIFI_SUPPLICANT_MD5)
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,8 +18,16 @@
#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
static unsigned int dpp_test_task_stack_high_watermark_bytes(void)
{
return (unsigned int)(uxTaskGetStackHighWaterMark(NULL) *
sizeof(StackType_t));
}
struct dpp_global {
void *msg_ctx;
struct dl_list bootstrap; /* struct dpp_bootstrap_info */
@@ -32,9 +40,48 @@ extern u8 dpp_nonce_override[DPP_MAX_NONCE_LEN];
extern size_t dpp_nonce_override_len;
#define MAX_FRAME_SIZE 1200
static void dpp_test_clear_overrides(void)
{
dpp_protocol_key_override_len = 0;
dpp_nonce_override_len = 0;
os_memset(dpp_protocol_key_override, 0, sizeof(dpp_protocol_key_override));
os_memset(dpp_nonce_override, 0, sizeof(dpp_nonce_override));
}
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
return 100000;
#else
return 100000;
#endif
}
static int dpp_test_leak_threshold(void)
{
return 400;
}
static void dpp_test_log_auth_timing(const char *label,
const struct dpp_authentication *auth)
{
TEST_ASSERT_NOT_NULL(auth);
ESP_LOGI("DPP Test",
"%s timing(us): parse=%llu response_form=%llu total=%llu",
label,
(unsigned long long) auth->auth_req_parse_us,
(unsigned long long) auth->auth_resp_form_us,
(unsigned long long) auth->auth_req_total_us);
ESP_LOGI("DPP Test", "%s task stack high watermark(bytes): %u",
label, dpp_test_task_stack_high_watermark_bytes());
}
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;
@@ -136,6 +183,7 @@ TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]")
TEST_ASSERT_NOT_NULL(auth_instance);
TEST_ASSERT_NOT_NULL(auth_instance->resp_msg);
dpp_test_log_auth_timing("Vector responder", auth_instance);
/* auth response u8 */
hex_len = os_strlen(auth_resp);
@@ -179,7 +227,83 @@ TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]")
{
dpp_auth_deinit(auth_instance);
dpp_global_deinit(dpp);
dpp_test_clear_overrides();
}
ESP_LOGI("DPP Test", "Test case passed");
}
TEST_CASE("Test DPP responder p256 production timing", "[wpa_dpp][performance]")
{
struct dpp_global_config dpp_conf;
struct dpp_global *dpp = NULL;
struct dpp_bootstrap_info *responder_bi = NULL;
struct dpp_bootstrap_info *initiator_bi = NULL;
struct dpp_authentication *initiator_auth = NULL;
struct dpp_authentication *responder_auth = NULL;
struct wpabuf *conf = NULL;
const u8 *frame;
size_t len;
int responder_id;
int initiator_id;
u32 limit_us = dpp_test_prod_limit_us();
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);
responder_id = dpp_bootstrap_gen(dpp, "type=qrcode curve=P-256");
TEST_ASSERT(responder_id > 0);
initiator_id = dpp_bootstrap_gen(dpp, "type=qrcode curve=P-256");
TEST_ASSERT(initiator_id > 0);
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);
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);
frame = wpabuf_head_u8(initiator_auth->req_msg) + 2;
len = wpabuf_len(initiator_auth->req_msg) - 2;
responder_auth = dpp_auth_req_rx(NULL, DPP_CAPAB_ENROLLEE, 0,
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);
dpp_test_log_auth_timing("Production responder", responder_auth);
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");
}
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);
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);
wpabuf_free(conf);
dpp_auth_deinit(responder_auth);
dpp_auth_deinit(initiator_auth);
dpp_global_deinit(dpp);
dpp_test_clear_overrides();
}
#endif
@@ -21,9 +21,17 @@
#include "test_utils.h"
#include "test_wpa_supplicant_common.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
typedef struct crypto_bignum crypto_bignum;
static unsigned int test_task_stack_high_watermark_bytes(void)
{
return (unsigned int)(uxTaskGetStackHighWaterMark(NULL) *
sizeof(StackType_t));
}
static int sae_commit_parse_limit_us(void)
{
#if CONFIG_IDF_TARGET_ESP32
@@ -258,34 +266,50 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
struct wpabuf *buf;
int default_groups[] = { IANA_SECP256R1, 0 };
int64_t start_us;
int64_t total_start_us;
int64_t total_us;
int64_t prepare_us;
int64_t write_us;
int64_t parse_us;
int64_t formation_us;
int limit_us = sae_commit_parse_limit_us();
memset(&sae, 0, sizeof(sae));
start_us = esp_timer_get_time();
total_start_us = esp_timer_get_time();
TEST_ASSERT(sae_set_group(&sae, IANA_SECP256R1) == 0);
start_us = esp_timer_get_time();
TEST_ASSERT(sae_prepare_commit(addr1, addr2, pwd, strlen((const char *)pwd), &sae) == 0);
prepare_us = esp_timer_get_time() - start_us;
buf = wpabuf_alloc2(SAE_COMMIT_MAX_LEN);
TEST_ASSERT(buf != NULL);
start_us = esp_timer_get_time();
sae_write_commit(&sae, buf, NULL, NULL);// No anti-clogging token
write_us = esp_timer_get_time() - start_us;
formation_us = prepare_us + write_us;
/* Parsing commit created by self will be detected as reflection attack*/
start_us = esp_timer_get_time();
TEST_ASSERT(sae_parse_commit(&sae,
wpabuf_mhead(buf), buf->used, NULL, 0, default_groups, 0) == SAE_SILENTLY_DISCARD);
parse_us = esp_timer_get_time() - start_us;
wpabuf_free2(buf);
sae_clear_temp_data(&sae);
sae_clear_data(&sae);
total_us = esp_timer_get_time() - start_us;
total_us = esp_timer_get_time() - total_start_us;
ESP_LOGI("SAE Test",
"Commit/parse timing(us): total=%lld limit=%d",
"Commit/parse timing(us): prepare=%lld write=%lld formation=%lld parse=%lld total=%lld limit=%d",
(long long) prepare_us, (long long) write_us,
(long long) formation_us, (long long) parse_us,
(long long) total_us, limit_us);
ESP_LOGI("SAE Test", "Task stack high watermark(bytes): %u",
test_task_stack_high_watermark_bytes());
TEST_ASSERT_MESSAGE(total_us <= limit_us, "SAE commit/parse timing regression");
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -20,6 +20,7 @@
#include "utils/wpabuf.h"
#include "test_utils.h"
#include "test_wpa_supplicant_common.h"
#include "esp_timer.h"
/* Helper functions for random SSID and password generation */
static void generate_random_string(char *str, size_t len, bool include_special)
@@ -55,13 +56,23 @@ static void generate_random_password(char *password)
TEST_CASE("Test SAE H2E complete workflow", "[wpa3_sae_h2e]")
{
set_leak_threshold(600);
struct sae_data sae;
struct wpabuf *buf = NULL;
struct sae_data sae1;
struct sae_data sae2;
struct wpabuf *buf1 = NULL;
struct wpabuf *buf2 = NULL;
struct wpabuf *confirm1 = NULL;
struct wpabuf *confirm2 = NULL;
const u8 addr1[ETH_ALEN] = { 0x4d, 0x3f, 0x2f, 0xff, 0xe3, 0x87 };
const u8 addr2[ETH_ALEN] = { 0xa5, 0xd8, 0xaa, 0x95, 0x8e, 0x3c };
char password[64];
char ssid[33];
size_t ssid_len;
struct sae_pt *pt = NULL;
int default_groups[] = { IANA_SECP256R1, 0 };
int64_t start_us;
int64_t prepare1_us, write1_us, form1_us, parse1_us;
int64_t prepare2_us, write2_us, form2_us, parse2_us;
int64_t process1_us, process2_us;
/* Generate random SSID and password */
generate_random_ssid(ssid, &ssid_len);
@@ -73,80 +84,144 @@ TEST_CASE("Test SAE H2E complete workflow", "[wpa3_sae_h2e]")
/* Step 1: Test H2E initialization */
ESP_LOGI("H2E", "\nStep 1: Testing H2E initialization");
memset(&sae, 0, sizeof(sae));
ESP_LOGI("H2E", "- Initial SAE state: h2e=%d", sae.h2e);
memset(&sae1, 0, sizeof(sae1));
memset(&sae2, 0, sizeof(sae2));
ESP_LOGI("H2E", "- Initial SAE state: sta1.h2e=%d sta2.h2e=%d",
sae1.h2e, sae2.h2e);
TEST_ASSERT_MESSAGE(sae_set_group(&sae, IANA_SECP256R1) == 0, "Failed to set SAE group");
ESP_LOGI("H2E", "- After group set: group=%d", sae.group);
TEST_ASSERT_MESSAGE(sae.h2e == 0, "H2E should be disabled by default");
TEST_ASSERT_MESSAGE(sae_set_group(&sae1, IANA_SECP256R1) == 0, "Failed to set SAE group for STA1");
TEST_ASSERT_MESSAGE(sae_set_group(&sae2, IANA_SECP256R1) == 0, "Failed to set SAE group for STA2");
ESP_LOGI("H2E", "- After group set: sta1.group=%d sta2.group=%d", sae1.group, sae2.group);
TEST_ASSERT_MESSAGE(sae1.h2e == 0 && sae2.h2e == 0, "H2E should be disabled by default");
sae.h2e = 1;
ESP_LOGI("H2E", "- After H2E enable: h2e=%d", sae.h2e);
TEST_ASSERT_MESSAGE(sae.h2e == 1, "Failed to enable H2E");
sae1.h2e = 1;
sae2.h2e = 1;
ESP_LOGI("H2E", "- After H2E enable: sta1.h2e=%d sta2.h2e=%d", sae1.h2e, sae2.h2e);
TEST_ASSERT_MESSAGE(sae1.h2e == 1 && sae2.h2e == 1, "Failed to enable H2E");
/* Step 2: Test password identifier validation */
ESP_LOGI("H2E", "\nStep 2: Testing password identifier validation");
/* Step 2: Derive PT and prepare commits for both peers */
ESP_LOGI("H2E", "\nStep 2: Deriving PT and preparing commits");
ESP_LOGI("H2E", "- Addr1: %02x:%02x:%02x:%02x:%02x:%02x",
addr1[0], addr1[1], addr1[2], addr1[3], addr1[4], addr1[5]);
ESP_LOGI("H2E", "- Addr2: %02x:%02x:%02x:%02x:%02x:%02x",
addr2[0], addr2[1], addr2[2], addr2[3], addr2[4], addr2[5]);
struct sae_pt *pt = sae_derive_pt(NULL, (const u8 *)ssid, ssid_len,
(const u8 *)password, strlen(password), NULL);
pt = sae_derive_pt(NULL, (const u8 *)ssid, ssid_len,
(const u8 *)password, strlen(password), NULL);
TEST_ASSERT_MESSAGE(pt != NULL, "Failed to derive PT");
TEST_ASSERT_MESSAGE(sae_prepare_commit_pt(&sae, pt, addr1, addr2, NULL, NULL) == 0,
"Failed to prepare SAE commit with password");
sae.state = SAE_NOTHING;
ESP_LOGI("H2E", "- After commit prep: h2e=%d, tmp=%p", sae.h2e, (void*)sae.tmp);
TEST_ASSERT_MESSAGE(sae.h2e == 1, "H2E state not maintained after commit preparation");
TEST_ASSERT_MESSAGE(sae.tmp != NULL, "Temporary data not allocated");
start_us = esp_timer_get_time();
TEST_ASSERT_MESSAGE(sae_prepare_commit_pt(&sae1, pt, addr1, addr2, NULL, NULL) == 0,
"Failed to prepare SAE commit for STA1");
prepare1_us = esp_timer_get_time() - start_us;
TEST_ASSERT_MESSAGE(sae1.h2e == 1 && sae1.tmp != NULL,
"STA1 H2E state not maintained after commit preparation");
/* Step 3: Test commit message validation */
ESP_LOGI("H2E", "\nStep 3: Testing commit message validation");
buf = wpabuf_alloc(1000);
ESP_LOGI("H2E", "- Allocated buffer size: 1000 bytes");
TEST_ASSERT_MESSAGE(buf != NULL, "Failed to allocate commit message buffer");
start_us = esp_timer_get_time();
TEST_ASSERT_MESSAGE(sae_prepare_commit_pt(&sae2, pt, addr2, addr1, NULL, NULL) == 0,
"Failed to prepare SAE commit for STA2");
prepare2_us = esp_timer_get_time() - start_us;
TEST_ASSERT_MESSAGE(sae2.h2e == 1 && sae2.tmp != NULL,
"STA2 H2E state not maintained after commit preparation");
TEST_ASSERT_MESSAGE(sae_write_commit(&sae, buf, NULL, NULL) == 0,
"Failed to write SAE commit message");
sae.state = SAE_COMMITTED;
ESP_LOGI("H2E", "- Commit message length: %zu bytes", wpabuf_len(buf));
TEST_ASSERT_MESSAGE(wpabuf_len(buf) > 0, "Commit message length is zero");
/* Step 3: Form commit messages and measure timing */
ESP_LOGI("H2E", "\nStep 3: Forming commit messages");
buf1 = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
buf2 = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
TEST_ASSERT_MESSAGE(buf1 != NULL && buf2 != NULL, "Failed to allocate commit message buffers");
ESP_LOGI("H2E", "- Parsing commit message...");
/* Reset SAE context for parsing */
sae_clear_data(&sae);
memset(&sae, 0, sizeof(sae));
start_us = esp_timer_get_time();
TEST_ASSERT_MESSAGE(sae_write_commit(&sae1, buf1, NULL, NULL) == 0,
"Failed to write SAE commit message for STA1");
write1_us = esp_timer_get_time() - start_us;
form1_us = prepare1_us + write1_us;
sae1.state = SAE_COMMITTED;
/* Initialize SAE parameters for parsing */
TEST_ASSERT_MESSAGE(sae_set_group(&sae, IANA_SECP256R1) == 0, "Failed to set SAE group for parsing");
sae.h2e = 1;
sae.state = SAE_COMMITTED;
start_us = esp_timer_get_time();
TEST_ASSERT_MESSAGE(sae_write_commit(&sae2, buf2, NULL, NULL) == 0,
"Failed to write SAE commit message for STA2");
write2_us = esp_timer_get_time() - start_us;
form2_us = prepare2_us + write2_us;
sae2.state = SAE_COMMITTED;
/* Parse the commit message */
TEST_ASSERT_MESSAGE(sae_parse_commit(&sae, wpabuf_head(buf), wpabuf_len(buf),
NULL, NULL, NULL, 1) == 0,
"Failed to parse SAE commit message");
TEST_ASSERT_MESSAGE(sae.peer_commit_scalar != NULL,
"Peer commit scalar not parsed");
TEST_ASSERT_MESSAGE(sae.tmp != NULL &&
(sae.tmp->peer_commit_element_ecc != NULL || sae.tmp->peer_commit_element_ffc != NULL),
"Peer commit element not parsed");
ESP_LOGI("H2E", "- Commit message parsed successfully");
ESP_LOGI("H2E",
"Commit formation timing(us): sta1_prepare=%lld sta1_write=%lld sta1_total=%lld sta2_prepare=%lld sta2_write=%lld sta2_total=%lld",
(long long) prepare1_us, (long long) write1_us, (long long) form1_us,
(long long) prepare2_us, (long long) write2_us, (long long) form2_us);
ESP_LOGI("H2E", "- Commit1 length: %zu bytes", wpabuf_len(buf1));
ESP_LOGI("H2E", "- Commit2 length: %zu bytes", wpabuf_len(buf2));
TEST_ASSERT_MESSAGE(wpabuf_len(buf1) > 0 && wpabuf_len(buf2) > 0,
"Commit message length is zero");
/* Cleanup */
if (buf) {
wpabuf_free(buf);
buf = NULL;
/* Step 4: Parse commits and complete H2E handshake */
ESP_LOGI("H2E", "\nStep 4: Parsing commits and completing handshake");
start_us = esp_timer_get_time();
TEST_ASSERT_MESSAGE(sae_parse_commit(&sae1, wpabuf_head(buf2), wpabuf_len(buf2),
NULL, 0, default_groups, 1) == 0,
"Failed to parse SAE commit message for STA1");
parse1_us = esp_timer_get_time() - start_us;
TEST_ASSERT_MESSAGE(sae1.peer_commit_scalar != NULL &&
sae1.tmp != NULL &&
(sae1.tmp->peer_commit_element_ecc != NULL || sae1.tmp->peer_commit_element_ffc != NULL),
"STA1 peer commit not parsed");
start_us = esp_timer_get_time();
TEST_ASSERT_MESSAGE(sae_parse_commit(&sae2, wpabuf_head(buf1), wpabuf_len(buf1),
NULL, 0, default_groups, 1) == 0,
"Failed to parse SAE commit message for STA2");
parse2_us = esp_timer_get_time() - start_us;
TEST_ASSERT_MESSAGE(sae2.peer_commit_scalar != NULL &&
sae2.tmp != NULL &&
(sae2.tmp->peer_commit_element_ecc != NULL || sae2.tmp->peer_commit_element_ffc != NULL),
"STA2 peer commit not parsed");
ESP_LOGI("H2E",
"Commit parse timing(us): sta1=%lld sta2=%lld avg=%lld",
(long long) parse1_us, (long long) parse2_us,
(long long)((parse1_us + parse2_us) / 2));
start_us = esp_timer_get_time();
TEST_ASSERT_MESSAGE(sae_process_commit(&sae1) == 0, "Failed to process commit for STA1");
process1_us = esp_timer_get_time() - start_us;
start_us = esp_timer_get_time();
TEST_ASSERT_MESSAGE(sae_process_commit(&sae2) == 0, "Failed to process commit for STA2");
process2_us = esp_timer_get_time() - start_us;
ESP_LOGI("H2E",
"Process commit timing(us): sta1=%lld sta2=%lld avg=%lld",
(long long) process1_us, (long long) process2_us,
(long long)((process1_us + process2_us) / 2));
confirm1 = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
confirm2 = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
TEST_ASSERT_MESSAGE(confirm1 != NULL && confirm2 != NULL, "Failed to allocate confirm buffers");
sae_write_confirm(&sae1, confirm1);
sae_write_confirm(&sae2, confirm2);
TEST_ASSERT_MESSAGE(sae_check_confirm(&sae1, wpabuf_head(confirm2), wpabuf_len(confirm2)) == 0,
"Failed to verify confirm for STA1");
TEST_ASSERT_MESSAGE(sae_check_confirm(&sae2, wpabuf_head(confirm1), wpabuf_len(confirm1)) == 0,
"Failed to verify confirm for STA2");
ESP_LOGI("H2E", "- Full H2E handshake completed successfully");
if (confirm1) {
wpabuf_free(confirm1);
}
if (confirm2) {
wpabuf_free(confirm2);
}
if (buf1) {
wpabuf_free(buf1);
}
if (buf2) {
wpabuf_free(buf2);
}
/* Free SAE PT data */
if (pt) {
sae_deinit_pt(pt);
pt = NULL;
}
sae_clear_data(&sae);
sae_clear_data(&sae1);
sae_clear_data(&sae2);
}
#endif /* CONFIG_WPA3_SAE */