diff --git a/components/hal/include/hal/ecdsa_hal.h b/components/hal/include/hal/ecdsa_hal.h index 0690abd085..7384883eee 100644 --- a/components/hal/include/hal/ecdsa_hal.h +++ b/components/hal/include/hal/ecdsa_hal.h @@ -32,8 +32,8 @@ typedef struct { 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. + * 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; 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 7a18756eec..97187ad76b 100644 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ b/components/mbedtls/port/ecdsa/ecdsa_alt.c @@ -220,7 +220,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; @@ -259,6 +260,10 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s 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, @@ -266,6 +271,10 @@ 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); @@ -274,6 +283,12 @@ static int esp_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s || !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(); @@ -304,7 +319,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); } @@ -333,12 +348,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, @@ -410,7 +496,7 @@ 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)); + MBEDTLS_MPI_CHK(esp_ecdsa_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen, ECDSA_K_TYPE_TRNG)); } 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/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.