From 8a934fa932c5db2d11dbff4f2792938cc27fe02f Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Tue, 9 Jun 2026 15:43:45 +0530 Subject: [PATCH] test(mbedtls): Add out-of-bounds test for the ECDSA hardware driver --- .../main/key_manager/test_key_manager.c | 4 +- .../test_apps/main/test_mbedtls_ecdsa.c | 70 ++++++++++++++++--- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/components/hal/test_apps/crypto/main/key_manager/test_key_manager.c b/components/hal/test_apps/crypto/main/key_manager/test_key_manager.c index 948c5931c93..227e4df301a 100644 --- a/components/hal/test_apps/crypto/main/key_manager/test_key_manager.c +++ b/components/hal/test_apps/crypto/main/key_manager/test_key_manager.c @@ -216,7 +216,7 @@ extern void test_ecdsa_export_pubkey_inner(bool is_p256, uint8_t *exported_pub_x #endif extern void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key, ecdsa_sign_type_t k_type); -extern int test_ecdsa_verify(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, uint8_t *pub_x, uint8_t *pub_y); +extern int test_ecdsa_verify(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, uint8_t *pub_x, uint8_t *pub_y, int expected_ret); extern void test_ecdsa_sign_and_verify(bool is_p256, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key, ecdsa_sign_type_t k_type); /* @@ -253,7 +253,7 @@ void key_mgr_test_ecdsa_key(bool is_p256, ecdsa_sign_type_t k_type) ESP_LOG_BUFFER_HEXDUMP("ECDSA key pubx", pub_x, pubkey_len, ESP_LOG_DEBUG); ESP_LOG_BUFFER_HEXDUMP("ECDSA key puby", pub_y, pubkey_len, ESP_LOG_DEBUG); - TEST_ASSERT_EQUAL(0, test_ecdsa_verify(is_p256, sha256_digest, r_le, s_le, pub_x, pub_y)); + TEST_ASSERT_EQUAL(0, test_ecdsa_verify(is_p256, sha256_digest, r_le, s_le, pub_x, pub_y, 0)); } static void key_mgr_test_ecdsa_p256_aes_mode(void) diff --git a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c index 1c4a4e65934..a0a19b565e3 100644 --- a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c +++ b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "hal/efuse_ll.h" #include "esp_efuse.h" @@ -214,8 +216,18 @@ const uint8_t ecdsa384_pub_y_km[] = { }; #endif /* SOC_KEY_MANAGER_SUPPORTED */ +/* Curve order N in big-endian, taken from mbedtls instead of a hard-coded table. */ +static void ecdsa_get_curve_order_be(mbedtls_ecp_group_id id, uint8_t *n_be, size_t len) +{ + mbedtls_ecp_group grp; + mbedtls_ecp_group_init(&grp); + TEST_ASSERT_EQUAL(0, mbedtls_ecp_group_load(&grp, id)); + TEST_ASSERT_EQUAL(0, mbedtls_mpi_write_binary(&grp.N, n_be, len)); + mbedtls_ecp_group_free(&grp); +} + void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *r_comp, const uint8_t *s_comp, - const uint8_t *pub_x, const uint8_t *pub_y) + const uint8_t *pub_x, const uint8_t *pub_y, int expected_ret) { size_t hash_len = HASH_LEN; int64_t elapsed_time; @@ -247,7 +259,8 @@ void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8 #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ ccomp_timer_start(); - TEST_ASSERT_MBEDTLS_OK(mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), hash, hash_len, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s)); + int actual_ret = mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), hash, hash_len, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s); + TEST_ASSERT_EQUAL(expected_ret, actual_ret); elapsed_time = ccomp_timer_stop(); if (id == MBEDTLS_ECP_DP_SECP192R1) { @@ -274,7 +287,7 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP192R1", "[mbe } #endif test_ecdsa_verify(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_r, ecdsa192_s, - ecdsa192_pub_x, ecdsa192_pub_y); + ecdsa192_pub_x, ecdsa192_pub_y, 0); } TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbedtls]") @@ -285,7 +298,7 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbe } #endif test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_r, ecdsa256_s, - ecdsa256_pub_x, ecdsa256_pub_y); + ecdsa256_pub_x, ecdsa256_pub_y, 0); } #ifdef SOC_ECDSA_SUPPORT_CURVE_P384 @@ -297,10 +310,51 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP384R1", "[mbe } #endif test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_r, ecdsa384_s, - ecdsa384_pub_x, ecdsa384_pub_y); + ecdsa384_pub_x, ecdsa384_pub_y, 0); } #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ +TEST_CASE("mbedtls ECDSA signature verification rejects out-of-range r, s on SECP256R1", "[mbedtls]") +{ +#if SOC_ECDSA_SUPPORTED + if (!ecdsa_ll_is_supported()) { + TEST_IGNORE_MESSAGE("ECDSA is not supported"); + } +#endif + static const uint8_t zero32[32] = { 0 }; + uint8_t p256_n_be[32]; + ecdsa_get_curve_order_be(MBEDTLS_ECP_DP_SECP256R1, p256_n_be, sizeof(p256_n_be)); + + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, zero32, zero32, ecdsa256_pub_x, ecdsa256_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=0, s=0 */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, zero32, p256_n_be, ecdsa256_pub_x, ecdsa256_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=0, s=N */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, p256_n_be, zero32, ecdsa256_pub_x, ecdsa256_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=N, s=0 */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, p256_n_be, p256_n_be, ecdsa256_pub_x, ecdsa256_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=N, s=N */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_r, zero32, ecdsa256_pub_x, ecdsa256_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=valid, s=0 */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_r, p256_n_be, ecdsa256_pub_x, ecdsa256_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=valid, s=N */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, p256_n_be, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=N, s=valid */ +} + +#ifdef SOC_ECDSA_SUPPORT_CURVE_P384 +TEST_CASE("mbedtls ECDSA signature verification rejects out-of-range r, s on SECP384R1", "[mbedtls]") +{ +#if SOC_ECDSA_SUPPORTED + if (!ecdsa_ll_is_supported()) { + TEST_IGNORE_MESSAGE("ECDSA is not supported"); + } +#endif + static const uint8_t zero48[48] = { 0 }; + uint8_t p384_n_be[48]; + ecdsa_get_curve_order_be(MBEDTLS_ECP_DP_SECP384R1, p384_n_be, sizeof(p384_n_be)); + + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, zero48, zero48, ecdsa384_pub_x, ecdsa384_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=0, s=0 */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, zero48, p384_n_be, ecdsa384_pub_x, ecdsa384_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=0, s=N */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, p384_n_be, zero48, ecdsa384_pub_x, ecdsa384_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=N, s=0 */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, p384_n_be, p384_n_be, ecdsa384_pub_x, ecdsa384_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=N, s=N */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_r, zero48, ecdsa384_pub_x, ecdsa384_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=valid, s=0 */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_r, p384_n_be, ecdsa384_pub_x, ecdsa384_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=valid, s=N */ + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, p384_n_be, ecdsa384_s, ecdsa384_pub_x, ecdsa384_pub_y, MBEDTLS_ERR_ECP_VERIFY_FAILED); /* r=N, s=valid */ +} +#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ #endif /* CONFIG_MBEDTLS_HARDWARE_ECC */ #if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN @@ -413,13 +467,13 @@ void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t if (id == MBEDTLS_ECP_DP_SECP192R1) { // Skip the initial zeroes - test_ecdsa_verify(id, sha, &r_be[MAX_HASH_LEN - ECDSA_P192_HASH_COMPONENT_LEN], &s_be[MAX_HASH_LEN - ECDSA_P192_HASH_COMPONENT_LEN], pub_x, pub_y); + test_ecdsa_verify(id, sha, &r_be[MAX_HASH_LEN - ECDSA_P192_HASH_COMPONENT_LEN], &s_be[MAX_HASH_LEN - ECDSA_P192_HASH_COMPONENT_LEN], pub_x, pub_y, 0); } else if (id == MBEDTLS_ECP_DP_SECP256R1) { - test_ecdsa_verify(id, sha, &r_be[MAX_HASH_LEN - ECDSA_P256_HASH_COMPONENT_LEN], &s_be[MAX_HASH_LEN - ECDSA_P256_HASH_COMPONENT_LEN], pub_x, pub_y); + test_ecdsa_verify(id, sha, &r_be[MAX_HASH_LEN - ECDSA_P256_HASH_COMPONENT_LEN], &s_be[MAX_HASH_LEN - ECDSA_P256_HASH_COMPONENT_LEN], pub_x, pub_y, 0); } #if SOC_ECDSA_SUPPORT_CURVE_P384 else if (id == MBEDTLS_ECP_DP_SECP384R1) { - test_ecdsa_verify(id, sha, r_be, s_be, pub_x, pub_y); + test_ecdsa_verify(id, sha, r_be, s_be, pub_x, pub_y, 0); } #endif