diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index b7e661ec31..552fb423af 100644 --- a/components/hal/ecdsa_hal.c +++ b/components/hal/ecdsa_hal.c @@ -38,6 +38,19 @@ static void configure_ecdsa_periph(ecdsa_hal_config_t *conf) if (conf->mode != ECDSA_MODE_EXPORT_PUBKEY) { ecdsa_ll_set_z_mode(conf->sha_mode); } + +#if SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + ecdsa_ll_set_k_type(conf->sign_type); + + if (conf->sign_type == ECDSA_K_TYPE_DETERMINISITIC) { + ecdsa_ll_set_deterministic_loop(conf->loop_number); + } +#endif +} + +bool ecdsa_hal_get_operation_result(void) +{ + return ecdsa_ll_get_operation_result(); } void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, @@ -112,7 +125,7 @@ int ecdsa_hal_verify_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, co ; } - int res = ecdsa_ll_get_verification_result(); + bool res = ecdsa_hal_get_operation_result(); return (res ? 0 : -1); } @@ -152,3 +165,12 @@ void ecdsa_hal_export_pubkey(ecdsa_hal_config_t *conf, uint8_t *pub_x, uint8_t * } } #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ + +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + +bool ecdsa_hal_det_signature_k_check(void) +{ + return (ecdsa_ll_check_k_value() == 0); +} + +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ diff --git a/components/hal/esp32h2/include/hal/ecdsa_ll.h b/components/hal/esp32h2/include/hal/ecdsa_ll.h index 3e16b9726c..393d5392fc 100644 --- a/components/hal/esp32h2/include/hal/ecdsa_ll.h +++ b/components/hal/esp32h2/include/hal/ecdsa_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -296,7 +296,7 @@ static inline bool ecdsa_ll_sha_is_busy(void) /** * @brief Write the ECDSA parameter * - * @param param Parameter to be writen + * @param param Parameter to be written * @param buf Buffer containing data * @param len Length of buffer */ @@ -366,14 +366,12 @@ static inline void ecdsa_ll_read_param(ecdsa_ll_param_t param, uint8_t *buf, uin } /** - * @brief Get result of ECDSA verification operation + * @brief Check if the ECDSA operation is successful * - * This is only valid for ECDSA verify mode - * - * @return - 1, if signature verification succeeds + * @return - 1, if ECDSA operation succeeds * - 0, otherwise */ -static inline int ecdsa_ll_get_verification_result(void) +static inline int ecdsa_ll_get_operation_result(void) { return REG_GET_BIT(ECDSA_RESULT_REG, ECDSA_OPERATION_RESULT); } diff --git a/components/hal/esp32p4/include/hal/ecdsa_ll.h b/components/hal/esp32p4/include/hal/ecdsa_ll.h index fe4123b9fc..c11bcd761e 100644 --- a/components/hal/esp32p4/include/hal/ecdsa_ll.h +++ b/components/hal/esp32p4/include/hal/ecdsa_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include "hal/assert.h" #include "soc/ecdsa_reg.h" #include "soc/hp_sys_clkrst_struct.h" +#include "soc/soc_caps.h" #include "hal/ecdsa_types.h" #ifdef __cplusplus @@ -216,6 +217,36 @@ static inline void ecdsa_ll_set_z_mode(ecdsa_ll_sha_mode_t mode) } } +/** + * @brief Set the signature generation type of ECDSA operation + * + * @param type Type of the ECDSA signature + */ +static inline void ecdsa_ll_set_k_type(ecdsa_sign_type_t type) +{ + switch (type) { + case ECDSA_K_TYPE_TRNG: + REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_DETERMINISTIC_K); + break; + case ECDSA_K_TYPE_DETERMINISITIC: + REG_SET_BIT(ECDSA_CONF_REG, ECDSA_DETERMINISTIC_K); + break; + default: + HAL_ASSERT(false && "Unsupported K type"); + break; + } +} + +/** + * @brief Set the loop number value that is used for deterministic derivation of K + * + * @param loop_number Loop number for deterministic K + */ +static inline void ecdsa_ll_set_deterministic_loop(uint16_t loop_number) +{ + REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_DETERMINISTIC_LOOP, loop_number); +} + /** * @brief Set the stage of ECDSA operation * @@ -303,7 +334,7 @@ static inline bool ecdsa_ll_sha_is_busy(void) /** * @brief Write the ECDSA parameter * - * @param param Parameter to be writen + * @param param Parameter to be written * @param buf Buffer containing data * @param len Length of buffer */ @@ -373,18 +404,27 @@ static inline void ecdsa_ll_read_param(ecdsa_ll_param_t param, uint8_t *buf, uin } /** - * @brief Get result of ECDSA verification operation + * @brief Check if the ECDSA operation is successful * - * This is only valid for ECDSA verify mode - * - * @return - 1, if signature verification succeeds + * @return - 1, if ECDSA operation succeeds * - 0, otherwise */ -static inline int ecdsa_ll_get_verification_result(void) +static inline int ecdsa_ll_get_operation_result(void) { return REG_GET_BIT(ECDSA_RESULT_REG, ECDSA_OPERATION_RESULT); } +/** + * @brief Check if the k value is greater than the curve order. + * + * @return 0, k value is not greater than the curve order. In this case, the k value is the set k value. + * @return 1, k value is greater than than the curve order. In this case, the k value is the set (k mod n). + */ +static inline int ecdsa_ll_check_k_value(void) +{ + return REG_GET_BIT(ECDSA_RESULT_REG, ECDSA_K_VALUE_WARNING); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/ecdsa_hal.h b/components/hal/include/hal/ecdsa_hal.h index 9798160019..7384883eee 100644 --- a/components/hal/include/hal/ecdsa_hal.h +++ b/components/hal/include/hal/ecdsa_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +30,11 @@ typedef struct { ecdsa_sha_mode_t sha_mode; /* Source of SHA that needs to be signed */ int efuse_key_blk; /* Efuse block to use as ECDSA key (The purpose of the efuse block must be ECDSA_KEY) */ bool use_km_key; /* Use an ECDSA key from the Key Manager peripheral */ + ecdsa_sign_type_t sign_type; /* Type of signature generation */ + uint16_t loop_number; /* Determines the loop number value in deterministic derivation algorithm to derive K. + * When using mbedtls APIs, this member of the config does not need any explicit + * initialisation as it is used and handled internally by the port layer (ECDSA_SIGN_ALT). + */ } ecdsa_hal_config_t; /** @@ -73,6 +78,25 @@ int ecdsa_hal_verify_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, co void ecdsa_hal_export_pubkey(ecdsa_hal_config_t *conf, uint8_t *pub_x, uint8_t *pub_y, uint16_t len); #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ +/** + * @brief Check if the ECDSA operation is successful + * + * @return - true, if the ECDSA operation is successful + * - false, if the ECDSA operation fails + */ +bool ecdsa_hal_get_operation_result(void); + +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE +/** + * @brief Check if the K value derived by the peripheral during deterministic signature generation is valid + * + * @return true, if the derived K value is valid + * @return false, if the derived K value is invalid + */ +bool ecdsa_hal_det_signature_k_check(void); + +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/ecdsa_types.h b/components/hal/include/hal/ecdsa_types.h index 8ef5636b49..c72ae963f7 100644 --- a/components/hal/include/hal/ecdsa_types.h +++ b/components/hal/include/hal/ecdsa_types.h @@ -1,10 +1,12 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once +#include "soc/soc_caps.h" + #ifdef __cplusplus extern "C" { #endif @@ -34,6 +36,16 @@ typedef enum { ECDSA_Z_USER_PROVIDED, } ecdsa_sha_mode_t; +/** + * @brief ECDSA signature type + */ +typedef enum { + ECDSA_K_TYPE_TRNG, +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + ECDSA_K_TYPE_DETERMINISITIC, +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ +} ecdsa_sign_type_t; + #ifdef __cplusplus } #endif diff --git a/components/hal/test_apps/crypto/README.md b/components/hal/test_apps/crypto/README.md index f9ee480507..7d49ecbe77 100644 --- a/components/hal/test_apps/crypto/README.md +++ b/components/hal/test_apps/crypto/README.md @@ -46,6 +46,10 @@ This contains tests for the following features of the crypto peripherals: - ECDSA P256 signature generation - ECDSA P192 signature verification - ECDSA P256 signature verification + - ECDSA P192 export public key + - ECDSA P256 export public key + - ECDSA P192 deterministic signature generation + - ECDSA P256 deterministic signature generation - AES peripheral - Block Mode diff --git a/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c b/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c index ee30352c4b..d0777dc817 100644 --- a/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c +++ b/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c @@ -16,6 +16,8 @@ #include "hal/ecdsa_hal.h" #include "hal/ecdsa_ll.h" #include "hal/ecdsa_types.h" +#include "hal/mpi_ll.h" +#include "soc/soc_caps.h" #include "memory_checks.h" #include "unity_fixture.h" @@ -25,21 +27,32 @@ static void ecdsa_enable_and_reset(void) { - esp_crypto_ecdsa_lock_acquire(); + ECDSA_RCC_ATOMIC() { + ecdsa_ll_enable_bus_clock(true); + ecdsa_ll_reset_register(); + } ECC_RCC_ATOMIC() { ecc_ll_enable_bus_clock(true); ecc_ll_reset_register(); } - ECDSA_RCC_ATOMIC() { - ecdsa_ll_enable_bus_clock(true); - ecdsa_ll_reset_register(); +#ifdef SOC_ECDSA_USES_MPI + MPI_RCC_ATOMIC() { + mpi_ll_enable_bus_clock(true); + mpi_ll_reset_register(); } +#endif } static void ecdsa_disable(void) { +#ifdef SOC_ECDSA_USES_MPI + MPI_RCC_ATOMIC() { + mpi_ll_enable_bus_clock(false); + } +#endif + ECC_RCC_ATOMIC() { ecc_ll_enable_bus_clock(false); } @@ -47,8 +60,6 @@ static void ecdsa_disable(void) ECDSA_RCC_ATOMIC() { ecdsa_ll_enable_bus_clock(false); } - - esp_crypto_ecdsa_lock_release(); } static void ecc_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) @@ -126,16 +137,21 @@ static void test_ecdsa_corrupt_data(bool is_p256, uint8_t* sha, uint8_t* r_le, u } -static void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key) +static 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) { uint8_t sha_le[32] = {0}; uint8_t zeroes[32] = {0}; uint16_t len; +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + uint16_t det_loop_number = 1; +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + ecdsa_hal_config_t conf = { .mode = ECDSA_MODE_SIGN_GEN, .sha_mode = ECDSA_Z_USER_PROVIDED, .use_km_key = use_km_key, + .sign_type = k_type, }; if (is_p256) { @@ -157,19 +173,38 @@ static void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* ecdsa_enable_and_reset(); + bool process_again = false; + do { +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + if (k_type == ECDSA_K_TYPE_DETERMINISITIC) { + conf.loop_number = det_loop_number++; + } +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + ecdsa_hal_gen_signature(&conf, sha_le, r_le, s_le, len); - } while(!memcmp(r_le, zeroes, len) || !memcmp(s_le, zeroes, len)); + + process_again = !ecdsa_hal_get_operation_result() + || !memcmp(r_le, zeroes, len) + || !memcmp(s_le, zeroes, len); + +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + if (k_type == ECDSA_K_TYPE_DETERMINISITIC) { + process_again |= !ecdsa_hal_det_signature_k_check(); + } +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + + } while(process_again); ecdsa_disable(); } -static void test_ecdsa_sign_and_verify(bool is_p256, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key) +static 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) { uint8_t r_le[32] = {0}; uint8_t s_le[32] = {0}; - test_ecdsa_sign(is_p256, sha, r_le, s_le, use_km_key); + test_ecdsa_sign(is_p256, sha, r_le, s_le, use_km_key, k_type); TEST_ASSERT_EQUAL(0, test_ecdsa_verify(is_p256, sha, r_le, s_le, pub_x, pub_y)); } @@ -178,6 +213,7 @@ static void test_ecdsa_export_pubkey(bool is_p256, bool use_km_key) { uint8_t pub_x[32] = {0}; uint8_t pub_y[32] = {0}; + uint8_t zeroes[32] = {0}; uint16_t len; ecdsa_hal_config_t conf = { @@ -200,7 +236,17 @@ static void test_ecdsa_export_pubkey(bool is_p256, bool use_km_key) } ecdsa_enable_and_reset(); - ecdsa_hal_export_pubkey(&conf, pub_x, pub_y, len); + + bool process_again = false; + + do { + ecdsa_hal_export_pubkey(&conf, pub_x, pub_y, len); + + process_again = !ecdsa_hal_get_operation_result() + || !memcmp(pub_x, zeroes, len) + || !memcmp(pub_y, zeroes, len); + + } while (process_again); if (is_p256) { TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa256_pub_x, pub_x, len); @@ -234,36 +280,43 @@ TEST(ecdsa, ecdsa_SECP192R1_signature_verification) TEST_ASSERT_EQUAL(0, test_ecdsa_verify(0, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y)); } - TEST(ecdsa, ecdsa_SECP192R1_sign_and_verify) { - test_ecdsa_sign_and_verify(0, sha, ecdsa192_pub_x, ecdsa192_pub_y, 0); + test_ecdsa_sign_and_verify(0, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_TRNG); } - TEST(ecdsa, ecdsa_SECP192R1_corrupt_signature) { test_ecdsa_corrupt_data(0, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y); } - TEST(ecdsa, ecdsa_SECP256R1_signature_verification) { TEST_ASSERT_EQUAL(0, test_ecdsa_verify(1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y)); } - TEST(ecdsa, ecdsa_SECP256R1_sign_and_verify) { - test_ecdsa_sign_and_verify(1, sha, ecdsa256_pub_x, ecdsa256_pub_y, 0); + test_ecdsa_sign_and_verify(1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_TRNG); } - TEST(ecdsa, ecdsa_SECP256R1_corrupt_signature) { test_ecdsa_corrupt_data(1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y); } +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE +TEST(ecdsa, ecdsa_SECP192R1_det_sign_and_verify) +{ + test_ecdsa_sign_and_verify(0, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC); +} + +TEST(ecdsa, ecdsa_SECP256R1_det_sign_and_verify) +{ + test_ecdsa_sign_and_verify(1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC); +} +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY TEST(ecdsa, ecdsa_SECP192R1_export_pubkey) { @@ -284,6 +337,10 @@ TEST_GROUP_RUNNER(ecdsa) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_signature_verification) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_sign_and_verify) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_corrupt_signature) +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_det_sign_and_verify) + RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_det_sign_and_verify) +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_export_pubkey) RUN_TEST_CASE(ecdsa, ecdsa_SECP256R1_export_pubkey) diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index e92ac5d0a4..86d49803fd 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -153,7 +153,7 @@ endif() # Add port files to mbedtls targets target_sources(mbedtls PRIVATE ${mbedtls_target_sources}) -# Choose perihperal type +# Choose peripheral type if(CONFIG_SOC_SHA_SUPPORTED) if(CONFIG_SOC_SHA_SUPPORT_DMA) @@ -266,6 +266,12 @@ if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_restartable") target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature") target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_write_signature_restartable") + + if(CONFIG_SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_det_ext") + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=mbedtls_ecdsa_sign_det_restartable") + endif() + endif() if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c index 8cce2663f7..8b1d182178 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -7,6 +7,7 @@ #include "hal/ecc_ll.h" #include "hal/ecdsa_ll.h" #include "hal/ecdsa_hal.h" +#include "hal/mpi_ll.h" #include "esp_crypto_lock.h" #include "esp_efuse.h" #include "esp_private/esp_crypto_lock_internal.h" @@ -15,6 +16,7 @@ #include "mbedtls/asn1write.h" #include "mbedtls/platform_util.h" #include "ecdsa/ecdsa_alt.h" +#include "soc/soc_caps.h" #define ECDSA_KEY_MAGIC (short) 0xECD5A #define ECDSA_SHA_LEN 32 @@ -26,26 +28,42 @@ static void esp_ecdsa_acquire_hardware(void) { esp_crypto_ecdsa_lock_acquire(); + ECDSA_RCC_ATOMIC() { + ecdsa_ll_enable_bus_clock(true); + ecdsa_ll_reset_register(); + } + ECC_RCC_ATOMIC() { ecc_ll_enable_bus_clock(true); ecc_ll_reset_register(); } - ECDSA_RCC_ATOMIC() { - ecdsa_ll_enable_bus_clock(true); - ecdsa_ll_reset_register(); +#ifdef SOC_ECDSA_USES_MPI + /* We need to reset the MPI peripheral because ECDSA peripheral + * of some targets use the MPI peripheral as well. + */ + MPI_RCC_ATOMIC() { + mpi_ll_enable_bus_clock(true); + mpi_ll_reset_register(); } +#endif /* SOC_ECDSA_USES_MPI */ } static void esp_ecdsa_release_hardware(void) { + ECDSA_RCC_ATOMIC() { + ecdsa_ll_enable_bus_clock(false); + } + ECC_RCC_ATOMIC() { ecc_ll_enable_bus_clock(false); } - ECDSA_RCC_ATOMIC() { - ecdsa_ll_enable_bus_clock(false); +#ifdef SOC_ECDSA_USES_MPI + MPI_RCC_ATOMIC() { + mpi_ll_enable_bus_clock(false); } +#endif /* SOC_ECDSA_USES_MPI */ esp_crypto_ecdsa_lock_release(); } @@ -101,9 +119,16 @@ int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk) esp_ecdsa_acquire_hardware(); + bool process_again = false; + do { ecdsa_hal_export_pubkey(&conf, qx_le, qy_le, len); - } while (!memcmp(qx_le, zeroes, len) || !memcmp(qy_le, zeroes, len)); + + process_again = !ecdsa_hal_get_operation_result() + || !memcmp(qx_le, zeroes, len) + || !memcmp(qy_le, zeroes, len); + + } while (process_again); esp_ecdsa_release_hardware(); @@ -213,7 +238,8 @@ int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *c static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s, - const mbedtls_mpi *d, const unsigned char* msg, size_t msg_len) + const mbedtls_mpi *d, const unsigned char* msg, size_t msg_len, + ecdsa_sign_type_t k_type) { ecdsa_curve_t curve; esp_efuse_block_t blk; @@ -250,6 +276,12 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s esp_ecdsa_acquire_hardware(); + bool process_again = false; + +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + uint16_t deterministic_loop_number = 1; +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + do { ecdsa_hal_config_t conf = { .mode = ECDSA_MODE_SIGN_GEN, @@ -257,10 +289,25 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s .sha_mode = ECDSA_Z_USER_PROVIDED, .efuse_key_blk = d->MBEDTLS_PRIVATE(n), .use_km_key = 0, //TODO: IDF-7992 + .sign_type = k_type, +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + .loop_number = deterministic_loop_number++, +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ }; ecdsa_hal_gen_signature(&conf, sha_le, r_le, s_le, len); - } while (!memcmp(r_le, zeroes, len) || !memcmp(s_le, zeroes, len)); + + process_again = !ecdsa_hal_get_operation_result() + || !memcmp(r_le, zeroes, len) + || !memcmp(s_le, zeroes, len); + +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + if (k_type == ECDSA_K_TYPE_DETERMINISITIC) { + process_again |= !ecdsa_hal_det_signature_k_check(); + } +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + + } while (process_again); esp_ecdsa_release_hardware(); @@ -290,7 +337,7 @@ int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mp */ if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { // Use hardware ECDSA peripheral - return esp_ecdsa_sign(grp, r, s, d, buf, blen); + return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); } else { return __real_mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, f_rng, p_rng); } @@ -319,12 +366,83 @@ int __wrap_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r */ if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { // Use hardware ECDSA peripheral - return esp_ecdsa_sign(grp, r, s, d, buf, blen); + return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); } else { return __real_mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen, f_rng, p_rng, f_rng_blind, p_rng_blind, rs_ctx); } } +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + +extern int __real_mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind); + +int __wrap_mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind); + +int __wrap_mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind) +{ + /* + * Check `d` whether it contains the hardware key + */ + if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { + // Use hardware ECDSA peripheral + return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_DETERMINISITIC); + } else { + return __real_mbedtls_ecdsa_sign_det_ext(grp, r, s, d, buf, blen, md_alg, f_rng_blind, p_rng_blind); + } +} + +extern int __real_mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +int __wrap_mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx); + +int __wrap_mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx) +{ + /* + * Check `d` whether it contains the hardware key + */ + if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { + // Use hardware ECDSA peripheral + return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_DETERMINISITIC); + } else { + return __real_mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg, f_rng_blind, p_rng_blind, NULL); + } +} + +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + int __real_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, @@ -395,8 +513,11 @@ int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, */ if (ctx->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { // Use hardware ECDSA peripheral - - MBEDTLS_MPI_CHK(esp_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen)); +#if defined(SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE) && defined(CONFIG_MBEDTLS_ECDSA_DETERMINISTIC) + MBEDTLS_MPI_CHK(esp_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen, ECDSA_K_TYPE_DETERMINISITIC)); +#else + MBEDTLS_MPI_CHK(esp_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen, ECDSA_K_TYPE_TRNG)); +#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ } MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen)); diff --git a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c index 22340e9482..a74dc251c4 100644 --- a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c +++ b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c @@ -1,6 +1,6 @@ /* mbedTLS Elliptic Curve Digital Signature performance tests * - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -190,7 +190,7 @@ const uint8_t ecdsa192_sign_pub_y[] = { 0x23, 0xae, 0x7e, 0x0f, 0x1f, 0x4d, 0x69, 0xd5 }; -void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *pub_x, const uint8_t *pub_y) +void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *pub_x, const uint8_t *pub_y, bool is_deterministic) { uint8_t r_be[MAX_ECDSA_COMPONENT_LEN] = {0}; uint8_t s_be[MAX_ECDSA_COMPONENT_LEN] = {0}; @@ -212,7 +212,11 @@ void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t esp_ecdsa_privkey_load_mpi(&key_mpi, SECP256R1_EFUSE_BLOCK); } - mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, HASH_LEN, NULL, NULL); + if (is_deterministic) { + mbedtls_ecdsa_sign_det_ext(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, HASH_LEN, 0, NULL, NULL); + } else { + mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, HASH_LEN, NULL, NULL); + } mbedtls_mpi_write_binary(&r, r_be, MAX_ECDSA_COMPONENT_LEN); mbedtls_mpi_write_binary(&s, s_be, MAX_ECDSA_COMPONENT_LEN); @@ -223,18 +227,36 @@ void test_ecdsa_sign(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t } else if (id == MBEDTLS_ECP_DP_SECP256R1) { test_ecdsa_verify(id, sha, r_be, s_be, pub_x, pub_y); } + + mbedtls_mpi_free(&r); + mbedtls_mpi_free(&s); + mbedtls_mpi_free(&key_mpi); } TEST_CASE("mbedtls ECDSA signature generation on SECP192R1", "[mbedtls][efuse_key]") { - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_sign_pub_x, ecdsa192_sign_pub_y); + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_sign_pub_x, ecdsa192_sign_pub_y, false); } TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][efuse_key]") { - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_sign_pub_x, ecdsa256_sign_pub_y); + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_sign_pub_x, ecdsa256_sign_pub_y, false); } +#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + +TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP192R1", "[mbedtls][efuse_key]") +{ + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_sign_pub_x, ecdsa192_sign_pub_y, true); +} + +TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbedtls][efuse_key]") +{ + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_sign_pub_x, ecdsa256_sign_pub_y, true); +} + +#endif + #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY void test_ecdsa_export_pubkey(mbedtls_ecp_group_id id, const uint8_t *pub_x, const uint8_t *pub_y) @@ -269,6 +291,7 @@ void test_ecdsa_export_pubkey(mbedtls_ecp_group_id id, const uint8_t *pub_x, con TEST_ASSERT_EQUAL_HEX8_ARRAY(pub_y, export_pub_y, len); mbedtls_ecdsa_free(keypair); + mbedtls_pk_free(&key_ctx); } TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][efuse_key]") diff --git a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in index a41bfe252d..a55a3e4282 100644 --- a/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h2/include/soc/Kconfig.soc_caps.in @@ -1191,6 +1191,10 @@ config SOC_CRYPTO_DPA_PROTECTION_SUPPORTED bool default y +config SOC_ECDSA_USES_MPI + bool + default y + config SOC_UART_NUM int default 2 diff --git a/components/soc/esp32h2/include/soc/soc_caps.h b/components/soc/esp32h2/include/soc/soc_caps.h index 1aa2285e18..9ec44e29d8 100644 --- a/components/soc/esp32h2/include/soc/soc_caps.h +++ b/components/soc/esp32h2/include/soc/soc_caps.h @@ -468,6 +468,9 @@ /*------------------------ Anti DPA (Security) CAPS --------------------------*/ #define SOC_CRYPTO_DPA_PROTECTION_SUPPORTED 1 +/*------------------------- ECDSA CAPS -------------------------*/ +#define SOC_ECDSA_USES_MPI (1) + /*-------------------------- UART CAPS ---------------------------------------*/ // ESP32-H2 has 2 UARTs #define SOC_UART_NUM (2) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 67fe0d00d8..0721d69751 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1055,6 +1055,14 @@ config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY bool default y +config SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + bool + default y + +config SOC_ECDSA_USES_MPI + bool + default y + config SOC_SDM_GROUPS int default 1 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index de657cc5b6..c94f187ec7 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -435,6 +435,8 @@ /*--------------------------- ECDSA CAPS ---------------------------------------*/ #define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) +#define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1) +#define SOC_ECDSA_USES_MPI (1) /*-------------------------- Sigma Delta Modulator CAPS -----------------*/ #define SOC_SDM_GROUPS 1U diff --git a/docs/en/api-reference/peripherals/ecdsa.rst b/docs/en/api-reference/peripherals/ecdsa.rst index d6e19cf5bc..efb018da1a 100644 --- a/docs/en/api-reference/peripherals/ecdsa.rst +++ b/docs/en/api-reference/peripherals/ecdsa.rst @@ -59,11 +59,21 @@ Following code snippet uses :cpp:func:`esp_efuse_write_key` to set physical key // writing key failed, maybe written already } +.. only:: SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + + Determinisitic Signature Generation + ----------------------------------- + + The ECDSA peripheral of {IDF_TARGET_NAME} also supports generation of deterministic signatures using deterministic derivation of the parameter K as specified in the `RFC 6979 `_ section 3.2. + + +Non-Determinisitic Signature Generation +--------------------------------------- Dependency on TRNG ------------------- +^^^^^^^^^^^^^^^^^^ -ECDSA peripheral relies on the hardware True Random Number Generator (TRNG) for its internal entropy requirement. During ECDSA signature creation, the algorithm requires a random integer to be generated as specified in the `RFC 6090 `_ section 5.3.2. +ECDSA peripheral relies on the hardware True Random Number Generator (TRNG) for its internal entropy requirement for generating non-deterministic signatures. During ECDSA signature creation, the algorithm requires a random integer to be generated as specified in the `RFC 6090 `_ section 5.3.2. Please ensure that hardware :doc:`RNG <../system/random>` is enabled before starting ECDSA computations (primarily signing) in the application.