diff --git a/components/efuse/esp32h21/esp_efuse_fields.c b/components/efuse/esp32h21/esp_efuse_fields.c index 223fab34e3..104fdb66aa 100644 --- a/components/efuse/esp32h21/esp_efuse_fields.c +++ b/components/efuse/esp32h21/esp_efuse_fields.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include "stdlib.h" #include "esp_types.h" #include "assert.h" +#include "hal/efuse_ll.h" #include "esp_err.h" #include "esp_log.h" #include "soc/efuse_periph.h" @@ -51,3 +52,45 @@ esp_err_t esp_efuse_enable_rom_secure_download_mode(void) } return esp_efuse_write_field_bit(ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD); } + +#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED +bool esp_efuse_is_ecdsa_p192_curve_supported(void) +{ + uint32_t current_curve = efuse_ll_get_ecdsa_curve_mode(); + return (current_curve == ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_BOTH_P192_P256_BIT || current_curve == ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_ONLY_P192_BIT); +} + +esp_err_t esp_efuse_enable_ecdsa_p192_curve_mode(void) +{ + esp_err_t err; + uint8_t current_curve, next_curve; + + err = esp_efuse_read_field_blob(ESP_EFUSE_ECDSA_CURVE_MODE, ¤t_curve, ESP_EFUSE_ECDSA_CURVE_MODE[0]->bit_count); + if (err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to read ECDSA curve mode"); + return err; + } + + // Check if already in desired state + if (current_curve == ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_BOTH_P192_P256_BIT || current_curve == ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_ONLY_P192_BIT) { + ESP_EARLY_LOGD(TAG, "ECDSA P-192 curve mode is already enabled"); + return ESP_OK; + } + + // Check if write is disabled or already locked to P256 + if (esp_efuse_read_field_bit(ESP_EFUSE_WR_DIS_ECDSA_CURVE_MODE) || current_curve == ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_ONLY_P256_BIT_LOCKED) { + ESP_EARLY_LOGE(TAG, "ECDSA curve mode is locked, cannot enable P-192 curve"); + return ESP_FAIL; + } + + // Attempt to write new curve mode + next_curve = ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_BOTH_P192_P256_BIT; + err = esp_efuse_write_field_blob(ESP_EFUSE_ECDSA_CURVE_MODE, &next_curve, ESP_EFUSE_ECDSA_CURVE_MODE[0]->bit_count); + if (err != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to enable ECDSA P-192 curve %d", err); + return err; + } + + return ESP_OK; +} +#endif /* SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED */ diff --git a/components/efuse/esp32h21/include/esp_efuse_chip.h b/components/efuse/esp32h21/include/esp_efuse_chip.h index d1d2add7ea..54f59d1cea 100644 --- a/components/efuse/esp32h21/include/esp_efuse_chip.h +++ b/components/efuse/esp32h21/include/esp_efuse_chip.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -77,6 +77,13 @@ typedef enum { ESP_EFUSE_KEY_PURPOSE_MAX, /**< MAX PURPOSE */ } esp_efuse_purpose_t; +typedef enum { + ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_ONLY_P256_BIT = 0, + ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_ONLY_P192_BIT = 1, + ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_BOTH_P192_P256_BIT = 2, + ESP_EFUSE_ECDSA_CURVE_MODE_ALLOW_ONLY_P256_BIT_LOCKED = 3, +} esp_efuse_ecdsa_curve_mode_t; + #ifdef __cplusplus } #endif diff --git a/components/efuse/include/esp_efuse.h b/components/efuse/include/esp_efuse.h index be3aca8e18..3673f272ac 100644 --- a/components/efuse/include/esp_efuse.h +++ b/components/efuse/include/esp_efuse.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -159,7 +159,7 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt) * * @return * - ESP_OK: The operation was successfully completed, or the bit was already set to value 1. - * - ESP_ERR_INVALID_ARG: Error in the passed arugments, including if the efuse field is not 1 bit wide. + * - ESP_ERR_INVALID_ARG: Error in the passed arguments, including if the efuse field is not 1 bit wide. */ esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[]); @@ -468,7 +468,7 @@ esp_err_t esp_efuse_batch_write_begin(void); * * @return * - ESP_OK: Successful. - * - ESP_ERR_INVALID_STATE: Tha batch mode was not set. + * - ESP_ERR_INVALID_STATE: The batch mode was not set. */ esp_err_t esp_efuse_batch_write_cancel(void); @@ -806,6 +806,29 @@ esp_err_t esp_efuse_check_errors(void); */ esp_err_t esp_efuse_destroy_block(esp_efuse_block_t block); +#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED +/** + * @brief Checks if 192-bit ECDSA curve operations are supported. + * + * This function checks if the current eFuse configuration supports 192-bit ECDSA curve operations. +*/ +bool esp_efuse_is_ecdsa_p192_curve_supported(void); + +/** + * @brief Enables 192-bit ECDSA curve operations by setting the appropriate eFuse value. + * + * This function enables support for 192-bit ECDSA curve operations by configuring the + * ECDSA curve mode eFuse. It checks the current curve mode and attempts to set it to + * allow both P192 and P256 operations if not already set. + * + * @return + * - ESP_OK: Successfully enabled 192-bit ECDSA operations or already enabled + * - ESP_FAIL: Failed to enable operations due to write protection + * - Other error codes: Failed to read/write eFuse + */ +esp_err_t esp_efuse_enable_ecdsa_p192_curve_mode(void); +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_security/Kconfig b/components/esp_security/Kconfig index 7a8c9ff631..50d0caf4ea 100644 --- a/components/esp_security/Kconfig +++ b/components/esp_security/Kconfig @@ -50,4 +50,13 @@ menu "ESP Security Specific" the cases when trusted boot is not enabled and the attacker tries carrying out non-constant time point multiplication operations by changing the default ESP-IDF configurations. Performing constant time operations protect the ECC multiplication operations from timing attacks. + + config ESP_ECDSA_ENABLE_P192_CURVE + bool "Enable ECDSA 192-curve operations" + depends on SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED + default N + help + By default, only the 256-bit curve operations are allowed. If this configuration is enabled, + it will set the eFuse to allow ECDSA operations using both the 192-bit and 256-bit curves. + endmenu diff --git a/components/esp_security/src/init.c b/components/esp_security/src/init.c index ab75144cda..11d01f89d9 100644 --- a/components/esp_security/src/init.c +++ b/components/esp_security/src/init.c @@ -58,6 +58,15 @@ ESP_SYSTEM_INIT_FN(esp_security_init, SECONDARY, BIT(0), 103) } } #endif + +#if CONFIG_ESP_ECDSA_ENABLE_P192_CURVE + esp_err_t err; + err = esp_efuse_enable_ecdsa_p192_curve_mode(); + if (err != ESP_OK) { + return err; + } +#endif + return ESP_OK; } diff --git a/components/hal/esp32h21/include/hal/ecdsa_ll.h b/components/hal/esp32h21/include/hal/ecdsa_ll.h new file mode 100644 index 0000000000..544c217b4c --- /dev/null +++ b/components/hal/esp32h21/include/hal/ecdsa_ll.h @@ -0,0 +1,426 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include +#include +#include "hal/assert.h" +#include "soc/ecdsa_reg.h" +#include "soc/pcr_struct.h" +#include "hal/ecdsa_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Memory blocks of ECDSA parameters + */ +typedef enum { + ECDSA_PARAM_R, + ECDSA_PARAM_S, + ECDSA_PARAM_Z, + ECDSA_PARAM_QAX, + ECDSA_PARAM_QAY +} ecdsa_ll_param_t; + +/** + * @brief Interrupt types in ECDSA + */ +typedef enum { + ECDSA_INT_CALC_DONE, + ECDSA_INT_SHA_RELEASE, +} ecdsa_ll_intr_type_t; + +/** + * @brief Stages of ECDSA operation + */ +typedef enum { + ECDSA_STAGE_START_CALC, + ECDSA_STAGE_LOAD_DONE, + ECDSA_STAGE_GET_DONE +} ecdsa_ll_stage_t; + +/** + * @brief States of ECDSA peripheral + */ +typedef enum { + ECDSA_STATE_IDLE, + ECDSA_STATE_LOAD, + ECDSA_STATE_GET, + ECDSA_STATE_BUSY +} ecdsa_ll_state_t; + +/** + * @brief Types of SHA + */ +typedef enum { + ECDSA_SHA_224, + ECDSA_SHA_256 +} ecdsa_ll_sha_type_t; + +/** + * @brief Operation modes of SHA + */ +typedef enum { + ECDSA_MODE_SHA_START, + ECDSA_MODE_SHA_CONTINUE +} ecdsa_ll_sha_mode_t; + +/** + * @brief Get the state of ECDSA peripheral + * + * @return State of ECDSA + */ +static inline uint32_t ecdsa_ll_get_state(void) +{ + return REG_GET_FIELD(ECDSA_STATE_REG, ECDSA_BUSY); +} + +/** + * @brief Enable the bus clock for ECDSA peripheral module + * + * @param true to enable the module, false to disable the module + */ +static inline void ecdsa_ll_enable_bus_clock(bool enable) +{ + PCR.ecdsa_conf.ecdsa_clk_en = enable; +} + +/** + * @brief Reset the ECDSA peripheral module + */ +static inline void ecdsa_ll_reset_register(void) +{ + PCR.ecdsa_conf.ecdsa_rst_en = 1; + PCR.ecdsa_conf.ecdsa_rst_en = 0; +} + +/** + * @brief Enable interrupt of a given type + * + * @param type Interrupt type + */ +static inline void ecdsa_ll_enable_intr(ecdsa_ll_intr_type_t type) +{ + switch (type) { + case ECDSA_INT_CALC_DONE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_PREP_DONE_INT_ENA, 1); + break; + case ECDSA_INT_SHA_RELEASE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_SHA_RELEASE_INT_ENA, 1); + break; + default: + HAL_ASSERT(false && "Unsupported interrupt type"); + break; + } +} + +/** + * @brief Disable interrupt of a given type + * + * @param type Interrupt type + */ +static inline void ecdsa_ll_disable_intr(ecdsa_ll_intr_type_t type) +{ + switch (type) { + case ECDSA_INT_CALC_DONE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_PREP_DONE_INT_ENA, 0); + break; + case ECDSA_INT_SHA_RELEASE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_SHA_RELEASE_INT_ENA, 0); + break; + default: + HAL_ASSERT(false && "Unsupported interrupt type"); + break; + } +} + +/** + * @brief Clear interrupt of a given type + * + * @param type Interrupt type + */ +static inline void ecdsa_ll_clear_intr(ecdsa_ll_intr_type_t type) +{ + switch (type) { + case ECDSA_INT_CALC_DONE: + REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_PREP_DONE_INT_CLR, 1); + break; + case ECDSA_INT_SHA_RELEASE: + REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_SHA_RELEASE_INT_CLR, 1); + break; + default: + HAL_ASSERT(false && "Unsupported interrupt type"); + break; + } +} + +/** + * @brief Set working mode of ECDSA + * + * @param mode Mode of operation + */ +static inline void ecdsa_ll_set_mode(ecdsa_mode_t mode) +{ + switch (mode) { + case ECDSA_MODE_SIGN_VERIFY: + REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 0); + break; + case ECDSA_MODE_SIGN_GEN: + REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 1); + break; + case ECDSA_MODE_EXPORT_PUBKEY: + REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 2); + break; + default: + HAL_ASSERT(false && "Unsupported mode"); + break; + } +} + +/** + * @brief Set curve for ECDSA operation + * + * @param curve ECDSA curve + */ +static inline void ecdsa_ll_set_curve(ecdsa_curve_t curve) +{ + switch (curve) { + case ECDSA_CURVE_SECP256R1: + REG_SET_BIT(ECDSA_CONF_REG, ECDSA_ECC_CURVE); + break; + case ECDSA_CURVE_SECP192R1: + REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_ECC_CURVE); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + return; + } +} + +/** + * @brief Set the source of `Z` (SHA message) + * + * @param mode Mode of SHA generation + */ +static inline void ecdsa_ll_set_z_mode(ecdsa_ll_sha_mode_t mode) +{ + switch (mode) { + case ECDSA_Z_USE_SHA_PERI: + REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_Z); + break; + case ECDSA_Z_USER_PROVIDED: + REG_SET_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_Z); + break; + default: + HAL_ASSERT(false && "Unsupported curve"); + break; + } +} + +/** + * @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 + * + * @param stage Stage of operation + */ +static inline void ecdsa_ll_set_stage(ecdsa_ll_stage_t stage) +{ + switch (stage) { + case ECDSA_STAGE_START_CALC: + REG_SET_BIT(ECDSA_START_REG, ECDSA_START); + break; + case ECDSA_STAGE_LOAD_DONE: + REG_SET_BIT(ECDSA_START_REG, ECDSA_LOAD_DONE); + break; + case ECDSA_STAGE_GET_DONE: + REG_SET_BIT(ECDSA_START_REG, ECDSA_GET_DONE); + break; + default: + HAL_ASSERT(false && "Unsupported state"); + break; + } +} + +/** + * @brief Set the SHA type + * + * @param type Type of SHA + */ +static inline void ecdsa_ll_sha_set_type(ecdsa_ll_sha_type_t type) +{ + switch (type) { + case ECDSA_SHA_224: + REG_SET_FIELD(ECDSA_SHA_MODE_REG, ECDSA_SHA_MODE, 1); + break; + case ECDSA_SHA_256: + REG_SET_FIELD(ECDSA_SHA_MODE_REG, ECDSA_SHA_MODE, 2); + break; + default: + HAL_ASSERT(false && "Unsupported type"); + break; + } +} + +/** + * @brief Set the SHA operation mode + * + * @param mode Mode of SHA operation + */ +static inline void ecdsa_ll_sha_set_mode(ecdsa_ll_sha_mode_t mode) +{ + switch (mode) { + case ECDSA_MODE_SHA_START: + REG_SET_BIT(ECDSA_SHA_START_REG, ECDSA_SHA_START); + break; + case ECDSA_MODE_SHA_CONTINUE: + REG_SET_BIT(ECDSA_SHA_CONTINUE_REG, ECDSA_SHA_CONTINUE); + break; + default: + HAL_ASSERT(false && "Unsupported type"); + break; + } +} + +/** + * @brief Check if SHA is busy + * + * @return - true, if SHA is busy + * - false, if SHA is IDLE + */ +static inline bool ecdsa_ll_sha_is_busy(void) +{ + return REG_GET_BIT(ECDSA_SHA_BUSY_REG, ECDSA_SHA_BUSY); +} + +/** + * @brief Write the ECDSA parameter + * + * @param param Parameter to be written + * @param buf Buffer containing data + * @param len Length of buffer + */ +static inline void ecdsa_ll_write_param(ecdsa_ll_param_t param, const uint8_t *buf, uint16_t len) +{ + uint32_t reg; + uint32_t word; + switch (param) { + case ECDSA_PARAM_R: + reg = ECDSA_R_MEM; + break; + case ECDSA_PARAM_S: + reg = ECDSA_S_MEM; + break; + case ECDSA_PARAM_Z: + reg = ECDSA_Z_MEM; + break; + case ECDSA_PARAM_QAX: + reg = ECDSA_QAX_MEM; + break; + case ECDSA_PARAM_QAY: + reg = ECDSA_QAY_MEM; + break; + default: + HAL_ASSERT(false && "Invalid parameter"); + return; + } + + for (int i = 0; i < len; i += 4) { + memcpy(&word, buf + i, 4); + REG_WRITE(reg + i, word); + } +} + +/** + * @brief Read the ECDSA parameter + * + * @param param Parameter to be read + * @param buf Buffer where the data will be written + * @param len Length of buffer + */ +static inline void ecdsa_ll_read_param(ecdsa_ll_param_t param, uint8_t *buf, uint16_t len) +{ + uint32_t reg; + switch (param) { + case ECDSA_PARAM_R: + reg = ECDSA_R_MEM; + break; + case ECDSA_PARAM_S: + reg = ECDSA_S_MEM; + break; + case ECDSA_PARAM_Z: + reg = ECDSA_Z_MEM; + break; + case ECDSA_PARAM_QAX: + reg = ECDSA_QAX_MEM; + break; + case ECDSA_PARAM_QAY: + reg = ECDSA_QAY_MEM; + break; + default: + HAL_ASSERT(false && "Invalid parameter"); + return; + } + + memcpy(buf, (void *)reg, len); +} + +/** + * @brief Check if the ECDSA operation is successful + * + * @return - 1, if ECDSA operation succeeds + * - 0, otherwise + */ +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/esp32h21/include/hal/efuse_ll.h b/components/hal/esp32h21/include/hal/efuse_ll.h index 7ed0dbefb7..59159d9df6 100644 --- a/components/hal/esp32h21/include/hal/efuse_ll.h +++ b/components/hal/esp32h21/include/hal/efuse_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +22,11 @@ extern "C" { /******************* eFuse fields *************************/ +__attribute__((always_inline)) static inline uint32_t efuse_ll_get_ecdsa_curve_mode(void) +{ + return EFUSE.rd_repeat_data0.ecdsa_curve_mode; +} + __attribute__((always_inline)) static inline uint32_t efuse_ll_get_flash_crypt_cnt(void) { return EFUSE.rd_repeat_data1.spi_boot_crypt_cnt; 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 6d29b0fccf..8cf5e1dac4 100644 --- a/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c +++ b/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: CC0-1.0 */ @@ -12,8 +12,12 @@ #include "esp_efuse_chip.h" #include "esp_private/esp_crypto_lock_internal.h" #include "esp_random.h" +#include "esp_err.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #include "hal/ecc_ll.h" #include "hal/ecdsa_hal.h" +#include "hal/efuse_ll.h" #include "hal/ecdsa_ll.h" #include "hal/ecdsa_types.h" #ifdef SOC_MPI_SUPPORTED @@ -27,6 +31,8 @@ #include "ecdsa_params.h" #include "hal_crypto_common.h" +__attribute__((unused)) static const char * TAG = "crypto_test"; + static void ecdsa_enable_and_reset(void) { ECDSA_RCC_ATOMIC() { @@ -280,19 +286,41 @@ TEST_TEAR_DOWN(ecdsa) test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL)); } + 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)); +#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED + if (!esp_efuse_is_ecdsa_p192_curve_supported()) { + ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); + } else +#endif + { + 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, false, ECDSA_K_TYPE_TRNG); +#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED + if (!esp_efuse_is_ecdsa_p192_curve_supported()) { + ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); + } else +#endif + { + 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); +#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED + if (!esp_efuse_is_ecdsa_p192_curve_supported()) { + ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); + } else +#endif + { + test_ecdsa_corrupt_data(0, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y); + } } TEST(ecdsa, ecdsa_SECP256R1_signature_verification) @@ -313,7 +341,14 @@ TEST(ecdsa, ecdsa_SECP256R1_corrupt_signature) #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); +#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED + if (!esp_efuse_is_ecdsa_p192_curve_supported()) { + ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); + } else +#endif + { + 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) @@ -325,7 +360,14 @@ TEST(ecdsa, ecdsa_SECP256R1_det_sign_and_verify) #ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY TEST(ecdsa, ecdsa_SECP192R1_export_pubkey) { - test_ecdsa_export_pubkey(0, ecdsa192_pub_x, ecdsa192_pub_y, 0); +#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED + if (!esp_efuse_is_ecdsa_p192_curve_supported()) { + ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); + } else +#endif + { + test_ecdsa_export_pubkey(0, ecdsa192_pub_x, ecdsa192_pub_y, 0); + } } TEST(ecdsa, ecdsa_SECP256R1_export_pubkey) diff --git a/components/mbedtls/test_apps/main/CMakeLists.txt b/components/mbedtls/test_apps/main/CMakeLists.txt index 931e39b189..7059105e28 100644 --- a/components/mbedtls/test_apps/main/CMakeLists.txt +++ b/components/mbedtls/test_apps/main/CMakeLists.txt @@ -7,7 +7,7 @@ set(TEST_CRTS "crts/server_cert_chain.pem" idf_component_register(SRC_DIRS "." PRIV_INCLUDE_DIRS "." - PRIV_REQUIRES cmock test_utils mbedtls esp_timer unity spi_flash esp_psram + PRIV_REQUIRES efuse cmock test_utils mbedtls esp_timer unity spi_flash esp_psram EMBED_TXTFILES ${TEST_CRTS} WHOLE_ARCHIVE) diff --git a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c b/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c index 768516d35c..5d0afc169a 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-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +16,9 @@ #include #include +#include "hal/efuse_ll.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" #include "soc/soc_caps.h" #include "test_utils.h" #include "ccomp_timer.h" @@ -36,6 +39,8 @@ #define NEWLIB_NANO_COMPAT_CAST(int64_t_var) int64_t_var #endif +__attribute__((unused)) static const char * TAG = "mbedtls_test"; + /* * All the following values are in big endian format, as required by the mbedTLS APIs */ @@ -141,8 +146,15 @@ void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8 TEST_CASE("mbedtls ECDSA signature verification performance on SECP192R1", "[mbedtls]") { - test_ecdsa_verify(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_r, ecdsa192_s, +#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED + if (!esp_efuse_is_ecdsa_p192_curve_supported()) { + ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled."); + } else +#endif + { + test_ecdsa_verify(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y); + } } TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbedtls]") diff --git a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in index 47f36de09a..067765ae89 100644 --- a/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h21/include/soc/Kconfig.soc_caps.in @@ -71,6 +71,10 @@ config SOC_ECC_EXTENDED_MODES_SUPPORTED bool default y +config SOC_ECDSA_SUPPORTED + bool + default y + config SOC_FLASH_ENC_SUPPORTED bool default y @@ -703,7 +707,15 @@ config SOC_CRYPTO_DPA_PROTECTION_SUPPORTED bool default y -config SOC_ECDSA_USES_MPI +config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY + bool + default y + +config SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + bool + default y + +config SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED bool default y diff --git a/components/soc/esp32h21/include/soc/soc_caps.h b/components/soc/esp32h21/include/soc/soc_caps.h index 64dbc03d21..07a922e0f8 100644 --- a/components/soc/esp32h21/include/soc/soc_caps.h +++ b/components/soc/esp32h21/include/soc/soc_caps.h @@ -49,7 +49,7 @@ #define SOC_DIG_SIGN_SUPPORTED 1 #define SOC_ECC_SUPPORTED 1 #define SOC_ECC_EXTENDED_MODES_SUPPORTED 1 -// #define SOC_ECDSA_SUPPORTED 1 //TODO: [ESP32H21] IDF-11496 +#define SOC_ECDSA_SUPPORTED 1 #define SOC_FLASH_ENC_SUPPORTED 1 // #define SOC_SECURE_BOOT_SUPPORTED 1 //TODO: [ESP32H21] IDF-11500 // #define SOC_BOD_SUPPORTED 1 //TODO: [ESP32H21] IDF-11530 @@ -485,7 +485,9 @@ #define SOC_CRYPTO_DPA_PROTECTION_SUPPORTED 1 /*------------------------- ECDSA CAPS -------------------------*/ -#define SOC_ECDSA_USES_MPI (1) +#define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) +#define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1) +#define SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED (1) /*-------------------------- UART CAPS ---------------------------------------*/ // ESP32-H21 has 2 UARTs diff --git a/components/soc/esp32h21/register/soc/ecdsa_reg.h b/components/soc/esp32h21/register/soc/ecdsa_reg.h index c1e80e2f3d..5584ad5d7b 100644 --- a/components/soc/esp32h21/register/soc/ecdsa_reg.h +++ b/components/soc/esp32h21/register/soc/ecdsa_reg.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,6 +54,13 @@ extern "C" { #define ECDSA_DETERMINISTIC_K_M (ECDSA_DETERMINISTIC_K_V << ECDSA_DETERMINISTIC_K_S) #define ECDSA_DETERMINISTIC_K_V 0x00000001U #define ECDSA_DETERMINISTIC_K_S 5 +/** ECDSA_DETERMINISTIC_LOOP : R/W; bitpos: [21:6]; default: 0; + * The (loop number - 1) value in the deterministic derivation algorithm to derive k. + */ +#define ECDSA_DETERMINISTIC_LOOP 0x0000FFFFU +#define ECDSA_DETERMINISTIC_LOOP_M (ECDSA_DETERMINISTIC_LOOP_V << ECDSA_DETERMINISTIC_LOOP_S) +#define ECDSA_DETERMINISTIC_LOOP_V 0x0000FFFFU +#define ECDSA_DETERMINISTIC_LOOP_S 6 /** ECDSA_CLK_REG register * ECDSA clock gate register @@ -253,6 +260,14 @@ extern "C" { #define ECDSA_OPERATION_RESULT_M (ECDSA_OPERATION_RESULT_V << ECDSA_OPERATION_RESULT_S) #define ECDSA_OPERATION_RESULT_V 0x00000001U #define ECDSA_OPERATION_RESULT_S 0 +/** ECDSA_K_VALUE_WARNING : RO/SS; bitpos: [1]; default: 0; + * The k value warning bit of ECDSA Accelerator, valid when k value is bigger than the + * curve order, then actually taken k = k mod n. + */ +#define ECDSA_K_VALUE_WARNING (BIT(1)) +#define ECDSA_K_VALUE_WARNING_M (ECDSA_K_VALUE_WARNING_V << ECDSA_K_VALUE_WARNING_S) +#define ECDSA_K_VALUE_WARNING_V 0x00000001U +#define ECDSA_K_VALUE_WARNING_S 1 /** ECDSA_DATE_REG register * Version control register