diff --git a/components/hal/ecdsa_hal.c b/components/hal/ecdsa_hal.c index 47853fdc14..552fb423af 100644 --- a/components/hal/ecdsa_hal.c +++ b/components/hal/ecdsa_hal.c @@ -38,6 +38,14 @@ 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) @@ -157,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/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 087bdab05b..0690abd085 100644 --- a/components/hal/include/hal/ecdsa_hal.h +++ b/components/hal/include/hal/ecdsa_hal.h @@ -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. + * This member of the config does not need any explicit initialisation as it is + * used and handled internally by the HAL layer. + */ } ecdsa_hal_config_t; /** @@ -81,6 +86,17 @@ void ecdsa_hal_export_pubkey(ecdsa_hal_config_t *conf, uint8_t *pub_x, uint8_t * */ 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 dd046d35f0..4a674abdad 100644 --- a/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c +++ b/components/hal/test_apps/crypto/main/ecdsa/test_ecdsa.c @@ -127,16 +127,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) { @@ -161,23 +166,35 @@ static void test_ecdsa_sign(bool is_p256, uint8_t* sha, uint8_t* r_le, uint8_t* 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); 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)); } @@ -253,36 +270,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) { @@ -303,6 +327,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/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 0318025f10..95e59b3c37 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1051,6 +1051,10 @@ config SOC_ECDSA_SUPPORT_EXPORT_PUBKEY bool default y +config SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + 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 2698fd2910..c26a36aa4c 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -434,6 +434,7 @@ /*--------------------------- ECDSA CAPS ---------------------------------------*/ #define SOC_ECDSA_SUPPORT_EXPORT_PUBKEY (1) +#define SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE (1) /*-------------------------- Sigma Delta Modulator CAPS -----------------*/ #define SOC_SDM_GROUPS 1U