ci(wpa_supplicant): Add UT for supplicant crypto

This commit is contained in:
Kapil Gupta
2026-04-26 10:06:40 +05:30
parent 28ef80d57c
commit 57d95ead73
10 changed files with 1021 additions and 28 deletions
+1 -1
View File
@@ -633,7 +633,7 @@ menu "Wi-Fi"
config ESP_WIFI_P256_ACCEL
bool "Enable P-256 crypto acceleration"
depends on ESP_WIFI_MBEDTLS_CRYPTO
default y
default n
help
Enable Espressif-specific P-256 acceleration in the WPA supplicant
crypto layer. This reduces SAE and DPP latency on supported targets
@@ -604,6 +604,12 @@ static void p256_fast_point_from_affine(p256_fast_jac_point *p,
os_memcpy(p->Z, one_mont, sizeof(p->Z));
}
#define P256_WINDOW_BITS 4U
#define P256_WINDOW_ENTRY_COUNT (1U << P256_WINDOW_BITS)
#define P256_WINDOW_PRECOMP_COUNT (P256_WINDOW_ENTRY_COUNT - 1U)
#define P256_WINDOW_BATCH_COUNT (P256_WINDOW_PRECOMP_COUNT - 1U)
#define P256_SCALAR_WINDOW_COUNT ((P256_WORDS * 32U) / P256_WINDOW_BITS)
static void p256_fast_point_double(p256_fast_jac_point *r)
{
u32 z2[P256_WORDS], y2[P256_WORDS], y4[P256_WORDS];
@@ -739,7 +745,7 @@ static int p256_fast_points_batch_to_affine_mont(
const p256_fast_jac_point *points, size_t num,
u32(*xs)[P256_WORDS], u32(*ys)[P256_WORDS])
{
u32 prefix[14][P256_WORDS];
u32 prefix[P256_WINDOW_BATCH_COUNT][P256_WORDS];
u32 prod_std[P256_WORDS], inv_std[P256_WORDS];
u32 running_inv[P256_WORDS], inv_z[P256_WORDS];
u32 tmp[P256_WORDS];
@@ -789,9 +795,9 @@ static int p256_fast_points_batch_to_affine_mont(
}
struct p256_window4_scratch {
p256_fast_jac_point precomp[15];
u32 table_x[16][P256_WORDS];
u32 table_y[16][P256_WORDS];
p256_fast_jac_point precomp[P256_WINDOW_PRECOMP_COUNT];
u32 table_x[P256_WINDOW_ENTRY_COUNT][P256_WORDS];
u32 table_y[P256_WINDOW_ENTRY_COUNT][P256_WORDS];
};
static int crypto_ec_point_mul_p256_window4_core(const mbedtls_ecp_group *grp,
@@ -846,14 +852,15 @@ static int crypto_ec_point_mul_p256_window4_core(const mbedtls_ecp_group *grp,
p256_fast_point_from_affine(&scratch->precomp[0], x_mont, y_mont, one_mont);
os_memcpy(&scratch->precomp[1], &scratch->precomp[0], sizeof(scratch->precomp[1]));
p256_fast_point_double(&scratch->precomp[1]);
for (window = 2; window < 15; window++) {
for (window = 2; window < P256_WINDOW_PRECOMP_COUNT; window++) {
os_memcpy(&scratch->precomp[window], &scratch->precomp[window - 1],
sizeof(scratch->precomp[window]));
p256_fast_point_add_mixed(&scratch->precomp[window], x_mont, y_mont,
one_mont);
}
if (p256_fast_points_batch_to_affine_mont(&scratch->precomp[1], 14,
if (p256_fast_points_batch_to_affine_mont(&scratch->precomp[1],
P256_WINDOW_BATCH_COUNT,
&scratch->table_x[2],
&scratch->table_y[2]) != 0) {
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
@@ -862,14 +869,17 @@ static int crypto_ec_point_mul_p256_window4_core(const mbedtls_ecp_group *grp,
p256_fast_point_set_zero(r);
for (window = 63; window >= 0; window--) {
u32 idx = p256_words_get_window(scalar, (unsigned) window * 4, 4);
for (window = P256_SCALAR_WINDOW_COUNT - 1; window >= 0; window--) {
u32 idx = p256_words_get_window(scalar,
(unsigned) window * P256_WINDOW_BITS,
P256_WINDOW_BITS);
if (started) {
p256_fast_point_double(r);
p256_fast_point_double(r);
p256_fast_point_double(r);
p256_fast_point_double(r);
unsigned int dbl;
for (dbl = 0; dbl < P256_WINDOW_BITS; dbl++) {
p256_fast_point_double(r);
}
}
if (idx == 0U) {
@@ -1001,9 +1011,7 @@ static int crypto_ec_point_mul_fast(const mbedtls_ecp_group *grp,
if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
return ret;
}
#endif
#if ESP_WIFI_P256_SOFT_ACCEL
#elif ESP_WIFI_P256_SOFT_ACCEL
if (crypto_ec_is_p256_group(grp)) {
return crypto_ec_point_mul_p256_jacobian_fast(grp, p, k, res);
}
@@ -1152,7 +1160,6 @@ struct crypto_bignum *crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
(const struct crypto_bignum *) &grp->P,
(struct crypto_bignum *) &temp));
#if CONFIG_ESP_WIFI_P256_ACCEL
if (mbedtls_ecp_group_a_is_minus_3(grp)) {
/*
* For NIST P-curves used in SAE, a == -3. Compute (-3x + b) mod p
@@ -1178,11 +1185,6 @@ struct crypto_bignum *crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
&grp->A));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &grp->P));
}
#else
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&temp2, (const mbedtls_mpi *) x,
&grp->A));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &grp->P));
#endif
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &grp->B));
while (mbedtls_mpi_cmp_mpi(&temp2, &grp->P) >= 0) {
@@ -44,6 +44,42 @@ struct dpp_global {
extern struct dpp_curve_params dpp_curves[];
#ifdef CONFIG_TESTING_OPTIONS
u64 dpp_last_auth_req_parse_us;
u64 dpp_last_auth_resp_form_us;
u64 dpp_last_auth_req_total_us;
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;
dpp_last_auth_req_parse_us = auth->auth_req_parse_us;
dpp_last_auth_resp_form_us = auth->auth_resp_form_us;
dpp_last_auth_req_total_us = auth->auth_req_total_us;
}
#endif
#define TRANSACTION_ID_ATTR_SET_LEN 5
#define CONNECTOR_ATTR_SET_LEN 4
@@ -1707,6 +1743,13 @@ 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;
dpp_last_auth_req_parse_us = 0;
dpp_last_auth_resp_form_us = 0;
dpp_last_auth_req_total_us = 0;
#endif
#ifdef CONFIG_TESTING_OPTIONS
if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) {
@@ -1892,9 +1935,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
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
i_bootstrap = dpp_get_attr(attr_start, attr_len,
DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
&i_bootstrap_len);
@@ -1912,8 +1961,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
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
return auth;
@@ -1926,8 +1981,14 @@ not_compatible:
auth->configurator = 0;
auth->peer_protocol_key = pi;
pi = NULL;
#ifdef CONFIG_TESTING_OPTIONS
parse_done_us = dpp_time_us();
#endif
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
auth->remove_on_tx_status = 1;
return auth;
@@ -317,8 +317,19 @@ struct dpp_authentication {
char *groups_override;
unsigned int ignore_netaccesskey_mismatch:1;
#endif /* CONFIG_TESTING_OPTIONS */
#ifdef CONFIG_TESTING_OPTIONS
u64 auth_req_parse_us;
u64 auth_resp_form_us;
u64 auth_req_total_us;
#endif
};
#ifdef CONFIG_TESTING_OPTIONS
extern u64 dpp_last_auth_req_parse_us;
extern u64 dpp_last_auth_resp_form_us;
extern u64 dpp_last_auth_req_total_us;
#endif
struct dpp_configurator {
struct dl_list list;
unsigned int id;
@@ -7,7 +7,7 @@ idf_component_register(SRCS
"test_sae.c"
"test_wpa_supplicant_main.c"
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES wpa_supplicant mbedtls esp_wifi esp_event unity
PRIV_REQUIRES wpa_supplicant mbedtls esp_wifi esp_event unity esp_psram esp_timer
WHOLE_ARCHIVE)
idf_component_get_property(esp_supplicant_dir wpa_supplicant COMPONENT_DIR)
@@ -23,3 +23,7 @@ target_include_directories(${COMPONENT_LIB} PRIVATE ${esp_supplicant_dir}/src)
add_definitions(-DWIFI_SUPPLICANT_MD5=\"${WIFI_SUPPLICANT_MD5}\")
add_definitions(-DCONFIG_WPA3_SAE)
add_definitions(-DCONFIG_DPP)
if(CONFIG_ESP_WIFI_TESTING_OPTIONS)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_TESTING_OPTIONS)
endif()
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -14,12 +14,211 @@
#include "utils/includes.h"
#include "crypto/crypto.h"
#include "esp_timer.h"
#include "mbedtls/ecdh.h"
#include "mbedtls/ecp.h"
#include "mbedtls/pk.h"
#include "test_utils.h"
#include "test_wpa_supplicant_common.h"
typedef struct crypto_bignum crypto_bignum;
static const uint8_t test_secp256r1_prime[32] = {
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
static const uint8_t test_p256_bignum_vals[][32] = {
{
0x00, 0x00, 0x00, 0x00, 0xde, 0xad, 0xbe, 0xef,
0xca, 0xfe, 0xba, 0xbe, 0x88, 0x99, 0xaa, 0xbb,
0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0
},
{
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x0f, 0xed, 0xcb, 0xa9, 0x87, 0x65, 0x43, 0x21,
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
},
{
0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a,
0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5,
0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0
}
};
static const uint8_t test_p256_scalar_seeds[][32] = {
{
0xff, 0xff, 0xff, 0xff, 0xde, 0xad, 0xbe, 0xef,
0xca, 0xfe, 0xba, 0xbe, 0x88, 0x99, 0xaa, 0xbb,
0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
0x13, 0x57, 0x9b, 0xdf, 0x24, 0x68, 0xac, 0xe0
},
{
0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a,
0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5, 0x5a, 0xa5,
0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0
},
{
0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78,
0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0,
0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f
}
};
static const unsigned int test_p256_point_multipliers[] = { 7, 13 };
static const unsigned int test_small_exponents[] = { 0, 1, 2, 3 };
static int test_mbedtls_rng(void *ctx, unsigned char *buf, size_t len)
{
(void) ctx;
return os_get_random(buf, len) == 0 ? 0 : MBEDTLS_ERR_ECP_RANDOM_FAILED;
}
static void test_load_valid_p256_scalar(const mbedtls_ecp_group *grp,
const uint8_t *seed, size_t seed_len,
mbedtls_mpi *scalar)
{
mbedtls_mpi range;
mbedtls_mpi_init(&range);
TEST_ASSERT_EQUAL(0, mbedtls_mpi_sub_int(&range, &grp->N, 1));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_read_binary(scalar, seed, seed_len));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(scalar, scalar, &range));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_add_int(scalar, scalar, 1));
mbedtls_mpi_free(&range);
}
static void test_make_p256_affine_point(mbedtls_ecp_group *grp,
unsigned int multiplier,
mbedtls_ecp_point *point)
{
mbedtls_mpi k;
mbedtls_mpi_init(&k);
TEST_ASSERT_EQUAL(0, mbedtls_mpi_lset(&k, multiplier));
TEST_ASSERT_EQUAL(0, mbedtls_ecp_mul(grp, point, &k, &grp->G,
test_mbedtls_rng, NULL));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_cmp_int(&point->MBEDTLS_PRIVATE(Z), 1));
mbedtls_mpi_free(&k);
}
static int test_legendre_reference(const mbedtls_mpi *a, const mbedtls_mpi *p)
{
mbedtls_mpi a_mod, exp, res, one, pm1;
int legendre = -2;
mbedtls_mpi_init(&a_mod);
mbedtls_mpi_init(&exp);
mbedtls_mpi_init(&res);
mbedtls_mpi_init(&one);
mbedtls_mpi_init(&pm1);
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(&a_mod, a, p));
if (mbedtls_mpi_cmp_int(&a_mod, 0) == 0) {
legendre = 0;
goto cleanup;
}
TEST_ASSERT_EQUAL(0, mbedtls_mpi_copy(&exp, p));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_sub_int(&exp, &exp, 1));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_shift_r(&exp, 1));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_exp_mod(&res, &a_mod, &exp, p, NULL));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_lset(&one, 1));
if (mbedtls_mpi_cmp_mpi(&res, &one) == 0) {
legendre = 1;
goto cleanup;
}
TEST_ASSERT_EQUAL(0, mbedtls_mpi_copy(&pm1, p));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_sub_int(&pm1, &pm1, 1));
if (mbedtls_mpi_cmp_mpi(&res, &pm1) == 0) {
legendre = -1;
goto cleanup;
}
TEST_FAIL_MESSAGE("Unexpected Legendre reference result");
cleanup:
mbedtls_mpi_free(&a_mod);
mbedtls_mpi_free(&exp);
mbedtls_mpi_free(&res);
mbedtls_mpi_free(&one);
mbedtls_mpi_free(&pm1);
return legendre;
}
static void test_print_crypto_timing(const char *label,
int64_t generic_total_us, size_t generic_ops,
int64_t api_total_us, size_t api_ops)
{
long long generic_avg = generic_ops ? (long long)(generic_total_us / (int64_t) generic_ops) : 0;
long long api_avg = api_ops ? (long long)(api_total_us / (int64_t) api_ops) : 0;
printf("%s timing(us): generic_avg=%lld api_avg=%lld generic_total=%lld api_total=%lld ops=%u\n",
label, generic_avg, api_avg,
(long long) generic_total_us, (long long) api_total_us,
(unsigned int) api_ops);
}
static int test_mbedtls_ecdh(const struct crypto_ec_key *key_own,
const struct crypto_ec_key *key_peer,
u8 *secret, size_t *secret_len)
{
mbedtls_ecdh_context ctx;
mbedtls_pk_context *own = (mbedtls_pk_context *) key_own;
mbedtls_pk_context *peer = (mbedtls_pk_context *) key_peer;
int ret = -1;
mbedtls_ecdh_init(&ctx);
if (mbedtls_ecdh_get_params(&ctx, mbedtls_pk_ec(*own),
MBEDTLS_ECDH_OURS) != 0) {
goto out;
}
if (mbedtls_ecdh_get_params(&ctx, mbedtls_pk_ec(*peer),
MBEDTLS_ECDH_THEIRS) != 0) {
goto out;
}
if (mbedtls_ecdh_calc_secret(&ctx, secret_len, secret, 66,
test_mbedtls_rng, NULL) != 0) {
goto out;
}
ret = 0;
out:
mbedtls_ecdh_free(&ctx);
return ret;
}
static int test_mbedtls_key_gen_p256(mbedtls_pk_context *kctx)
{
mbedtls_pk_init(kctx);
if (mbedtls_pk_setup(kctx,
mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) != 0) {
return -1;
}
if (mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(*kctx),
test_mbedtls_rng, NULL) != 0) {
mbedtls_pk_free(kctx);
return -1;
}
return 0;
}
TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]")
{
set_leak_threshold(300);
@@ -203,6 +402,38 @@ TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]")
}
{ /** BN mul mod on secp256r1 prime */
uint8_t val[32];
uint8_t one[32] = {0};
crypto_bignum *bn1, *bn2, *bn3, *mulmod;
one[0] = 1;
os_memcpy(val, test_secp256r1_prime, sizeof(val));
val[31]--;
mulmod = crypto_bignum_init();
TEST_ASSERT_NOT_NULL(mulmod);
bn1 = crypto_bignum_init_set(val, sizeof(val));
TEST_ASSERT_NOT_NULL(bn1);
bn2 = crypto_bignum_init_set(val, sizeof(val));
TEST_ASSERT_NOT_NULL(bn2);
bn3 = crypto_bignum_init_set(test_secp256r1_prime,
sizeof(test_secp256r1_prime));
TEST_ASSERT_NOT_NULL(bn3);
TEST_ASSERT(crypto_bignum_mulmod(bn1, bn2, bn3, mulmod) == 0);
TEST_ASSERT(crypto_bignum_to_bin(mulmod, val, sizeof(val), 0) == 1);
TEST_ASSERT_EQUAL_UINT8_ARRAY(one, val, 1);
crypto_bignum_deinit(bn1, 1);
crypto_bignum_deinit(bn2, 1);
crypto_bignum_deinit(bn3, 1);
crypto_bignum_deinit(mulmod, 1);
}
{ /** BN exp mod*/
uint8_t buf1[32], buf2[32], buf3[32], buf4[32], buf5[32];
@@ -273,6 +504,84 @@ TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]")
crypto_bignum_deinit(bn2, 1);
}
{ /** BN Legendre symbol test on secp256r1 prime */
uint8_t val[32] = {0};
crypto_bignum *bn_val, *bn_p;
bn_p = crypto_bignum_init_set(test_secp256r1_prime,
sizeof(test_secp256r1_prime));
TEST_ASSERT_NOT_NULL(bn_p);
val[31] = 1;
bn_val = crypto_bignum_init_set(val, sizeof(val));
TEST_ASSERT_NOT_NULL(bn_val);
TEST_ASSERT(crypto_bignum_legendre(bn_val, bn_p) == 1);
crypto_bignum_deinit(bn_val, 1);
os_memset(val, 0, sizeof(val));
val[31] = 3;
bn_val = crypto_bignum_init_set(val, sizeof(val));
TEST_ASSERT_NOT_NULL(bn_val);
TEST_ASSERT(crypto_bignum_legendre(bn_val, bn_p) == -1);
crypto_bignum_deinit(bn_val, 1);
os_memset(val, 0, sizeof(val));
bn_val = crypto_bignum_init_set(val, sizeof(val));
TEST_ASSERT_NOT_NULL(bn_val);
TEST_ASSERT(crypto_bignum_legendre(bn_val, bn_p) == 0);
crypto_bignum_deinit(bn_val, 1);
crypto_bignum_deinit(bn_p, 1);
}
}
TEST_CASE("Test secp256r1 fast bignum paths against mbedtls reference", "[wpa_crypto]")
{
crypto_bignum *bn_p;
int i;
set_leak_threshold(620);
bn_p = crypto_bignum_init_set(test_secp256r1_prime,
sizeof(test_secp256r1_prime));
TEST_ASSERT_NOT_NULL(bn_p);
for (i = 0; i < ARRAY_SIZE(test_p256_bignum_vals); i++) {
crypto_bignum *bn_a = crypto_bignum_init_set(test_p256_bignum_vals[i], sizeof(test_p256_bignum_vals[i]));
crypto_bignum *bn_b = crypto_bignum_init_set(
test_p256_bignum_vals[(i + 1) % ARRAY_SIZE(test_p256_bignum_vals)],
sizeof(test_p256_bignum_vals[0]));
crypto_bignum *bn_mul = crypto_bignum_init();
mbedtls_mpi ref_mul;
int ref_legendre;
TEST_ASSERT_NOT_NULL(bn_a);
TEST_ASSERT_NOT_NULL(bn_b);
TEST_ASSERT_NOT_NULL(bn_mul);
mbedtls_mpi_init(&ref_mul);
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mul_mpi(&ref_mul,
(const mbedtls_mpi *) bn_a,
(const mbedtls_mpi *) bn_b));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(&ref_mul, &ref_mul,
(const mbedtls_mpi *) bn_p));
TEST_ASSERT_EQUAL(0, crypto_bignum_mulmod(bn_a, bn_b, bn_p, bn_mul));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) bn_mul,
&ref_mul));
ref_legendre = test_legendre_reference((const mbedtls_mpi *) bn_a,
(const mbedtls_mpi *) bn_p);
TEST_ASSERT_EQUAL(ref_legendre, crypto_bignum_legendre(bn_a, bn_p));
mbedtls_mpi_free(&ref_mul);
crypto_bignum_deinit(bn_a, 1);
crypto_bignum_deinit(bn_b, 1);
crypto_bignum_deinit(bn_mul, 1);
}
crypto_bignum_deinit(bn_p, 1);
}
/*
@@ -536,3 +845,385 @@ TEST_CASE("Test crypto lib ECC apis", "[wpa_crypto]")
}
}
TEST_CASE("Test secp256r1 point multiply against mbedtls reference", "[wpa_crypto]")
{
struct crypto_ec *e;
struct crypto_ec_point *p = NULL;
struct crypto_ec_point *res = NULL;
mbedtls_ecp_point ref;
int i, j;
set_leak_threshold(620);
e = crypto_ec_init(19);
TEST_ASSERT_NOT_NULL(e);
p = crypto_ec_point_init(e);
TEST_ASSERT_NOT_NULL(p);
res = crypto_ec_point_init(e);
TEST_ASSERT_NOT_NULL(res);
mbedtls_ecp_point_init(&ref);
for (i = 0; i < ARRAY_SIZE(test_p256_point_multipliers); i++) {
test_make_p256_affine_point((mbedtls_ecp_group *) e,
test_p256_point_multipliers[i],
(mbedtls_ecp_point *) p);
for (j = 0; j < ARRAY_SIZE(test_p256_scalar_seeds); j++) {
mbedtls_mpi scalar;
mbedtls_mpi_init(&scalar);
test_load_valid_p256_scalar((const mbedtls_ecp_group *) e,
test_p256_scalar_seeds[j],
sizeof(test_p256_scalar_seeds[j]),
&scalar);
TEST_ASSERT_EQUAL(0, crypto_ec_point_mul(e, p,
(struct crypto_bignum *) &scalar,
res));
TEST_ASSERT_EQUAL(0, mbedtls_ecp_mul((mbedtls_ecp_group *) e,
&ref, &scalar,
(const mbedtls_ecp_point *) p,
test_mbedtls_rng, NULL));
TEST_ASSERT_EQUAL(0, crypto_ec_point_cmp(e, res,
(const struct crypto_ec_point *) &ref));
mbedtls_mpi_free(&scalar);
}
}
mbedtls_ecp_point_free(&ref);
crypto_ec_point_deinit(p, 1);
crypto_ec_point_deinit(res, 1);
crypto_ec_deinit(e);
}
TEST_CASE("Measure secp256r1 bignum API timings against mbedtls reference", "[wpa_crypto]")
{
const unsigned int loops = 64;
crypto_bignum *bn_p;
int64_t generic_total_us = 0;
int64_t api_total_us = 0;
size_t ops = 0;
int i, loop;
set_leak_threshold(700);
bn_p = crypto_bignum_init_set(test_secp256r1_prime,
sizeof(test_secp256r1_prime));
TEST_ASSERT_NOT_NULL(bn_p);
for (i = 0; i < ARRAY_SIZE(test_p256_bignum_vals); i++) {
crypto_bignum *bn_a = crypto_bignum_init_set(test_p256_bignum_vals[i],
sizeof(test_p256_bignum_vals[i]));
crypto_bignum *bn_b = crypto_bignum_init_set(
test_p256_bignum_vals[(i + 1) % ARRAY_SIZE(test_p256_bignum_vals)],
sizeof(test_p256_bignum_vals[0]));
crypto_bignum *bn_mul = crypto_bignum_init();
mbedtls_mpi ref_mul;
int ref_legendre;
TEST_ASSERT_NOT_NULL(bn_a);
TEST_ASSERT_NOT_NULL(bn_b);
TEST_ASSERT_NOT_NULL(bn_mul);
mbedtls_mpi_init(&ref_mul);
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mul_mpi(&ref_mul,
(const mbedtls_mpi *) bn_a,
(const mbedtls_mpi *) bn_b));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(&ref_mul, &ref_mul,
(const mbedtls_mpi *) bn_p));
TEST_ASSERT_EQUAL(0, crypto_bignum_mulmod(bn_a, bn_b, bn_p, bn_mul));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) bn_mul,
&ref_mul));
ref_legendre = test_legendre_reference((const mbedtls_mpi *) bn_a,
(const mbedtls_mpi *) bn_p);
TEST_ASSERT_EQUAL(ref_legendre, crypto_bignum_legendre(bn_a, bn_p));
for (loop = 0; loop < loops; loop++) {
int64_t start_us = esp_timer_get_time();
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mul_mpi(&ref_mul,
(const mbedtls_mpi *) bn_a,
(const mbedtls_mpi *) bn_b));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_mod_mpi(&ref_mul, &ref_mul,
(const mbedtls_mpi *) bn_p));
generic_total_us += esp_timer_get_time() - start_us;
}
for (loop = 0; loop < loops; loop++) {
int64_t start_us = esp_timer_get_time();
TEST_ASSERT_EQUAL(0, crypto_bignum_mulmod(bn_a, bn_b, bn_p, bn_mul));
api_total_us += esp_timer_get_time() - start_us;
}
ops += loops;
mbedtls_mpi_free(&ref_mul);
crypto_bignum_deinit(bn_a, 1);
crypto_bignum_deinit(bn_b, 1);
crypto_bignum_deinit(bn_mul, 1);
}
test_print_crypto_timing("secp256r1 mulmod", generic_total_us, ops,
api_total_us, ops);
generic_total_us = 0;
api_total_us = 0;
ops = 0;
for (i = 0; i < ARRAY_SIZE(test_small_exponents); i++) {
crypto_bignum *bn_exp = crypto_bignum_init_uint(test_small_exponents[i]);
char label[48];
TEST_ASSERT_NOT_NULL(bn_exp);
generic_total_us = 0;
api_total_us = 0;
ops = 0;
for (loop = 0; loop < ARRAY_SIZE(test_p256_bignum_vals); loop++) {
crypto_bignum *bn_a = crypto_bignum_init_set(test_p256_bignum_vals[loop],
sizeof(test_p256_bignum_vals[loop]));
crypto_bignum *bn_res = crypto_bignum_init();
mbedtls_mpi ref_res;
int iter;
TEST_ASSERT_NOT_NULL(bn_a);
TEST_ASSERT_NOT_NULL(bn_res);
mbedtls_mpi_init(&ref_res);
TEST_ASSERT_EQUAL(0, mbedtls_mpi_exp_mod(&ref_res,
(const mbedtls_mpi *) bn_a,
(const mbedtls_mpi *) bn_exp,
(const mbedtls_mpi *) bn_p,
NULL));
TEST_ASSERT_EQUAL(0, crypto_bignum_exptmod(bn_a, bn_exp, bn_p,
bn_res));
TEST_ASSERT_EQUAL(0, mbedtls_mpi_cmp_mpi((const mbedtls_mpi *) bn_res,
&ref_res));
for (iter = 0; iter < loops; iter++) {
int64_t start_us = esp_timer_get_time();
TEST_ASSERT_EQUAL(0, mbedtls_mpi_exp_mod(&ref_res,
(const mbedtls_mpi *) bn_a,
(const mbedtls_mpi *) bn_exp,
(const mbedtls_mpi *) bn_p,
NULL));
generic_total_us += esp_timer_get_time() - start_us;
}
for (iter = 0; iter < loops; iter++) {
int64_t start_us = esp_timer_get_time();
TEST_ASSERT_EQUAL(0, crypto_bignum_exptmod(bn_a, bn_exp, bn_p,
bn_res));
api_total_us += esp_timer_get_time() - start_us;
}
ops += loops;
mbedtls_mpi_free(&ref_res);
crypto_bignum_deinit(bn_a, 1);
crypto_bignum_deinit(bn_res, 1);
}
snprintf(label, sizeof(label), "secp256r1 exptmod e=%u",
test_small_exponents[i]);
test_print_crypto_timing(label, generic_total_us, ops,
api_total_us, ops);
crypto_bignum_deinit(bn_exp, 1);
}
generic_total_us = 0;
api_total_us = 0;
ops = 0;
for (i = 0; i < ARRAY_SIZE(test_p256_bignum_vals); i++) {
crypto_bignum *bn_a = crypto_bignum_init_set(test_p256_bignum_vals[i],
sizeof(test_p256_bignum_vals[i]));
TEST_ASSERT_NOT_NULL(bn_a);
TEST_ASSERT_EQUAL(test_legendre_reference((const mbedtls_mpi *) bn_a,
(const mbedtls_mpi *) bn_p),
crypto_bignum_legendre(bn_a, bn_p));
for (loop = 0; loop < loops; loop++) {
int64_t start_us = esp_timer_get_time();
(void) test_legendre_reference((const mbedtls_mpi *) bn_a,
(const mbedtls_mpi *) bn_p);
generic_total_us += esp_timer_get_time() - start_us;
}
for (loop = 0; loop < loops; loop++) {
int64_t start_us = esp_timer_get_time();
(void) crypto_bignum_legendre(bn_a, bn_p);
api_total_us += esp_timer_get_time() - start_us;
}
ops += loops;
crypto_bignum_deinit(bn_a, 1);
}
test_print_crypto_timing("secp256r1 legendre", generic_total_us, ops,
api_total_us, ops);
crypto_bignum_deinit(bn_p, 1);
}
TEST_CASE("Measure secp256r1 EC API timings against mbedtls reference", "[wpa_crypto]")
{
const unsigned int point_mul_loops = 4;
const unsigned int key_gen_loops = 4;
const unsigned int ecdh_loops = 4;
struct crypto_ec *e;
struct crypto_ec_point *p = NULL;
struct crypto_ec_point *res = NULL;
mbedtls_ecp_point ref;
int64_t generic_total_us = 0;
int64_t api_total_us = 0;
size_t ops = 0;
int i, j, loop;
set_leak_threshold(900);
e = crypto_ec_init(19);
TEST_ASSERT_NOT_NULL(e);
p = crypto_ec_point_init(e);
TEST_ASSERT_NOT_NULL(p);
res = crypto_ec_point_init(e);
TEST_ASSERT_NOT_NULL(res);
mbedtls_ecp_point_init(&ref);
for (i = 0; i < ARRAY_SIZE(test_p256_point_multipliers); i++) {
test_make_p256_affine_point((mbedtls_ecp_group *) e,
test_p256_point_multipliers[i],
(mbedtls_ecp_point *) p);
for (j = 0; j < ARRAY_SIZE(test_p256_scalar_seeds); j++) {
mbedtls_mpi scalar;
mbedtls_mpi_init(&scalar);
test_load_valid_p256_scalar((const mbedtls_ecp_group *) e,
test_p256_scalar_seeds[j],
sizeof(test_p256_scalar_seeds[j]),
&scalar);
TEST_ASSERT_EQUAL(0, crypto_ec_point_mul(e, p,
(struct crypto_bignum *) &scalar,
res));
TEST_ASSERT_EQUAL(0, mbedtls_ecp_mul((mbedtls_ecp_group *) e,
&ref, &scalar,
(const mbedtls_ecp_point *) p,
test_mbedtls_rng, NULL));
TEST_ASSERT_EQUAL(0, crypto_ec_point_cmp(e, res,
(const struct crypto_ec_point *) &ref));
for (loop = 0; loop < point_mul_loops; loop++) {
int64_t start_us = esp_timer_get_time();
TEST_ASSERT_EQUAL(0, mbedtls_ecp_mul((mbedtls_ecp_group *) e,
&ref, &scalar,
(const mbedtls_ecp_point *) p,
test_mbedtls_rng, NULL));
generic_total_us += esp_timer_get_time() - start_us;
}
for (loop = 0; loop < point_mul_loops; loop++) {
int64_t start_us = esp_timer_get_time();
TEST_ASSERT_EQUAL(0, crypto_ec_point_mul(e, p,
(struct crypto_bignum *) &scalar,
res));
api_total_us += esp_timer_get_time() - start_us;
}
ops += point_mul_loops;
mbedtls_mpi_free(&scalar);
}
}
test_print_crypto_timing("secp256r1 point_mul", generic_total_us, ops,
api_total_us, ops);
generic_total_us = 0;
api_total_us = 0;
for (loop = 0; loop < key_gen_loops; loop++) {
mbedtls_pk_context kctx;
int64_t start_us = esp_timer_get_time();
TEST_ASSERT_EQUAL(0, test_mbedtls_key_gen_p256(&kctx));
generic_total_us += esp_timer_get_time() - start_us;
mbedtls_pk_free(&kctx);
}
for (loop = 0; loop < key_gen_loops; loop++) {
struct crypto_ec_key *key;
int64_t start_us = esp_timer_get_time();
key = crypto_ec_key_gen(19);
TEST_ASSERT_NOT_NULL(key);
api_total_us += esp_timer_get_time() - start_us;
crypto_ec_key_deinit(key);
}
test_print_crypto_timing("secp256r1 key_gen", generic_total_us, key_gen_loops,
api_total_us, key_gen_loops);
{
struct crypto_ec_key *key_own = crypto_ec_key_gen(19);
struct crypto_ec_key *key_peer = crypto_ec_key_gen(19);
u8 secret_generic[66];
u8 secret_api[66];
size_t secret_generic_len = 0;
size_t secret_api_len = 0;
TEST_ASSERT_NOT_NULL(key_own);
TEST_ASSERT_NOT_NULL(key_peer);
TEST_ASSERT_EQUAL(0, test_mbedtls_ecdh(key_own, key_peer,
secret_generic,
&secret_generic_len));
TEST_ASSERT_EQUAL(0, crypto_ecdh(key_own, key_peer,
secret_api, &secret_api_len));
TEST_ASSERT_EQUAL(secret_generic_len, secret_api_len);
TEST_ASSERT_EQUAL_MEMORY(secret_generic, secret_api, secret_api_len);
generic_total_us = 0;
api_total_us = 0;
for (loop = 0; loop < ecdh_loops; loop++) {
int64_t start_us = esp_timer_get_time();
size_t secret_len = 0;
TEST_ASSERT_EQUAL(0, test_mbedtls_ecdh(key_own, key_peer,
secret_generic,
&secret_len));
generic_total_us += esp_timer_get_time() - start_us;
}
for (loop = 0; loop < ecdh_loops; loop++) {
int64_t start_us = esp_timer_get_time();
size_t secret_len = 0;
TEST_ASSERT_EQUAL(0, crypto_ecdh(key_own, key_peer,
secret_api, &secret_len));
api_total_us += esp_timer_get_time() - start_us;
}
test_print_crypto_timing("secp256r1 ecdh", generic_total_us, ecdh_loops,
api_total_us, ecdh_loops);
crypto_ec_key_deinit(key_own);
crypto_ec_key_deinit(key_peer);
}
mbedtls_ecp_point_free(&ref);
crypto_ec_point_deinit(p, 1);
crypto_ec_point_deinit(res, 1);
crypto_ec_deinit(e);
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,6 +9,7 @@
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <inttypes.h>
#include "unity.h"
#include <string.h>
#include "utils/common.h"
@@ -18,8 +19,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 +41,46 @@ 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_MBEDTLS_HARDWARE_ECC
return 200000;
#else
return 425000;
#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)
{
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(130);
set_leak_threshold(dpp_test_leak_threshold());
/* Global variables */
char command[1200] = {0};
const u8 *frame;
@@ -66,6 +112,10 @@ TEST_CASE("Test vectors DPP responder p256", "[wpa_dpp]")
sprintf(command, "type=qrcode key=%s", key);
id = dpp_bootstrap_gen(dpp, command);
uri = dpp_bootstrap_get_uri(dpp, id);
if (uri == NULL) {
ESP_LOGE("DPP Test", "Failed to get URI from bootstrap id");
TEST_ASSERT(0);
}
printf("uri is =%s\n", uri);
printf("is be =%s\n", bootstrap_info);
TEST_ASSERT((strcmp(uri, bootstrap_info) == 0));
@@ -129,6 +179,9 @@ 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);
/* auth response u8 */
hex_len = os_strlen(auth_resp);
@@ -172,7 +225,118 @@ 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();
u64 total_us = 0;
const char *failure = NULL;
set_leak_threshold(dpp_test_leak_threshold());
os_memset(&dpp_conf, 0, sizeof(dpp_conf));
dpp = dpp_global_init(&dpp_conf);
if (!dpp) {
TEST_FAIL_MESSAGE("Failed to initialize DPP global context");
}
responder_id = dpp_bootstrap_gen(dpp, "type=qrcode curve=P-256");
if (responder_id <= 0) {
failure = "Failed to generate responder bootstrap";
goto cleanup;
}
initiator_id = dpp_bootstrap_gen(dpp, "type=qrcode curve=P-256");
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);
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);
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;
responder_auth = dpp_auth_req_rx(NULL, DPP_CAPAB_ENROLLEE, 0,
NULL, responder_bi, 2412,
frame, frame + DPP_HDR_LEN,
len - DPP_HDR_LEN);
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=%" PRIu32,
(unsigned long long) total_us,
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);
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;
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
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -20,9 +20,41 @@
#include "utils/wpabuf.h"
#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
return 400000;
#elif CONFIG_IDF_TARGET_ESP32S3
return 300000;
#elif CONFIG_IDF_TARGET_ESP32S2
return 380000;
#elif CONFIG_IDF_TARGET_ESP32C3
return 340000;
#elif CONFIG_IDF_TARGET_ESP32C5
return 130000;
#elif CONFIG_IDF_TARGET_ESP32C6
return 180000;
#elif CONFIG_IDF_TARGET_ESP32C61
return 200000;
#elif CONFIG_IDF_TARGET_ESP32C2
return 230000;
#else
return 230000;
#endif
}
static struct wpabuf *wpabuf_alloc2(size_t len)
{
struct wpabuf *buf = (struct wpabuf *)os_zalloc(sizeof(struct wpabuf) + len);
@@ -233,26 +265,52 @@ TEST_CASE("Test SAE functionality with ECC group", "[wpa3_sae]")
u8 pwd[] = "ESP32-WPA3";
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));
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() - total_start_us;
ESP_LOGI("SAE Test",
"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");
}
ESP_LOGI("SAE Test", "=========== Complete ============");
@@ -32,7 +32,7 @@ static void check_leak(size_t before_free, size_t after_free, const char *type)
{
ssize_t delta = after_free - before_free;
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d, threshold %d)\n", type, before_free, after_free, delta, leak_threshold);
TEST_ASSERT_MESSAGE(delta > leak_threshold, "memory leak");
TEST_ASSERT_MESSAGE(delta >= leak_threshold, "memory leak");
}
#if SOC_SHA_SUPPORT_SHA512
@@ -1,5 +1,7 @@
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=n
CONFIG_ESP_WIFI_TESTING_OPTIONS=y
CONFIG_ESP_WIFI_DEBUG_PRINT=y
CONFIG_ESP_WIFI_DPP_SUPPORT=y
CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y
CONFIG_ESP_WIFI_P256_ACCEL=y