mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
fix(esp_wifi): Optimize crypto operations for DPP
This commit is contained in:
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user