From e9ea55bea2a6d01437cf6e8fd4a8d3a60460bfc0 Mon Sep 17 00:00:00 2001 From: "harshal.patil" Date: Tue, 30 Dec 2025 02:23:29 +0530 Subject: [PATCH] feat(mbedtls/ecdsa): Introduce PSA ECDSA driver --- components/esp-tls/esp_tls_mbedtls.c | 90 +- .../tee_test_fw/main/test_esp_tee_sec_stg.c | 101 +- components/mbedtls/CMakeLists.txt | 57 +- components/mbedtls/mbedtls | 2 +- components/mbedtls/port/aes/esp_aes_gcm.c | 2 - components/mbedtls/port/ecdsa/ecdsa_alt.c | 1523 ----------------- .../mbedtls/port/include/ecdsa/ecdsa_alt.h | 161 -- .../mbedtls/port/include/mbedtls/esp_config.h | 14 + components/mbedtls/port/include/mbedtls/gcm.h | 20 - .../esp_ecdsa/psa_crypto_driver_esp_ecdsa.c | 865 ++++++++++ .../include/psa_crypto_driver_esp_ecdsa.h | 241 +++ .../psa_crypto_driver_esp_ecdsa_contexts.h | 80 + components/mbedtls/test_apps/main/test_gcm.c | 146 -- ...{test_mbedtls_ecdsa.c => test_psa_ecdsa.c} | 525 ++++-- .../protocomm/test_apps/main/test_protocomm.c | 2 - docs/doxygen/Doxyfile | 2 +- docs/en/api-reference/peripherals/ecdsa.rst | 3 +- .../release-6.x/6.0/security.rst | 2 +- docs/sphinx-known-warnings.txt | 10 - .../zh_CN/api-reference/peripherals/ecdsa.rst | 2 +- .../release-6.x/6.0/security.rst | 2 +- .../tee/tee_secure_storage/main/tee_main.c | 71 +- 22 files changed, 1736 insertions(+), 2185 deletions(-) delete mode 100644 components/mbedtls/port/ecdsa/ecdsa_alt.c delete mode 100644 components/mbedtls/port/include/ecdsa/ecdsa_alt.h delete mode 100644 components/mbedtls/port/include/mbedtls/gcm.h create mode 100644 components/mbedtls/port/psa_driver/esp_ecdsa/psa_crypto_driver_esp_ecdsa.c create mode 100644 components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa.h create mode 100644 components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa_contexts.h delete mode 100644 components/mbedtls/test_apps/main/test_gcm.c rename components/mbedtls/test_apps/main/{test_mbedtls_ecdsa.c => test_psa_ecdsa.c} (53%) diff --git a/components/esp-tls/esp_tls_mbedtls.c b/components/esp-tls/esp_tls_mbedtls.c index 42f31565ab..c77f07f940 100644 --- a/components/esp-tls/esp_tls_mbedtls.c +++ b/components/esp-tls/esp_tls_mbedtls.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,8 +24,8 @@ #include "mbedtls/esp_mbedtls_dynamic.h" #include "mbedtls/private/pk_private.h" #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN -#include "mbedtls/ecp.h" -#include "ecdsa/ecdsa_alt.h" +#include "psa_crypto_driver_esp_ecdsa.h" +#include "hal/ecdsa_types.h" #endif #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE @@ -66,23 +66,31 @@ static mbedtls_x509_crt *global_cacert = NULL; #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN /** - * @brief Convert ESP-TLS ECDSA curve enum to mbedTLS group ID - * @param curve ESP-TLS ECDSA curve enum value - * @param grp_id Pointer to store the converted mbedTLS group ID + * @brief Convert ESP-TLS ECDSA curve enum to ESP ECDSA curve + * @param tls_curve ESP-TLS ECDSA curve enum value + * @param curve Pointer to store the converted ESP ECDSA curve + * @param curve_bits Pointer to store the curve bits + * @param sha_alg Pointer to store the SHA algorithm * @return ESP_OK on success, ESP_ERR_INVALID_ARG on invalid curve */ -static esp_err_t esp_tls_ecdsa_curve_to_mbedtls_group_id(esp_tls_ecdsa_curve_t curve, mbedtls_ecp_group_id *grp_id) +static esp_err_t esp_tls_ecdsa_curve_to_esp_ecdsa_curve(esp_tls_ecdsa_curve_t tls_curve, esp_ecdsa_curve_t *curve, size_t *curve_bits, psa_algorithm_t *sha_alg) { - switch (curve) { + switch (tls_curve) { case ESP_TLS_ECDSA_CURVE_SECP256R1: - *grp_id = MBEDTLS_ECP_DP_SECP256R1; + *curve = ESP_ECDSA_CURVE_SECP256R1; + *curve_bits = 256; + *sha_alg = PSA_ALG_SHA_256; break; #if SOC_ECDSA_SUPPORT_CURVE_P384 case ESP_TLS_ECDSA_CURVE_SECP384R1: - *grp_id = MBEDTLS_ECP_DP_SECP384R1; + *curve = ESP_ECDSA_CURVE_SECP384R1; + *curve_bits = 384; + *sha_alg = PSA_ALG_SHA_384; break; #endif default: + *curve_bits = 0; + *sha_alg = 0; return ESP_ERR_INVALID_ARG; } return ESP_OK; @@ -513,12 +521,14 @@ void esp_mbedtls_cleanup(esp_tls_t *tls) #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN /* In mbedtls v4.0, ECDSA keys require manual cleanup of the keypair structure */ if (mbedtls_pk_get_type(&tls->clientkey) == MBEDTLS_PK_ECDSA) { + ESP_LOGD(TAG, "Cleaning up client key"); mbedtls_ecp_keypair *keypair = tls->clientkey.MBEDTLS_PRIVATE(pk_ctx); if (keypair != NULL) { mbedtls_ecp_keypair_free(keypair); mbedtls_free(keypair); keypair = NULL; } + psa_destroy_key(tls->clientkey.MBEDTLS_PRIVATE(priv_id)); tls->clientkey.MBEDTLS_PRIVATE(pk_ctx) = NULL; } @@ -530,6 +540,7 @@ void esp_mbedtls_cleanup(esp_tls_t *tls) mbedtls_free(keypair); keypair = NULL; } + psa_destroy_key(tls->serverkey.MBEDTLS_PRIVATE(priv_id)); tls->serverkey.MBEDTLS_PRIVATE(pk_ctx) = NULL; } #endif @@ -599,23 +610,51 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki) #endif #ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN if (tls->use_ecdsa_peripheral) { + esp_ecdsa_curve_t curve = ESP_ECDSA_CURVE_MAX; + size_t curve_bits = 0; + psa_algorithm_t sha_alg = 0; + psa_algorithm_t ecdsa_alg = 0; // Determine the curve group ID based on user preference - mbedtls_ecp_group_id grp_id; - esp_err_t esp_ret = esp_tls_ecdsa_curve_to_mbedtls_group_id(tls->ecdsa_curve, &grp_id); - if (esp_ret != ESP_OK) { + esp_err_t esp_ret = esp_tls_ecdsa_curve_to_esp_ecdsa_curve(tls->ecdsa_curve, &curve, &curve_bits, &sha_alg); + if (esp_ret != ESP_OK || curve == ESP_ECDSA_CURVE_MAX || curve_bits == 0 || sha_alg == 0) { return esp_ret; } - esp_ecdsa_pk_conf_t conf = { - .grp_id = grp_id, +#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + ecdsa_alg = PSA_ALG_DETERMINISTIC_ECDSA(sha_alg); +#else + ecdsa_alg = PSA_ALG_ECDSA(sha_alg); +#endif + + psa_key_id_t priv_key_id = 0; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + // Set attributes for opaque private key + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&key_attr, curve_bits); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&key_attr, ecdsa_alg); + psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE); + + esp_ecdsa_opaque_key_t opaque_key = { + .curve = curve, .efuse_block = tls->ecdsa_efuse_blk, + .use_km_key = false, }; - ret = esp_ecdsa_set_pk_context(pki->pk_key, &conf); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize pk context for ecdsa peripheral with the key stored in efuse block %d", tls->ecdsa_efuse_blk); + // Import opaque key reference + psa_status_t status = psa_import_key(&key_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id); + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "Failed to import opaque key reference"); + return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED; + } + mbedtls_pk_init(pki->pk_key); + ret = mbedtls_pk_wrap_psa(pki->pk_key, priv_key_id); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to wrap opaque key reference"); return ret; } + + psa_reset_key_attributes(&key_attr); } else #endif if (pki->privkey_pem_buf != NULL) { @@ -1071,24 +1110,21 @@ esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t return esp_ret; } - mbedtls_ecp_group_id grp_id; - esp_ret = esp_tls_ecdsa_curve_to_mbedtls_group_id(tls->ecdsa_curve, &grp_id); - if (esp_ret != ESP_OK) { - return esp_ret; - } - // Create dynamic ciphersuite array based on curve static int ecdsa_peripheral_supported_ciphersuites[4] = {0}; // Max 4 elements int ciphersuite_count = 0; - if (grp_id == MBEDTLS_ECP_DP_SECP384R1) { +#if SOC_ECDSA_SUPPORT_CURVE_P384 + if (tls->ecdsa_curve == ESP_TLS_ECDSA_CURVE_SECP384R1) { ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384; - } else { + } else +#endif + { ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; } #if CONFIG_MBEDTLS_SSL_PROTO_TLS1_3 - if (grp_id == MBEDTLS_ECP_DP_SECP384R1) { + if (tls->ecdsa_curve == ESP_TLS_ECDSA_CURVE_SECP384R1) { ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS1_3_AES_256_GCM_SHA384; } else { ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS1_3_AES_128_GCM_SHA256; diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c index 390f609f0d..5fdd3883be 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c @@ -8,18 +8,18 @@ #include "esp_log.h" #include "esp_heap_caps.h" #include "esp_partition.h" -#include "ecdsa/ecdsa_alt.h" #include "esp_tee.h" #include "esp_tee_sec_storage.h" #include "secure_service_num.h" #include "psa/initial_attestation.h" +#include "psa/crypto.h" +#include "psa_crypto_driver_esp_ecdsa.h" #include "esp_random.h" #include "nvs.h" #include "unity.h" #include "sdkconfig.h" -#include "ecdsa/ecdsa_alt.h" /* Note: negative value here so that assert message prints a grep-able error hex value (mbedTLS uses -N for error codes) */ @@ -491,26 +491,35 @@ static const uint8_t sha[] = { 0xa9, 0x53, 0x97, 0xec, 0xcc, 0x66, 0x5b, 0xa6 }; -static void test_ecdsa_sign(mbedtls_ecp_group_id gid) +static void test_ecdsa_sign(esp_ecdsa_curve_t curve) { esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_TYPE_MAX; size_t key_len = 0; size_t sha_len = SHA256_DIGEST_SZ; - switch (gid) { - case MBEDTLS_ECP_DP_SECP256R1: + psa_algorithm_t sha_alg = 0; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + uint8_t export_pub_key[1 + 2 * ECDSA_SECP384R1_KEY_LEN] = {0}; + uint8_t signature[2 * ECDSA_SECP384R1_KEY_LEN]; + size_t signature_len = 0; + + switch (curve) { + case ESP_ECDSA_CURVE_SECP256R1: key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; key_len = ECDSA_SECP256R1_KEY_LEN; + sha_alg = PSA_ALG_SHA_256; break; #if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN - case MBEDTLS_ECP_DP_SECP384R1: + case ESP_ECDSA_CURVE_SECP384R1: key_type = ESP_SEC_STG_KEY_ECDSA_SECP384R1; key_len = ECDSA_SECP384R1_KEY_LEN; sha_len = SHA384_DIGEST_SZ; + sha_alg = PSA_ALG_SHA_384; break; #endif default: - ESP_LOGE(TAG, "Unsupported curve ID: %d", gid); + ESP_LOGE(TAG, "Unsupported curve ID: %d", curve); return; } const char *key_id = "ecdsa_k0"; @@ -523,53 +532,75 @@ static void test_ecdsa_sign(mbedtls_ecp_group_id gid) esp_err_t err = esp_tee_sec_storage_clear_key(key_cfg.id); TEST_ASSERT_TRUE(err == ESP_OK || err == ESP_ERR_NOT_FOUND); + // TODO: Add wrapper for psa_generate_key() TEST_ESP_OK(esp_tee_sec_storage_gen_key(&key_cfg)); - esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {}; - TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey)); + psa_key_id_t priv_key_id = 0; + psa_key_attributes_t priv_key_attr = PSA_KEY_ATTRIBUTES_INIT; - mbedtls_mpi r, s; - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); + psa_key_id_t pub_key_id = 0; + psa_key_attributes_t pub_key_attr = PSA_KEY_ATTRIBUTES_INIT; - mbedtls_ecdsa_context ecdsa_context; - mbedtls_ecdsa_init(&ecdsa_context); - - TEST_ASSERT_MBEDTLS_OK(mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), gid)); - - mbedtls_pk_context key_ctx; - - esp_ecdsa_pk_conf_t conf = { - .grp_id = gid, + esp_ecdsa_opaque_key_t opaque_key = { + .curve = curve, .tee_key_id = key_id, - .load_pubkey = true, }; - TEST_ASSERT_EQUAL(0, esp_ecdsa_tee_set_pk_context(&key_ctx, &conf)); - mbedtls_ecp_keypair *keypair = key_ctx.MBEDTLS_PRIVATE(pk_ctx); //mbedtls_pk_ec(key_ctx); - mbedtls_mpi key_mpi = keypair->MBEDTLS_PRIVATE(d); + psa_algorithm_t alg = PSA_ALG_ECDSA(sha_alg); - TEST_ASSERT_MBEDTLS_OK(mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, sha_len, NULL, NULL)); + // Set attributes for opaque private key + psa_set_key_type(&priv_key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&priv_key_attr, key_len * 8); + psa_set_key_usage_flags(&priv_key_attr, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&priv_key_attr, alg); + psa_set_key_lifetime(&priv_key_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE); // Opaque key - esp_tee_sec_storage_ecdsa_sign_t sign = {}; - TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&r, sign.signature, key_len)); - TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&s, sign.signature + key_len, key_len)); + status = psa_import_key(&priv_key_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id); - TEST_ESP_OK(verify_ecdsa_sign(key_type, sha, sha_len, &pubkey, &sign)); + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_NOT_EQUAL(0, priv_key_id); - esp_ecdsa_free_pk_context(&key_ctx); - mbedtls_ecdsa_free(&ecdsa_context); - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); + size_t pub_key_len = 0; + status = psa_export_public_key(priv_key_id, export_pub_key, sizeof(export_pub_key), &pub_key_len); + + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(pub_key_len, 1 + 2 * key_len); + + status = psa_sign_hash(priv_key_id, + alg, + sha, sha_len, + signature, 2 * key_len, + &signature_len); + + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(signature_len, 2 * key_len); + + psa_set_key_type(&pub_key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&pub_key_attr, key_len * 8); + psa_set_key_usage_flags(&pub_key_attr, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&pub_key_attr, alg); + psa_set_key_lifetime(&pub_key_attr, PSA_KEY_PERSISTENCE_VOLATILE); + + status = psa_import_key(&pub_key_attr, export_pub_key, pub_key_len, &pub_key_id); + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_NOT_EQUAL(0, pub_key_id); + + status = psa_verify_hash(pub_key_id, alg, sha, sha_len, signature, 2 * key_len); + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id)); + + psa_destroy_key(priv_key_id); + psa_destroy_key(pub_key_id); + psa_reset_key_attributes(&priv_key_attr); + psa_reset_key_attributes(&pub_key_attr); } TEST_CASE("Test TEE Secure Storage - mbedtls ECDSA signing", "[mbedtls]") { test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1); #if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP384R1); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1); #endif } #endif diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index fc5b52bf46..992c8c5dff 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -4,7 +4,7 @@ idf_build_get_property(esp_tee_build ESP_TEE_BUILD) if(esp_tee_build) include(${COMPONENT_DIR}/esp_tee/esp_tee_mbedtls.cmake) - return() +return() elseif(BOOTLOADER_BUILD) # TODO: IDF-11673 if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER) @@ -415,47 +415,28 @@ if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES) endif() endif() -if(CONFIG_MBEDTLS_HARDWARE_ECC) - target_sources(builtin PRIVATE "${COMPONENT_DIR}/port/ecc/esp_ecc.c" - "${COMPONENT_DIR}/port/ecc/ecc_alt.c") - include_directories("${COMPONENT_DIR}/tf-psa-crypto/drivers/builtin/include/mbedtls") +if(CONFIG_SOC_ECC_SUPPORTED) + target_sources(builtin PRIVATE "${COMPONENT_DIR}/port/ecc/esp_ecc.c") + if(CONFIG_MBEDTLS_HARDWARE_ECC) + target_sources(builtin PRIVATE "${COMPONENT_DIR}/port/ecc/ecc_alt.c") + include_directories("${COMPONENT_DIR}/tf-psa-crypto/drivers/builtin/include/mbedtls") + endif() endif() -if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR -CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN) - target_sources(builtin PRIVATE "${COMPONENT_DIR}/port/ecdsa/ecdsa_alt.c") - - set(WRAP_FUNCTIONS_SIGN - mbedtls_ecdsa_sign - mbedtls_ecdsa_sign_restartable - mbedtls_ecdsa_write_signature - mbedtls_ecdsa_write_signature_restartable) - - set(WRAP_FUNCTIONS_VERIFY - mbedtls_ecdsa_verify - mbedtls_ecdsa_verify_restartable - mbedtls_ecdsa_read_signature - mbedtls_ecdsa_read_signature_restartable) - +if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN) + # ESP_ECDSA_DRIVER_ENABLED needs to be public because users would use OPAQUE key contexts in their applications. + target_compile_definitions(tfpsacrypto PUBLIC ESP_ECDSA_DRIVER_ENABLED) if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN) - foreach(wrap ${WRAP_FUNCTIONS_SIGN}) - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}") - endforeach() - - 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() + target_compile_definitions(tfpsacrypto PRIVATE ESP_ECDSA_SIGN_DRIVER_ENABLED) endif() - if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) - foreach(wrap ${WRAP_FUNCTIONS_VERIFY}) - target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}") - endforeach() + target_compile_definitions(tfpsacrypto PRIVATE ESP_ECDSA_VERIFY_DRIVER_ENABLED) endif() - + target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/psa_driver/esp_ecdsa/psa_crypto_driver_esp_ecdsa.c") + target_include_directories(tfpsacrypto PUBLIC "${COMPONENT_DIR}/port/psa_driver/include") + target_link_libraries(tfpsacrypto PRIVATE idf::efuse) if(CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN) - target_link_libraries(builtin PRIVATE idf::tee_sec_storage) + target_link_libraries(tfpsacrypto PRIVATE idf::tee_sec_storage) endif() endif() @@ -508,10 +489,6 @@ if(CONFIG_PM_ENABLE) target_link_libraries(tfpsacrypto PRIVATE idf::esp_pm) endif() -if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) - target_link_libraries(builtin PRIVATE idf::efuse) -endif() - target_link_libraries(${COMPONENT_LIB} ${linkage_type} ${mbedtls_targets}) # Ensure PSA crypto initialization is included in the build @@ -529,7 +506,7 @@ function(builtin_optional_deps component_name) endfunction() if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM) - builtin_optional_deps(esp_timer idf::esp_timer) + target_link_libraries(tfpsacrypto PRIVATE idf::esp_timer) endif() # # Link esp-cryptoauthlib to mbedtls diff --git a/components/mbedtls/mbedtls b/components/mbedtls/mbedtls index 41dc25dd2f..ccdb388c27 160000 --- a/components/mbedtls/mbedtls +++ b/components/mbedtls/mbedtls @@ -1 +1 @@ -Subproject commit 41dc25dd2f557cbb0ee0771e6c725b3621d65527 +Subproject commit ccdb388c276d67c8c86066ec1f1b277483884c78 diff --git a/components/mbedtls/port/aes/esp_aes_gcm.c b/components/mbedtls/port/aes/esp_aes_gcm.c index ff40afbd3b..02a6f2c856 100644 --- a/components/mbedtls/port/aes/esp_aes_gcm.c +++ b/components/mbedtls/port/aes/esp_aes_gcm.c @@ -21,8 +21,6 @@ #include "esp_aes_internal.h" #include "hal/aes_hal.h" -#include "mbedtls/gcm.h" - #include "esp_heap_caps.h" #include "esp_log.h" #include "soc/soc_caps.h" diff --git a/components/mbedtls/port/ecdsa/ecdsa_alt.c b/components/mbedtls/port/ecdsa/ecdsa_alt.c deleted file mode 100644 index d622dff227..0000000000 --- a/components/mbedtls/port/ecdsa/ecdsa_alt.c +++ /dev/null @@ -1,1523 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include - -#include "esp_err.h" -#include "esp_log.h" - -#include "hal/ecdsa_types.h" - -#include "soc/soc_caps.h" - -#include "esp_crypto_lock.h" -#include "esp_crypto_periph_clk.h" -#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS -#include "mbedtls/private/ecdsa.h" -#include "mbedtls/private/pk_private.h" -#include "mbedtls/asn1.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/platform_util.h" -#include "mbedtls/bignum.h" - -#include "ecdsa/ecdsa_alt.h" -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY -#include "pk_wrap.h" -#endif // CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY -#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN -#include "esp_tee_sec_storage.h" -#endif -#if SOC_ECDSA_SUPPORTED -#include "hal/ecdsa_ll.h" -#include "hal/ecdsa_hal.h" -#include "esp_efuse.h" -#include "esp_efuse_chip.h" -#endif -#if SOC_ECC_SUPPORTED -#include "hal/ecc_ll.h" -#endif -#if SOC_MPI_SUPPORTED -#include "hal/mpi_ll.h" -#endif - -#define ECDSA_KEY_MAGIC (short) 0xECD5A -#define ECDSA_KEY_MAGIC_TEE (short) 0xA5DCE - -/* Key lengths for different ECDSA curves */ -#define ECDSA_KEY_LEN_P192 24 -#define ECDSA_KEY_LEN_P256 32 -#define ECDSA_KEY_LEN_P384 48 - -#if SOC_ECDSA_SUPPORT_CURVE_P384 -#define MAX_ECDSA_COMPONENT_LEN 48 -#define MAX_ECDSA_SHA_LEN 48 -#else -#define MAX_ECDSA_COMPONENT_LEN 32 -#define MAX_ECDSA_SHA_LEN 32 -#endif - -#define ECDSA_SHA_LEN 32 -#if SOC_ECDSA_SUPPORT_CURVE_P384 -#define ECDSA_SHA_LEN_P384 48 -#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM -#include "esp_timer.h" -#include "soc/chip_revision.h" -#include "hal/efuse_hal.h" - -#if CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH -/* - * This is the maximum time (in us) required for performing 1 ECDSA signature - * in this configuration along some additional margin considerations - */ -#define ECDSA_MAX_SIG_TIME 24000 -#else /* CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH */ -#define ECDSA_MAX_SIG_TIME 17500 -#endif /* !CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH */ - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM -#define DUMMY_OP_COUNT ECDSA_SIGN_MAX_DUMMY_OP_COUNT -#else /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM */ -#define DUMMY_OP_COUNT 0 -#endif /* !CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM */ -#define ECDSA_CM_FIXED_SIG_TIME ECDSA_MAX_SIG_TIME * (DUMMY_OP_COUNT + 1) - -#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM */ - -__attribute__((unused)) static const char *TAG = "ecdsa_alt"; - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY -/* Forward declaration of custom PK info structure for ESP hardware ECDSA */ -extern const mbedtls_pk_info_t esp_ecdsa_pk_info; -#endif - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN -/* Forward declarations for wrapped functions */ -int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -/* Forward declaration for ASN.1 conversion helper */ -static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, - unsigned char *sig, size_t sig_size, - size_t *slen); -#endif - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY -int __wrap_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s); - -/* Forward declaration for hardware verify function */ -static int esp_ecdsa_verify(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s); -#else -/* Forward declaration for software verify when hardware verify is disabled */ -int __real_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s); -#endif - - -#if SOC_ECDSA_SUPPORTED -/** - * @brief Check if the extracted efuse blocks are valid - * - * @param high_blk High efuse block number - * @param low_blk Low efuse block number - * @return true if both blocks are valid, false otherwise - */ -static inline bool is_efuse_blk_valid(int high_blk, int low_blk) -{ - return (high_blk >= EFUSE_BLK0 && high_blk < EFUSE_BLK_MAX && - low_blk >= EFUSE_BLK0 && low_blk < EFUSE_BLK_MAX); -} - -static void esp_ecdsa_acquire_hardware(void) -{ - esp_crypto_ecdsa_lock_acquire(); - - esp_crypto_ecdsa_enable_periph_clk(true); - - esp_crypto_ecc_enable_periph_clk(true); - -#if SOC_ECDSA_USES_MPI - if (ecdsa_ll_is_mpi_required()) { - /* We need to reset the MPI peripheral because ECDSA peripheral - * of some targets use the MPI peripheral as well. - */ - esp_crypto_mpi_enable_periph_clk(true); - } -#endif /* SOC_ECDSA_USES_MPI */ -} - -static void esp_ecdsa_release_hardware(void) -{ - esp_crypto_ecdsa_enable_periph_clk(false); - - esp_crypto_ecc_enable_periph_clk(false); - -#if SOC_ECDSA_USES_MPI - if (ecdsa_ll_is_mpi_required()) { - esp_crypto_mpi_enable_periph_clk(false); - } -#endif /* SOC_ECDSA_USES_MPI */ - - esp_crypto_ecdsa_lock_release(); -} -#endif /* SOC_ECDSA_SUPPORTED */ - -#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN -/** - * @brief Validate if the efuse block(s) have the appropriate ECDSA key purpose for the given curve - * - * This function validates that the provided efuse block(s) have been programmed with the appropriate - * ECDSA key purpose for the specified curve type. It handles both curve-specific key purposes - * (when SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES is defined) and generic ECDSA key purpose. - * - * For SECP384R1 curve, it checks for both high and low key blocks when supported. - * For SECP192R1 and SECP256R1 curves, it validates the single block. - * - * @param[in] grp_id The ECP group ID (curve type) to validate the key purpose for - * @param[in] efuse_blk The efuse block(s) to validate (can be combined for 384-bit keys) - * - * @return - * - 0 on success (block(s) have correct purpose) - * - MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input parameters are invalid - * - MBEDTLS_ERR_ECP_INVALID_KEY if block(s) don't have appropriate key purpose - */ -static int esp_ecdsa_validate_efuse_block(mbedtls_ecp_group_id grp_id, int efuse_blk) -{ - int low_blk = efuse_blk; - esp_efuse_purpose_t expected_key_purpose_low; -#if SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES && ((!defined(CONFIG_IDF_TARGET_ESP32P4) && SOC_EFUSE_ECDSA_KEY_P192) || EFUSE_LL_HAS_ECDSA_KEY_P192) -#if SOC_ECDSA_SUPPORT_CURVE_P384 - int high_blk; - HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk); - esp_efuse_purpose_t expected_key_purpose_high; -#endif - - switch (grp_id) { - case MBEDTLS_ECP_DP_SECP192R1: - expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P192; - break; - case MBEDTLS_ECP_DP_SECP256R1: - expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P256; - break; -#if SOC_ECDSA_SUPPORT_CURVE_P384 - case MBEDTLS_ECP_DP_SECP384R1: - expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_L; - expected_key_purpose_high = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_H; - break; -#endif - default: - ESP_LOGE(TAG, "Unsupported ECDSA curve ID: %d", grp_id); - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } -#else /* SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES && ((!defined(CONFIG_IDF_TARGET_ESP32P4) && SOC_EFUSE_ECDSA_KEY_P192) || EFUSE_LL_HAS_ECDSA_KEY_P192) */ - expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY; -#endif /* !SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES && ((!defined(CONFIG_IDF_TARGET_ESP32P4) && SOC_EFUSE_ECDSA_KEY_P192) || EFUSE_LL_HAS_ECDSA_KEY_P192) */ - - if (expected_key_purpose_low != esp_efuse_get_key_purpose((esp_efuse_block_t)low_blk)) { - ESP_LOGE(TAG, "Key burned in efuse has incorrect purpose"); - return MBEDTLS_ERR_ECP_INVALID_KEY; - } - -#if SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES && ((!defined(CONFIG_IDF_TARGET_ESP32P4) && SOC_EFUSE_ECDSA_KEY_P192) || EFUSE_LL_HAS_ECDSA_KEY_P192) -#if SOC_ECDSA_SUPPORT_CURVE_P384 -// Only check high block purpose for P384 curves that actually use it - if (grp_id == MBEDTLS_ECP_DP_SECP384R1 && - expected_key_purpose_high != esp_efuse_get_key_purpose((esp_efuse_block_t)high_blk)) { - ESP_LOGE(TAG, "Key burned in efuse has incorrect purpose for high block"); - return MBEDTLS_ERR_ECP_INVALID_KEY; - } -#endif // SOC_ECDSA_SUPPORT_CURVE_P384 -#endif // SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES && ((!defined(CONFIG_IDF_TARGET_ESP32P4) && SOC_EFUSE_ECDSA_KEY_P192) || EFUSE_LL_HAS_ECDSA_KEY_P192) - - return 0; -} -#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ - -static void __attribute__((unused)) ecdsa_be_to_le(const uint8_t* be_point, uint8_t *le_point, uint8_t len) -{ - /* When the size is 24 bytes, it should be padded with 0 bytes*/ - memset(le_point, 0x0, len); - - for(int i = 0; i < len; i++) { - le_point[i] = be_point[len - i - 1]; - } -} - -#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY -int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk) -{ - int ret = -1; - bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false; - - // Check if ECDSA peripheral is supported on this chip revision - if (!ecdsa_ll_is_supported()) { - ESP_LOGE(TAG, "ECDSA peripheral not supported on this chip revision"); - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } - - if (!use_km_key) { - int high_blk, low_blk; - HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk); - - if (!is_efuse_blk_valid(high_blk, low_blk)) { - ESP_LOGE(TAG, "Invalid efuse block selected"); - return ret; - } - } - - ecdsa_curve_t curve; - uint16_t len; - uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; - uint8_t qx_le[MAX_ECDSA_COMPONENT_LEN]; - uint8_t qy_le[MAX_ECDSA_COMPONENT_LEN]; - - if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP192R1) { - curve = ECDSA_CURVE_SECP192R1; - len = ECDSA_KEY_LEN_P192; - } else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP256R1) { - curve = ECDSA_CURVE_SECP256R1; - len = ECDSA_KEY_LEN_P256; - } -#if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP384R1) { - curve = ECDSA_CURVE_SECP384R1; - len = ECDSA_KEY_LEN_P384; - } -#endif - else { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - if (!use_km_key) { - ret = esp_ecdsa_validate_efuse_block(keypair->MBEDTLS_PRIVATE(grp).id, efuse_blk); - if (ret != 0) { - return ret; - } - } - - ecdsa_hal_config_t conf = { - .mode = ECDSA_MODE_EXPORT_PUBKEY, - .curve = curve, - }; - - if (use_km_key) { - conf.use_km_key = 1; - conf.efuse_key_blk = -1; - } else { - conf.use_km_key = 0; - conf.efuse_key_blk = efuse_blk; - } - - esp_ecdsa_acquire_hardware(); - bool process_again = false; - - do { - ecdsa_hal_export_pubkey(&conf, qx_le, qy_le, 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(); - - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), qx_le, len)); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary_le(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), qy_le, len)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z)), 1)); - - return 0; - -cleanup: - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; -} -#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN -static int validate_ecdsa_pk_input(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf) -{ - int ret = -1; - - if (!key_ctx) { - ESP_LOGE(TAG, "mbedtls_pk_context cannot be NULL"); - return ret; - } - - if (!conf) { - ESP_LOGE(TAG, "esp_ecdsa_pk_conf_t cannot be NULL"); - return ret; - } - - if (conf->grp_id != MBEDTLS_ECP_DP_SECP192R1 && conf->grp_id != MBEDTLS_ECP_DP_SECP256R1 -#if SOC_ECDSA_SUPPORT_CURVE_P384 - && conf->grp_id != MBEDTLS_ECP_DP_SECP384R1 -#endif - ) { - ESP_LOGE(TAG, "Invalid EC curve group id mentioned in esp_ecdsa_pk_conf_t"); - return ret; - } - - return 0; -} -#endif - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN -int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk) -{ - if (!key) { - ESP_LOGE(TAG, "Invalid memory"); - return -1; - } - - bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false; - if (!use_km_key) { - int high_blk, low_blk; - HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk); - - if (!is_efuse_blk_valid(high_blk, low_blk)) { - ESP_LOGE(TAG, "Invalid efuse block selected"); - return -1; - } - } - - mbedtls_mpi_init(key); - - /* We use the mbedtls_mpi struct to pass our own context to hardware ECDSA peripheral - * MPI struct expects `s` to be either 1 or -1, by setting it to 0xECD5A, we ensure that it does - * not collide with a valid MPI. This is done to differentiate between using the private key stored in efuse - * or using the private key provided by software - * - * `n` is used to store the efuse block which should be used as key - */ - key->MBEDTLS_PRIVATE(s) = ECDSA_KEY_MAGIC; - if (!use_km_key) { - key->MBEDTLS_PRIVATE(n) = efuse_blk; - } else { - key->MBEDTLS_PRIVATE(n) = (unsigned short) USE_ECDSA_KEY_FROM_KEY_MANAGER; - } - key->MBEDTLS_PRIVATE(p) = NULL; - - return 0; -} - -int esp_ecdsa_privkey_load_pk_context(mbedtls_pk_context *key_ctx, int efuse_blk) -{ - const mbedtls_pk_info_t *pk_info; - mbedtls_ecp_keypair *keypair; - - if (!key_ctx) { - ESP_LOGE(TAG, "Invalid memory"); - return -1; - } - - bool use_km_key = (efuse_blk == USE_ECDSA_KEY_FROM_KEY_MANAGER)? true: false; - if (!use_km_key) { - int high_blk, low_blk; - HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk); - - if (!is_efuse_blk_valid(high_blk, low_blk)) { - ESP_LOGE(TAG, "Invalid efuse block selected"); - return -1; - } - } - - mbedtls_pk_init(key_ctx); -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY - /* Use our custom pk_info that routes to hardware ECDSA for signing and/or verification */ - pk_info = &esp_ecdsa_pk_info; -#else - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA); -#endif - if (mbedtls_pk_setup(key_ctx, pk_info) != 0) { - return -1; - } - - /* In mbedtls v4.0, MBEDTLS_PK_ECDSA doesn't allocate pk_ctx (ctx_alloc_func = NULL) - * because EC keys are managed through PSA. For hardware ECDSA, we need to manually - * allocate an mbedtls_ecp_keypair structure to store the magic values. */ - keypair = calloc(1, sizeof(mbedtls_ecp_keypair)); - if (keypair == NULL) { - return MBEDTLS_ERR_ECP_ALLOC_FAILED; - } - - /* Initialize the keypair structure */ - mbedtls_ecp_keypair_init(keypair); - - /* Manually assign to pk_ctx since mbedtls_pk_setup didn't do it */ - key_ctx->MBEDTLS_PRIVATE(pk_ctx) = keypair; - - return esp_ecdsa_privkey_load_mpi(&(keypair->MBEDTLS_PRIVATE(d)), efuse_blk); -} - -int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf) -{ - int ret = -1; - int efuse_key_block = -1; - - ret = validate_ecdsa_pk_input(key_ctx, conf); - if (ret != 0) { - return ret; - } - - if (conf->use_km_key) { - efuse_key_block = USE_ECDSA_KEY_FROM_KEY_MANAGER; - } else { - efuse_key_block = conf->efuse_block; - } - - if ((ret = esp_ecdsa_privkey_load_pk_context(key_ctx, efuse_key_block)) != 0) { - ESP_LOGE(TAG, "Loading private key context failed, esp_ecdsa_privkey_load_pk_context() returned %d", ret); - return ret; - } - - mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*key_ctx); - if ((ret = mbedtls_ecp_group_load(&(keypair->MBEDTLS_PRIVATE(grp)), conf->grp_id)) != 0) { - ESP_LOGE(TAG, "Loading ecp group failed, mbedtls_pk_ec() returned %d", ret); - return ret; - } - -#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY - if (conf->load_pubkey) { - if ((ret = esp_ecdsa_load_pubkey(keypair, efuse_key_block)) != 0) { - ESP_LOGE(TAG, "Loading public key context failed, esp_ecdsa_load_pubkey() returned %d", ret); - return ret; - } - } -#endif - return 0; -} - -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, - ecdsa_sign_type_t k_type) -{ - ecdsa_curve_t curve; - uint16_t len; - uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; - uint8_t sha_le[MAX_ECDSA_SHA_LEN]; - uint8_t r_le[MAX_ECDSA_COMPONENT_LEN]; - uint8_t s_le[MAX_ECDSA_COMPONENT_LEN]; - - if (!grp || !r || !s || !d || !msg) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - // Check if ECDSA peripheral is supported on this chip revision - if (!ecdsa_ll_is_supported()) { - ESP_LOGE(TAG, "ECDSA peripheral not supported on this chip revision"); - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } - - if ((grp->id == MBEDTLS_ECP_DP_SECP192R1 && msg_len != ECDSA_SHA_LEN) || - (grp->id == MBEDTLS_ECP_DP_SECP256R1 && msg_len != ECDSA_SHA_LEN) -#if SOC_ECDSA_SUPPORT_CURVE_P384 - || (grp->id == MBEDTLS_ECP_DP_SECP384R1 && msg_len != ECDSA_SHA_LEN_P384) -#endif - ) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { - curve = ECDSA_CURVE_SECP192R1; - len = ECDSA_KEY_LEN_P192; - } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { - curve = ECDSA_CURVE_SECP256R1; - len = ECDSA_KEY_LEN_P256; - } -#if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (grp->id == MBEDTLS_ECP_DP_SECP384R1) { - curve = ECDSA_CURVE_SECP384R1; - len = ECDSA_KEY_LEN_P384; - } -#endif - else { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - bool use_km_key = false; - if (d->MBEDTLS_PRIVATE(n) == (unsigned short) USE_ECDSA_KEY_FROM_KEY_MANAGER) { - use_km_key = true; - } - - if (!use_km_key) { - int ret = esp_ecdsa_validate_efuse_block(grp->id, d->MBEDTLS_PRIVATE(n)); - if (ret != 0) { - return ret; - } - } - - ecdsa_be_to_le(msg, sha_le, len); - - esp_ecdsa_acquire_hardware(); - - bool process_again = false; - -#if !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP - uint16_t deterministic_loop_number __attribute__((unused)) = 1; -#endif /* !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */ - - do { - ecdsa_hal_config_t conf = { - .mode = ECDSA_MODE_SIGN_GEN, - .curve = curve, - .sha_mode = ECDSA_Z_USER_PROVIDED, - .sign_type = k_type, - }; -#if !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP - if (ecdsa_ll_is_deterministic_mode_supported()) { - conf.loop_number = deterministic_loop_number++; - } -#endif /* !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */ - - if (use_km_key) { - conf.use_km_key = 1; - conf.efuse_key_blk = -1; - } else { - conf.use_km_key = 0; - conf.efuse_key_blk = d->MBEDTLS_PRIVATE(n); - } -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM - uint64_t sig_time = esp_timer_get_time(); -#endif - ecdsa_hal_gen_signature(&conf, sha_le, r_le, s_le, len); -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM - if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) { - sig_time = esp_timer_get_time() - sig_time; - if (sig_time < ECDSA_CM_FIXED_SIG_TIME) { - esp_rom_delay_us(ECDSA_CM_FIXED_SIG_TIME - sig_time); - } - } -#endif - process_again = !ecdsa_hal_get_operation_result() - || !memcmp(r_le, zeroes, len) - || !memcmp(s_le, zeroes, len); - -#if SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP - if (ecdsa_ll_is_deterministic_mode_supported() && k_type == ECDSA_K_TYPE_DETERMINISITIC) { - process_again |= !ecdsa_hal_det_signature_k_check(); - } -#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */ - - } while (process_again); - - esp_ecdsa_release_hardware(); - - mbedtls_mpi_read_binary_le(r, r_le, len); - mbedtls_mpi_read_binary_le(s, s_le, len); - - return 0; -} -#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ - -void esp_ecdsa_free_pk_context(mbedtls_pk_context *key_ctx) -{ - if (key_ctx == NULL) { - return; - } - - /* In mbedtls v4.0, we manually allocated the keypair structure for hardware ECDSA. - * We need to free it manually since ctx_free_func is NULL for MBEDTLS_PK_ECDSA. */ - mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*key_ctx); - if (keypair != NULL) { - mbedtls_ecp_keypair_free(keypair); - free(keypair); - key_ctx->MBEDTLS_PRIVATE(pk_ctx) = NULL; - } - - mbedtls_pk_free(key_ctx); -} - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY -/* Custom PK wrapper functions for ESP hardware ECDSA - * - * Flow: mbedtls_pk_sign() → esp_ecdsa_pk_sign_wrap() → esp_ecdsa_sign() → Hardware ECDSA - * - * This bypasses the PSA opaque key path and routes directly to hardware ECDSA - * by using a custom pk_info structure that doesn't require PSA key IDs. - */ -static int esp_ecdsa_pk_can_do(mbedtls_pk_type_t type) -{ - return type == MBEDTLS_PK_ECKEY || - type == MBEDTLS_PK_ECDSA; -} - -static size_t esp_ecdsa_pk_get_bitlen(mbedtls_pk_context *pk) -{ - mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*pk); - if (keypair == NULL) { - return 0; - } - return keypair->MBEDTLS_PRIVATE(grp).nbits; -} -#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY */ - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY -static int esp_ecdsa_pk_verify_wrap(mbedtls_pk_context *pk, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len) -{ - mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*pk); - int ret; - unsigned char *p = (unsigned char *) sig; - const unsigned char *end = sig + sig_len; - size_t len; - mbedtls_mpi r, s; - - (void) md_alg; /* Not used for hardware ECDSA verification */ - - if (keypair == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* Check if public key is loaded */ - if (mbedtls_mpi_cmp_int(&keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 0) == 0) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - - /* Parse the DER signature */ - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - ret += MBEDTLS_ERR_PK_BAD_INPUT_DATA; - goto cleanup; - } - - if (p + len != end) { - ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - goto cleanup; - } - - if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 || - (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) { - ret += MBEDTLS_ERR_PK_BAD_INPUT_DATA; - goto cleanup; - } - - /* Call verification function directly - wrapper doesn't work from same compilation unit */ - ret = esp_ecdsa_verify(&keypair->MBEDTLS_PRIVATE(grp), - hash, hash_len, - &keypair->MBEDTLS_PRIVATE(Q), - &r, &s); - - if (ret == 0 && p != end) { - ESP_LOGW(TAG, "Extra data after signature"); - ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - -cleanup: - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - return ret; -} -#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY */ - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN -static int esp_ecdsa_pk_sign_wrap(mbedtls_pk_context *pk, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t sig_size, - size_t *sig_len) -{ - mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*pk); - int ret; - mbedtls_mpi r, s; - - (void) md_alg; /* Not used for hardware ECDSA signing */ - - if (keypair == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* Check if this is a hardware-backed key by checking the magic value */ - signed short key_magic = keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s); - if (key_magic != ECDSA_KEY_MAGIC && key_magic != ECDSA_KEY_MAGIC_TEE) { - /* Not a hardware key, this shouldn't happen with our setup */ - return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE; - } - - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - - /* Call esp_ecdsa_sign directly - wrapper doesn't work from same compilation unit */ - ret = esp_ecdsa_sign(&keypair->MBEDTLS_PRIVATE(grp), - &r, &s, - &keypair->MBEDTLS_PRIVATE(d), - hash, hash_len, - ECDSA_K_TYPE_TRNG); - if (ret != 0) { - goto cleanup; - } - - /* Convert r and s to DER format */ - ret = ecdsa_signature_to_asn1(&r, &s, sig, sig_size, sig_len); - -cleanup: - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - return ret; -} -#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY -static int esp_ecdsa_pk_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv) -{ - /* For hardware-backed keys, we cannot easily verify the pair - * since the private key never leaves the eFuse. - * We'll do a basic check that both contexts are valid. */ - if (pub == NULL || prv == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - mbedtls_ecp_keypair *pub_keypair = mbedtls_pk_ec(*pub); - mbedtls_ecp_keypair *prv_keypair = mbedtls_pk_ec(*prv); - - if (pub_keypair == NULL || prv_keypair == NULL) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - /* Check that both use the same curve */ - if (pub_keypair->MBEDTLS_PRIVATE(grp).id != prv_keypair->MBEDTLS_PRIVATE(grp).id) { - return MBEDTLS_ERR_PK_BAD_INPUT_DATA; - } - - return 0; -} - -/* Custom pk_info structure for ESP hardware ECDSA */ -const mbedtls_pk_info_t esp_ecdsa_pk_info = { - .type = MBEDTLS_PK_ECDSA, - .name = "ESP_ECDSA", - .get_bitlen = esp_ecdsa_pk_get_bitlen, - .can_do = esp_ecdsa_pk_can_do, -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY - .verify_func = esp_ecdsa_pk_verify_wrap, -#else - .verify_func = NULL, -#endif -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN - .sign_func = esp_ecdsa_pk_sign_wrap, -#else - .sign_func = NULL, -#endif -#if defined(MBEDTLS_ECP_RESTARTABLE) - .verify_rs_func = NULL, - .sign_rs_func = NULL, - .rs_alloc_func = NULL, - .rs_free_func = NULL, -#endif /* MBEDTLS_ECP_RESTARTABLE */ - .check_pair_func = esp_ecdsa_pk_check_pair_wrap, - .ctx_alloc_func = NULL, - .ctx_free_func = NULL, - .debug_func = NULL, -}; -#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY */ - - -#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN -int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, const char *tee_key_id) -{ - int ret = -1; - uint16_t len; - esp_tee_sec_storage_type_t key_type; - - if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP256R1) { - len = ECDSA_KEY_LEN_P256; - key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; - } -#if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP384R1) { - len = ECDSA_KEY_LEN_P384; - key_type = ESP_SEC_STG_KEY_ECDSA_SECP384R1; - } -#endif - else { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - esp_tee_sec_storage_key_cfg_t cfg = { - .id = tee_key_id, - .type = key_type - }; - - esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {}; - if (esp_tee_sec_storage_ecdsa_get_pubkey(&cfg, &pubkey) != ESP_OK) { - ESP_LOGE(TAG, "Failed to get public key from secure storage"); - goto cleanup; - } - - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), pubkey.pub_x, len)); - MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), pubkey.pub_y, len)); - MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z)), 1)); - - return 0; - -cleanup: - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; -} - -int esp_ecdsa_tee_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf) -{ - int ret = -1; - - ret = validate_ecdsa_pk_input(key_ctx, conf); - if (ret != 0) { - ESP_LOGE(TAG, "Invalid input, validate_input() returned %d", ret); - return ret; - } - - if (!conf->tee_key_id) { - ESP_LOGE(TAG, "Invalid esp_ecdsa_pk_conf_t configuration"); - return ret; - } - - const char *key_id = conf->tee_key_id; - if (!key_id) { - ESP_LOGE(TAG, "Invalid TEE key id"); - return ret; - } - - const mbedtls_pk_info_t *pk_info; - mbedtls_ecp_keypair *keypair; - - mbedtls_pk_init(key_ctx); - pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECDSA); - ret = mbedtls_pk_setup(key_ctx, pk_info); - if (ret != 0) { - ESP_LOGE(TAG, "Failed to setup pk context, mbedtls_pk_setup() returned %d", ret); - return ret; - } - keypair = calloc(1, sizeof(mbedtls_ecp_keypair)); - if (keypair == NULL) { - ESP_LOGE(TAG, "Failed to allocate memory for ecp_keypair"); - return MBEDTLS_ERR_ECP_ALLOC_FAILED; - } - - mbedtls_ecp_keypair_init(keypair); - - key_ctx->MBEDTLS_PRIVATE(pk_ctx) = keypair; - - mbedtls_mpi_init(&(keypair->MBEDTLS_PRIVATE(d))); - keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s) = ECDSA_KEY_MAGIC_TEE; - keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(n) = 1; - - mbedtls_mpi_uint *key_id_mpi = malloc(sizeof(mbedtls_mpi_uint)); - if (!key_id_mpi) { - return -1; - } - key_id_mpi[0] = (mbedtls_mpi_uint)(uintptr_t)key_id; - keypair->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(p) = key_id_mpi; - - if ((ret = mbedtls_ecp_group_load(&(keypair->MBEDTLS_PRIVATE(grp)), conf->grp_id)) != 0) { - ESP_LOGE(TAG, "Loading ecp group failed, mbedtls_pk_ec() returned %d", ret); - return ret; - } - - if (conf->load_pubkey) { - if ((ret = esp_ecdsa_tee_load_pubkey(keypair, key_id)) != 0) { - ESP_LOGE(TAG, "Loading public key context failed, esp_ecdsa_load_pubkey() returned %d", ret); - return ret; - } - } - - return 0; -} - -static int esp_ecdsa_tee_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mpi* s, - const mbedtls_mpi *d, const unsigned char* msg, size_t msg_len, - ecdsa_sign_type_t k_type) -{ - uint16_t len; - esp_tee_sec_storage_type_t key_type; - - if (!grp || !r || !s || !d || !msg) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - if ((grp->id == MBEDTLS_ECP_DP_SECP256R1 && msg_len != ECDSA_SHA_LEN) -#if SOC_ECDSA_SUPPORT_CURVE_P384 - || (grp->id == MBEDTLS_ECP_DP_SECP384R1 && msg_len != ECDSA_SHA_LEN_P384) -#endif - ) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { - len = ECDSA_KEY_LEN_P256; - key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; - } -#if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (grp->id == MBEDTLS_ECP_DP_SECP384R1) { - len = ECDSA_KEY_LEN_P384; - key_type = ESP_SEC_STG_KEY_ECDSA_SECP384R1; - } -#endif - else { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - if (k_type != ECDSA_K_TYPE_TRNG) { - ESP_LOGE(TAG, "ECDSA deterministic mode not supported"); - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - const char *key_id = (const char *)(uintptr_t)(d->MBEDTLS_PRIVATE(p)[0]); - - esp_tee_sec_storage_key_cfg_t cfg = { - .id = key_id, - .type = key_type - }; - - esp_tee_sec_storage_ecdsa_sign_t sign = {}; - esp_err_t err = esp_tee_sec_storage_ecdsa_sign(&cfg, (uint8_t *)msg, msg_len, &sign); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to get signature: 0x%08lx", err); - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - mbedtls_mpi_read_binary(r, sign.signature, len); - mbedtls_mpi_read_binary(s, sign.signature + len, len); - - return 0; -} -#endif - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN -/* - * Compute ECDSA signature of a hashed message; - */ -extern int __real_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); - -int __wrap_mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) -{ - /* - * Check `d` whether it contains the hardware key - */ - signed short key_magic = d->MBEDTLS_PRIVATE(s); -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN - if (key_magic == ECDSA_KEY_MAGIC) { - // Use hardware ECDSA peripheral - return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); - } -#endif -#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN - if (key_magic == ECDSA_KEY_MAGIC_TEE) { - // Use TEE secure storage - return esp_ecdsa_tee_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); - } -#endif - - // Fallback to software implementation - return __real_mbedtls_ecdsa_sign(grp, r, s, d, buf, blen, f_rng, p_rng); -} - -extern int __real_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, - mbedtls_ecdsa_restart_ctx *rs_ctx); - -int __wrap_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int (*f_rng_blind)(void *, unsigned char *, size_t), void *p_rng_blind, - mbedtls_ecdsa_restart_ctx *rs_ctx); - -int __wrap_mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - 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 - */ - signed short key_magic = d->MBEDTLS_PRIVATE(s); -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN - if (key_magic == ECDSA_KEY_MAGIC) { - // Use hardware ECDSA peripheral - return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); - } -#endif -#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN - if (key_magic == ECDSA_KEY_MAGIC_TEE) { - // Use TEE secure storage - return esp_ecdsa_tee_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_TRNG); - } -#endif - - // Fallback to software implementation - 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 CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN - if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { - if (ecdsa_ll_is_deterministic_mode_supported()) { - // Use hardware ECDSA peripheral - return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_DETERMINISITIC); - } else { - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } - } -#endif - -#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN - if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC_TEE) { - if (ecdsa_ll_is_deterministic_mode_supported()) { - // Use TEE secure storage - return esp_ecdsa_tee_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_DETERMINISITIC); - } else { - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } - } -#endif - - // Fallback to software implementation - 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 CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN - if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC) { - if (ecdsa_ll_is_deterministic_mode_supported()) { - // Use hardware ECDSA peripheral - return esp_ecdsa_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_DETERMINISITIC); - } else { - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } - } -#endif - -#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN - if (d->MBEDTLS_PRIVATE(s) == ECDSA_KEY_MAGIC_TEE) { - if (ecdsa_ll_is_deterministic_mode_supported()) { - // Use TEE secure storage - return esp_ecdsa_tee_sign(grp, r, s, d, buf, blen, ECDSA_K_TYPE_DETERMINISITIC); - } else { - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } - } -#endif - - // Fallback to software implementation - return __real_mbedtls_ecdsa_sign_det_ext(grp, r, s, d, buf, blen, md_alg, f_rng_blind, p_rng_blind); -} - -#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, - unsigned char *sig, size_t sig_size, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - mbedtls_ecdsa_restart_ctx *rs_ctx); - -int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t sig_size, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - mbedtls_ecdsa_restart_ctx *rs_ctx); - -/* - * Convert a signature (given by context) to ASN.1 - */ -static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, - unsigned char *sig, size_t sig_size, - size_t *slen) -{ - int ret = PSA_ERROR_CORRUPTION_DETECTED; - unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 }; - // Setting the pointer p to the end of the buffer as the functions used afterwards write in backwards manner in the given buffer. - unsigned char *p = buf + sizeof(buf); - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r)); - - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len)); - MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf, - MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE)); - - if (len > sig_size) { - return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - } - - memcpy(sig, p, len); - *slen = len; - - return 0; -} - -int __wrap_mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t sig_size, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - mbedtls_ecdsa_restart_ctx *rs_ctx) -{ - signed short key_magic = ctx->MBEDTLS_PRIVATE(d).MBEDTLS_PRIVATE(s); - - if (key_magic != ECDSA_KEY_MAGIC && key_magic != ECDSA_KEY_MAGIC_TEE) { - return __real_mbedtls_ecdsa_write_signature_restartable(ctx, md_alg, hash, hlen, sig, sig_size, slen, f_rng, p_rng, rs_ctx); - } - - int ret = PSA_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi r, s; - - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - -ecdsa_sign_type_t k_type = ECDSA_K_TYPE_TRNG; -#if defined(SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE) && defined(CONFIG_MBEDTLS_ECDSA_DETERMINISTIC) - if (ecdsa_ll_is_deterministic_mode_supported()) { - k_type = ECDSA_K_TYPE_DETERMINISITIC; - } -#endif - - /* - * Check `d` whether it contains the hardware key - */ -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN - if (key_magic == 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, k_type)); - } -#endif -#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN - if (key_magic == ECDSA_KEY_MAGIC_TEE) { - // Use TEE secure storage - MBEDTLS_MPI_CHK(esp_ecdsa_tee_sign(&ctx->MBEDTLS_PRIVATE(grp), &r, &s, &ctx->MBEDTLS_PRIVATE(d), hash, hlen, k_type)); - } -#endif - - MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen)); - -cleanup: - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - - return ret; -} - -int __wrap_mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t sig_size, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng); - -int __wrap_mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, - mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t sig_size, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng) -{ - return __wrap_mbedtls_ecdsa_write_signature_restartable( - ctx, md_alg, hash, hlen, sig, sig_size, slen, - f_rng, p_rng, NULL); -} -#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */ - -#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY -static int esp_ecdsa_verify(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s) -{ - ecdsa_curve_t curve; - uint16_t len; - uint8_t r_le[MAX_ECDSA_COMPONENT_LEN]; - uint8_t s_le[MAX_ECDSA_COMPONENT_LEN]; - uint8_t qx_le[MAX_ECDSA_COMPONENT_LEN]; - uint8_t qy_le[MAX_ECDSA_COMPONENT_LEN]; - uint8_t sha_le[MAX_ECDSA_SHA_LEN]; - - if (!grp || !buf || !Q || !r || !s) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - // Check if ECDSA peripheral is supported on this chip revision - if (!ecdsa_ll_is_supported()) { - ESP_LOGE(TAG, "ECDSA peripheral not supported on this chip revision"); - return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - } - - if ((grp->id == MBEDTLS_ECP_DP_SECP192R1 && blen != ECDSA_SHA_LEN) || - (grp->id == MBEDTLS_ECP_DP_SECP256R1 && blen != ECDSA_SHA_LEN) -#if SOC_ECDSA_SUPPORT_CURVE_P384 - || (grp->id == MBEDTLS_ECP_DP_SECP384R1 && blen != ECDSA_SHA_LEN_P384) -#endif - ) { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - if (grp->id == MBEDTLS_ECP_DP_SECP192R1) { - curve = ECDSA_CURVE_SECP192R1; - len = ECDSA_KEY_LEN_P192; - } else if (grp->id == MBEDTLS_ECP_DP_SECP256R1) { - curve = ECDSA_CURVE_SECP256R1; - len = ECDSA_KEY_LEN_P256; - } -#if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (grp->id == MBEDTLS_ECP_DP_SECP384R1) { - curve = ECDSA_CURVE_SECP384R1; - len = ECDSA_KEY_LEN_P384; - } -#endif - else { - return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - } - - if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 || - mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0 ) - { - return MBEDTLS_ERR_ECP_VERIFY_FAILED; - } - - ecdsa_be_to_le(buf, sha_le, len); - - mbedtls_mpi_write_binary_le(&Q->MBEDTLS_PRIVATE(X), qx_le, len); - mbedtls_mpi_write_binary_le(&Q->MBEDTLS_PRIVATE(Y), qy_le, len); - mbedtls_mpi_write_binary_le(r, r_le, len); - mbedtls_mpi_write_binary_le(s, s_le, len); - - esp_ecdsa_acquire_hardware(); - - ecdsa_hal_config_t conf = { - .mode = ECDSA_MODE_SIGN_VERIFY, - .curve = curve, - .sha_mode = ECDSA_Z_USER_PROVIDED, - }; - - int ret = ecdsa_hal_verify_signature(&conf, sha_le, r_le, s_le, qx_le, qy_le, len); - - esp_ecdsa_release_hardware(); - - if (ret != 0) { - return MBEDTLS_ERR_ECP_VERIFY_FAILED; - } - - return ret; -} - -/* - * Verify ECDSA signature of hashed message - */ -extern int __real_mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s, - mbedtls_ecdsa_restart_ctx *rs_ctx); - -int __wrap_mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s, - mbedtls_ecdsa_restart_ctx *rs_ctx); - -int __wrap_mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s, - mbedtls_ecdsa_restart_ctx *rs_ctx) -{ - if ((grp->id == MBEDTLS_ECP_DP_SECP192R1 && blen == ECDSA_SHA_LEN && esp_efuse_is_ecdsa_p192_curve_supported()) || - (grp->id == MBEDTLS_ECP_DP_SECP256R1 && blen == ECDSA_SHA_LEN && esp_efuse_is_ecdsa_p256_curve_supported()) -#if SOC_ECDSA_SUPPORT_CURVE_P384 - || (grp->id == MBEDTLS_ECP_DP_SECP384R1 && blen == ECDSA_SHA_LEN_P384) -#endif - ) { - return esp_ecdsa_verify(grp, buf, blen, Q, r, s); - } else { - return __real_mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, rs_ctx); - } -} - -/* - * Verify ECDSA signature of hashed message - */ -extern int __real_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s); - -int __wrap_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s); - -int __wrap_mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, - const mbedtls_mpi *r, - const mbedtls_mpi *s) -{ - return __wrap_mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL); -} - - -int __real_mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen, - mbedtls_ecdsa_restart_ctx *rs_ctx); - -int __wrap_mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen, - mbedtls_ecdsa_restart_ctx *rs_ctx); - -int __wrap_mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen, - mbedtls_ecdsa_restart_ctx *rs_ctx) -{ - int ret = PSA_ERROR_CORRUPTION_DETECTED; - unsigned char *p = (unsigned char *) sig; - const unsigned char *end = sig + slen; - size_t len; - mbedtls_mpi r, s; - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - - if ((ret = mbedtls_asn1_get_tag(&p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { - ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - if (p + len != end) { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - goto cleanup; - } - - if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 || - (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) { - ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - if ((ret = __wrap_mbedtls_ecdsa_verify_restartable(&ctx->MBEDTLS_PRIVATE(grp), hash, hlen, - &ctx->MBEDTLS_PRIVATE(Q), &r, &s, NULL)) != 0) { - goto cleanup; - } - - /* At this point we know that the buffer starts with a valid signature. - * Return 0 if the buffer just contains the signature, and a specific - * error code if the valid signature is followed by more data. */ - if (p != end) { - ret = PSA_ERROR_INVALID_SIGNATURE; - } - -cleanup: - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - - return ret; -} - - -int __real_mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen); - -int __wrap_mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen); - -int __wrap_mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen) -{ - return __wrap_mbedtls_ecdsa_read_signature_restartable( - ctx, hash, hlen, sig, slen, NULL); -} -#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY */ diff --git a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h b/components/mbedtls/port/include/ecdsa/ecdsa_alt.h deleted file mode 100644 index 58ca85713e..0000000000 --- a/components/mbedtls/port/include/ecdsa/ecdsa_alt.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include -#include -#include "mbedtls/ecp.h" -#include "mbedtls/pk.h" -#include "sdkconfig.h" -#include "soc/soc_caps.h" -#include "hal/ecdsa_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define USE_ECDSA_KEY_FROM_KEY_MANAGER INT_MAX - -/** - * @brief ECDSA private key context initialization config structure - * @note Contains configuration information like the efuse key block that should be used as the private key, - * EC group ID of the private key and if the export public key operation is supported - * by the peripheral, a flag load_pubkey that is used specify if the public key has to be populated - */ -typedef struct { - mbedtls_ecp_group_id grp_id; /*!< MbedTLS ECP group identifier */ - union { - uint8_t efuse_block; /*!< EFuse block id for ECDSA private key */ -#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN - const char *tee_key_id; /*!< TEE secure storage key id for ECDSA private key */ -#endif - bool use_km_key; /*!< Use key deployed in the key manager for ECDSA operation. Note: The key must be already deployed by the application and it must be activated for the lifetime of this context */ - }; /*!< Union to hold either EFuse block id or TEE secure storage key id or use key deployed in the key manager for ECDSA operation for ECDSA private key */ -#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN - bool load_pubkey; /*!< Export ECDSA public key from the hardware */ -#endif -} esp_ecdsa_pk_conf_t; - -#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || __DOXYGEN__ - -/** - * @brief Populate the public key buffer of the mbedtls_ecp_keypair context. - * - * @param keypair The mbedtls ECP key-pair structure - * @param efuse_blk The efuse key block that should be used as the private key. - * The efuse block where ECDSA key is stored. If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h. - * @return - 0 if successful - * - MBEDTLS_ERR_ECP_BAD_INPUT_DATA if invalid ecp group id specified - * - MBEDTLS_ERR_ECP_INVALID_KEY if efuse block with purpose ECDSA_KEY is not found - * - -1 if invalid efuse block is specified - */ -int esp_ecdsa_load_pubkey(mbedtls_ecp_keypair *keypair, int efuse_blk); - -#endif // SOC_ECDSA_SUPPORT_EXPORT_PUBKEY || __DOXYGEN__ - -#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || __DOXYGEN__ - -/** - * @brief Initialize MPI to notify mbedtls_ecdsa_sign to use the private key in efuse - * We break the MPI struct of the private key in order to - * differentiate between hardware key and software key - * - * @param key The MPI in which this functions stores the hardware context. - * This must be uninitialized - * @param efuse_blk The efuse key block that should be used as the private key. - * The efuse block where ECDSA key is stored. If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h. - * - * @return - 0 if successful - * - -1 otherwise - * - */ -int esp_ecdsa_privkey_load_mpi(mbedtls_mpi *key, int efuse_blk); - -/** - * @brief Initialize PK context to notify mbedtls_ecdsa_sign to use the private key in efuse - * We break the MPI struct used to represent the private key `d` in ECP keypair - * in order to differentiate between hardware key and software key - * - * @param key_ctx The context in which this functions stores the hardware context. - * This must be uninitialized - * @param efuse_blk The efuse key block that should be used as the private key. - * The efuse block where ECDSA key is stored. If two blocks are used to store the key, then the macro HAL_ECDSA_COMBINE_KEY_BLOCKS() can be used to combine them. The macro is defined in hal/ecdsa_types.h. - * - * @return - 0 if successful - * - -1 otherwise - */ -int esp_ecdsa_privkey_load_pk_context(mbedtls_pk_context *key_ctx, int efuse_blk); - -/** - * @brief Initialize PK context and completely populate mbedtls_ecp_keypair context. - * We break the MPI struct used to represent the private key `d` in ECP keypair - * in order to differentiate between hardware key and software key. - * We also populate the ECP group field present in the mbedtls_ecp_keypair context. - * If the ECDSA peripheral of the chip supports exporting the public key, - * we can also populate the public key buffer of the mbedtls_ecp_keypair context - * if the load_pubkey flag is set in the esp_ecdsa_pk_conf_t config argument. - * - * @param key_ctx The context in which this functions stores the hardware context. - * This must be uninitialized - * @param conf ESP-ECDSA private key context initialization config structure - * - * @return - 0 if successful - * - -1 otherwise - */ -int esp_ecdsa_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf); - -#endif // CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || __DOXYGEN__ - -/** - * @brief Free the PK context initialized with hardware ECDSA key. - * This function properly cleans up the manually allocated mbedtls_ecp_keypair - * structure and then frees the PK context. - * - * Note: In mbedtls v4.0, ECDSA keys are managed through PSA, so the standard - * mbedtls_pk_free() does not deallocate the manually created keypair structure. - * Always use this function instead of mbedtls_pk_free() for contexts initialized - * with esp_ecdsa_set_pk_context(). - * - * @param key_ctx The PK context to free (initialized with esp_ecdsa_set_pk_context) - */ -void esp_ecdsa_free_pk_context(mbedtls_pk_context *key_ctx); - -#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN || __DOXYGEN__ - -/** - * @brief Populate the public key buffer of the mbedtls_ecp_keypair context from - * the TEE secure storage. - * - * @param keypair The mbedtls ECP key-pair structure - * @param tee_key_id The TEE secure storage key id of the private key - * - * @return - 0 if successful else MBEDTLS_ERR_ECP_BAD_INPUT_DATA - */ -int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, const char *tee_key_id); - -/** - * @brief Initialize PK context and fully populate the mbedtls_ecp_keypair context. - * This function modifies the MPI struct used to represent the private key `d` - * in the ECP keypair to differentiate between TEE secure storage keys and software keys. - * It also populates the ECP group field in the mbedtls_ecp_keypair context. - * Additionally, if the load_pubkey flag is set in the esp_ecdsa_pk_conf_t config argument, - * the public key buffer of the mbedtls_ecp_keypair context will be populated. - * - * @param key_ctx The context in which this function stores the TEE secure storage context. - * This must be uninitialized. - * @param conf ESP-ECDSA private key context initialization config structure. - * - * @return - 0 if successful - * - -1 otherwise - */ -int esp_ecdsa_tee_set_pk_context(mbedtls_pk_context *key_ctx, esp_ecdsa_pk_conf_t *conf); - -#endif // CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN || __DOXYGEN__ - -#ifdef __cplusplus -} -#endif diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h index c862bcd7ed..22b4217978 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -237,6 +237,20 @@ #undef MBEDTLS_MPI_MUL_MPI_ALT #endif +#ifdef MBEDTLS_HARDWARE_ECDSA_SIGN +#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192 +#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256 +#if SOC_ECDSA_SUPPORT_CURVE_P384 +#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384 +#endif +#define MBEDTLS_PSA_ACCEL_ALG_ECDSA +#define MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT +#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT +#endif + #ifdef CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN #define MBEDTLS_ECDSA_SIGN_ALT #endif diff --git a/components/mbedtls/port/include/mbedtls/gcm.h b/components/mbedtls/port/include/mbedtls/gcm.h deleted file mode 100644 index a2c9009d0d..0000000000 --- a/components/mbedtls/port/include/mbedtls/gcm.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include "sdkconfig.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_GCM_ALT) && defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) - -#endif /* MBEDTLS_GCM_ALT && MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK*/ - -#ifdef __cplusplus -} -#endif diff --git a/components/mbedtls/port/psa_driver/esp_ecdsa/psa_crypto_driver_esp_ecdsa.c b/components/mbedtls/port/psa_driver/esp_ecdsa/psa_crypto_driver_esp_ecdsa.c new file mode 100644 index 0000000000..abdf9d50f7 --- /dev/null +++ b/components/mbedtls/port/psa_driver/esp_ecdsa/psa_crypto_driver_esp_ecdsa.c @@ -0,0 +1,865 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * ESP ECDSA PSA Crypto Opaque Driver + * + * This driver provides PSA Crypto API integration for ESP ECDSA hardware. + */ + +#include +#include "soc/soc_caps.h" +#include "esp_log.h" + +#include "esp_crypto_lock.h" +#include "esp_crypto_periph_clk.h" + +#include "esp_efuse.h" +#include "esp_efuse_chip.h" + +#if SOC_ECDSA_SUPPORTED +#include "hal/ecdsa_types.h" +#include "hal/ecdsa_hal.h" +#include "hal/ecdsa_ll.h" +#endif /* SOC_ECDSA_SUPPORTED */ + +#if SOC_ECC_SUPPORTED +#include "hal/ecc_ll.h" +#include "ecc_impl.h" +#endif /* SOC_ECC_SUPPORTED */ + +#if SOC_MPI_SUPPORTED && SOC_ECDSA_USES_MPI +#include "hal/mpi_ll.h" +#endif /* SOC_MPI_SUPPORTED && SOC_ECDSA_USES_MPI */ + +#include "psa_crypto_driver_esp_ecdsa.h" +#include "psa_crypto_driver_wrappers_no_static.h" +#include "sdkconfig.h" + +static const char *TAG = "psa_crypto_driver_esp_ecdsa"; + +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN +#include "esp_tee_sec_storage.h" +#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */ + +/* Key lengths for different ECDSA curves */ +#define ECDSA_KEY_LEN_P192 24 +#define ECDSA_KEY_LEN_P256 32 +#define ECDSA_KEY_LEN_P384 48 + +#define ECDSA_UNCOMPRESSED_POINT_FORMAT 0x04 + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM +#include "esp_timer.h" +#include "soc/chip_revision.h" +#include "hal/efuse_hal.h" + +#if CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH +/* + * This is the maximum time (in us) required for performing 1 ECDSA signature + * in this configuration along some additional margin considerations + */ +#define ECDSA_MAX_SIG_TIME 24000 +#else /* CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH */ +#define ECDSA_MAX_SIG_TIME 17500 +#endif /* !CONFIG_ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH */ + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM +#define DUMMY_OP_COUNT ECDSA_SIGN_MAX_DUMMY_OP_COUNT +#else /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM */ +#define DUMMY_OP_COUNT 0 +#endif /* !CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM */ +#define ECDSA_CM_FIXED_SIG_TIME ECDSA_MAX_SIG_TIME * (DUMMY_OP_COUNT + 1) + +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM */ + +// Helper function to get curve from mbedtls group ID +static esp_ecdsa_curve_t psa_bits_to_ecdsa_curve(size_t key_len) +{ + switch (key_len) { + case ECDSA_KEY_LEN_P192: + return ESP_ECDSA_CURVE_SECP192R1; + case ECDSA_KEY_LEN_P256: + return ESP_ECDSA_CURVE_SECP256R1; +#if SOC_ECDSA_SUPPORT_CURVE_P384 + case ECDSA_KEY_LEN_P384: + return ESP_ECDSA_CURVE_SECP384R1; +#endif + default: + return ESP_ECDSA_CURVE_MAX; + } +} + +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN +static esp_tee_sec_storage_type_t esp_ecdsa_curve_to_tee_sec_storage_type(esp_ecdsa_curve_t curve) +{ + switch (curve) { + case ESP_ECDSA_CURVE_SECP256R1: + return ESP_SEC_STG_KEY_ECDSA_SECP256R1; +#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN + case ESP_ECDSA_CURVE_SECP384R1: + return ESP_SEC_STG_KEY_ECDSA_SECP384R1; +#endif + default: + return (esp_tee_sec_storage_type_t)-1; + } +} +#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */ + +static void change_endianess(const uint8_t *old_point, uint8_t *new_point, uint8_t len) +{ + /* When the size is less than MAX_ECDSA_COMPONENT_LEN, it should be padded with 0 bytes*/ + memset(new_point, 0x0, len); + + for(int i = 0; i < len; i++) { + new_point[i] = old_point[len - i - 1]; + } +} + +static psa_status_t validate_ecdsa_sha_alg(psa_algorithm_t alg, const esp_ecdsa_curve_t curve) +{ + if ((PSA_ALG_SIGN_GET_HASH(alg) != PSA_ALG_SHA_256 && (curve == ESP_ECDSA_CURVE_SECP192R1 || curve == ESP_ECDSA_CURVE_SECP256R1)) +#if SOC_ECDSA_SUPPORT_CURVE_P384 + || (PSA_ALG_SIGN_GET_HASH(alg) != PSA_ALG_SHA_384 && curve == ESP_ECDSA_CURVE_SECP384R1) +#endif + ) { + return PSA_ERROR_NOT_SUPPORTED; + } + + return PSA_SUCCESS; +} + +#if SOC_ECDSA_SUPPORTED +static void esp_ecdsa_acquire_hardware(void) +{ + esp_crypto_ecdsa_lock_acquire(); + + esp_crypto_ecdsa_enable_periph_clk(true); + + esp_crypto_ecc_enable_periph_clk(true); + +#if SOC_ECDSA_USES_MPI + if (ecdsa_ll_is_mpi_required()) { + /* We need to reset the MPI peripheral because ECDSA peripheral + * of some targets use the MPI peripheral as well. + */ + esp_crypto_mpi_enable_periph_clk(true); + } +#endif /* SOC_ECDSA_USES_MPI */ +} + +static void esp_ecdsa_release_hardware(void) +{ + esp_crypto_ecdsa_enable_periph_clk(false); + + esp_crypto_ecc_enable_periph_clk(false); + +#if SOC_ECDSA_USES_MPI + if (ecdsa_ll_is_mpi_required()) { + esp_crypto_mpi_enable_periph_clk(false); + } +#endif /* SOC_ECDSA_USES_MPI */ + + esp_crypto_ecdsa_lock_release(); +} + +psa_status_t esp_ecdsa_transparent_verify_hash_start( + esp_ecdsa_transparent_verify_hash_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + // Check if the ECDSA peripheral is supported on this chip revision + if (!ecdsa_ll_is_supported()) { + ESP_LOGE(TAG, "ECDSA peripheral not supported on this chip revision"); + return PSA_ERROR_NOT_SUPPORTED; + } + + if (!operation || !attributes || !key_buffer || !hash || !signature) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // Check if ECDSA algorithm + if (!PSA_ALG_IS_ECDSA(alg)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + size_t key_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)); + esp_ecdsa_curve_t curve = psa_bits_to_ecdsa_curve(key_len); + if (curve == ESP_ECDSA_CURVE_MAX) { + return PSA_ERROR_NOT_SUPPORTED; + } + + status = validate_ecdsa_sha_alg(alg, curve); + if (status != PSA_SUCCESS) { + return status; + } + + if ((curve == ESP_ECDSA_CURVE_SECP192R1 && hash_length != ECDSA_SHA_LEN) || + (curve == ESP_ECDSA_CURVE_SECP256R1 && hash_length != ECDSA_SHA_LEN) +#if SOC_ECDSA_SUPPORT_CURVE_P384 + || (curve == ESP_ECDSA_CURVE_SECP384R1 && hash_length != ECDSA_SHA_LEN_P384) +#endif + ) { + return PSA_ERROR_NOT_SUPPORTED; + } + + if (signature_length != 2 * key_len) { + return PSA_ERROR_INVALID_SIGNATURE; + } + + const uint8_t *public_key_buffer = NULL; + size_t public_key_buffer_size = 0; + uint8_t public_key[2 * MAX_ECDSA_COMPONENT_LEN + 1]; + + /* The contents of key_buffer may either be the private key len bytes + * (private key format), or 0x04 followed by the public key len bytes (public + * key format). To ensure the key is in the latter format, the public key + * is exported. */ + if (!PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes))) { + // Private key is provided, convert it to public key + size_t public_key_size = sizeof(public_key); + size_t public_key_length = 0; + + status = psa_driver_wrapper_export_public_key( + attributes, + key_buffer, + key_buffer_size, + public_key, + public_key_size, + &public_key_length); + if (status != PSA_SUCCESS) { + return status; + } + public_key_buffer = public_key; + public_key_buffer_size = public_key_length; + } else { + public_key_buffer = key_buffer; + public_key_buffer_size = key_buffer_size; + } + + if (public_key_buffer[0] != ECDSA_UNCOMPRESSED_POINT_FORMAT) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // As PSA supports only uncompressed point format, the public key buffer size should be 2 * key_len + 1 + if (public_key_buffer_size != 2 * key_len + 1) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + /* Verify the public key */ + ecc_point_t point; + memset(&point, 0, sizeof(ecc_point_t)); + + change_endianess(public_key_buffer + 1, point.x, key_len); + change_endianess(public_key_buffer + 1 + key_len, point.y, key_len); + point.len = key_len; + + if (!esp_ecc_point_verify(&point)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memset(operation, 0, sizeof(esp_ecdsa_transparent_verify_hash_operation_t)); + operation->curve = curve; + operation->key_len = key_len; + operation->sha_len = hash_length; + change_endianess(hash, operation->sha, key_len); + change_endianess(signature, operation->r, key_len); + change_endianess(signature + key_len, operation->s, key_len); + /* The public key buffer is in the format 0x04 followed by the 2*key_len bytes public key */ + /* The first byte is the format byte, which is ECDSA_UNCOMPRESSED_POINT_FORMAT */ + /* The next key_len bytes are the x coordinate */ + /* The next key_len bytes are the y coordinate */ + change_endianess(public_key_buffer + 1, operation->qx, key_len); + change_endianess(public_key_buffer + 1 + key_len, operation->qy, key_len); + + return PSA_SUCCESS; +} + +psa_status_t esp_ecdsa_transparent_verify_hash_complete(esp_ecdsa_transparent_verify_hash_operation_t *operation) +{ + if (!operation) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + esp_ecdsa_acquire_hardware(); + + ecdsa_hal_config_t conf = { + .mode = ECDSA_MODE_SIGN_VERIFY, + .curve = operation->curve, + .sha_mode = ECDSA_Z_USER_PROVIDED, + }; + + int ret = ecdsa_hal_verify_signature(&conf, operation->sha, operation->r, operation->s, operation->qx, operation->qy, operation->key_len); + + esp_ecdsa_release_hardware(); + + if (ret != 0) { + return PSA_ERROR_INVALID_SIGNATURE; + } + + return PSA_SUCCESS; +} + +psa_status_t esp_ecdsa_transparent_verify_hash_abort(esp_ecdsa_transparent_verify_hash_operation_t *operation) +{ + if (operation) { + memset(operation, 0, sizeof(esp_ecdsa_transparent_verify_hash_operation_t)); + } + return PSA_SUCCESS; +} + +psa_status_t esp_ecdsa_transparent_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + esp_ecdsa_transparent_verify_hash_operation_t operation; + + status = esp_ecdsa_transparent_verify_hash_start(&operation, attributes, key_buffer, key_buffer_size, alg, hash, hash_length, signature, signature_length); + if (status != PSA_SUCCESS) { + return status; + } + + status = esp_ecdsa_transparent_verify_hash_complete(&operation); + if (status != PSA_SUCCESS) { + return status; + } + + return esp_ecdsa_transparent_verify_hash_abort(&operation); +} +#endif /* SOC_ECDSA_SUPPORTED */ + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN +#if SOC_ECDSA_SUPPORT_CURVE_P384 +/** + * @brief Check if the extracted efuse blocks are valid + * + * @param high_blk High efuse block number + * @param low_blk Low efuse block number + * @return true if both blocks are valid, false otherwise + */ +static bool is_efuse_blk_valid(int high_blk, int low_blk) +{ + return (high_blk >= EFUSE_BLK0 && high_blk < EFUSE_BLK_MAX && + low_blk >= EFUSE_BLK0 && low_blk < EFUSE_BLK_MAX); +} +#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ + +/** + * @brief Validate if the efuse block(s) have the appropriate ECDSA key purpose for the given curve + * + * This function validates that the provided efuse block(s) have been programmed with the appropriate + * ECDSA key purpose for the specified curve type. It handles both curve-specific key purposes + * (when SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES is defined) and generic ECDSA key purpose. + * + * For SECP384R1 curve, it checks for both high and low key blocks when supported. + * For SECP192R1 and SECP256R1 curves, it validates the single block. + * + * @param[in] curve The ECDSA curve to validate the key purpose for + * @param[in] efuse_blk The efuse block(s) to validate (can be combined for 384-bit keys) + * + * @return + * - 0 on success (block(s) have correct purpose) + * - PSA_ERROR_INVALID_ARGUMENT if input parameters are invalid + * - PSA_ERROR_NOT_PERMITTED if block(s) don't have appropriate key purpose + */ +static psa_status_t esp_ecdsa_validate_efuse_block(esp_ecdsa_curve_t curve, int efuse_blk) +{ + int low_blk = efuse_blk; + esp_efuse_purpose_t expected_key_purpose_low; +#if SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES +#if SOC_ECDSA_SUPPORT_CURVE_P384 + int high_blk; + HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk); + if (!is_efuse_blk_valid(high_blk, low_blk)) { + ESP_LOGE(TAG, "Invalid efuse block selected"); + return PSA_ERROR_INVALID_ARGUMENT; + } + esp_efuse_purpose_t expected_key_purpose_high; +#endif + + switch (curve) { + case ESP_ECDSA_CURVE_SECP192R1: + expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P192; + break; + case ESP_ECDSA_CURVE_SECP256R1: + expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P256; + break; +#if SOC_ECDSA_SUPPORT_CURVE_P384 + case ESP_ECDSA_CURVE_SECP384R1: + expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_L; + expected_key_purpose_high = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_H; + break; +#endif + default: + ESP_LOGE(TAG, "Unsupported ECDSA curve: %ld", curve); + return PSA_ERROR_INVALID_ARGUMENT; + } +#else /* SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */ + expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY; +#endif /* !SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */ + + if (expected_key_purpose_low != esp_efuse_get_key_purpose((esp_efuse_block_t)low_blk)) { + ESP_LOGE(TAG, "Key burned in efuse has incorrect purpose, expected: %d, got: %d, low_blk: %d", expected_key_purpose_low, esp_efuse_get_key_purpose((esp_efuse_block_t)low_blk), low_blk); + return PSA_ERROR_NOT_PERMITTED; + } + +#if SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES && SOC_ECDSA_SUPPORT_CURVE_P384 + // Only check high block purpose for P384 curves that actually use it + if (curve == ESP_ECDSA_CURVE_SECP384R1 && + expected_key_purpose_high != esp_efuse_get_key_purpose((esp_efuse_block_t)high_blk)) { + ESP_LOGE(TAG, "Key burned in efuse has incorrect purpose for high block"); + return PSA_ERROR_NOT_PERMITTED; + } +#endif + + return PSA_SUCCESS; +} +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN +static psa_status_t validate_ecdsa_opaque_key_attributes(const psa_key_attributes_t *attributes, const esp_ecdsa_opaque_key_t *opaque_key) +{ + esp_ecdsa_curve_t expected_curve = psa_bits_to_ecdsa_curve(PSA_BITS_TO_BYTES(psa_get_key_bits(attributes))); + + if (expected_curve != opaque_key->curve) { + return PSA_ERROR_INVALID_ARGUMENT; + } + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN + if (!(opaque_key->use_km_key +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + || opaque_key->tee_key_id +#endif + )) { + psa_status_t status = esp_ecdsa_validate_efuse_block(opaque_key->curve, opaque_key->efuse_block); + if (status != PSA_SUCCESS) { + return status; + } + } +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ + return PSA_SUCCESS; +} + +psa_status_t esp_ecdsa_opaque_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length, + size_t *bits) +{ + if (!attributes || !data || data_length < 1 || !key_buffer || !key_buffer_length || !bits) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (key_buffer_size < sizeof(esp_ecdsa_opaque_key_t) || data_length < sizeof(esp_ecdsa_opaque_key_t)) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + + const esp_ecdsa_opaque_key_t *opaque_key = (const esp_ecdsa_opaque_key_t *) data; + psa_status_t status = validate_ecdsa_opaque_key_attributes(attributes, opaque_key); + if (status != PSA_SUCCESS) { + return status; + } + + memcpy(key_buffer, opaque_key, sizeof(esp_ecdsa_opaque_key_t)); + *key_buffer_length = sizeof(esp_ecdsa_opaque_key_t); + *bits = psa_get_key_bits(attributes); + return PSA_SUCCESS; +} + +psa_status_t esp_ecdsa_opaque_sign_hash_start( + esp_ecdsa_opaque_sign_hash_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length) +{ + if (!operation || !attributes || !key_buffer || !hash) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (key_buffer_size < sizeof(esp_ecdsa_opaque_key_t)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + // Check if ECDSA algorithm + if (!PSA_ALG_IS_ECDSA(alg)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + esp_ecdsa_opaque_key_t *opaque_key = (esp_ecdsa_opaque_key_t *) key_buffer; + psa_status_t status = validate_ecdsa_opaque_key_attributes(attributes, opaque_key); + if (status != PSA_SUCCESS) { + return status; + } + + status = validate_ecdsa_sha_alg(alg, opaque_key->curve); + if (status != PSA_SUCCESS) { + return status; + } + + size_t component_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)); + + // Validate hash length + if ((opaque_key->curve == ESP_ECDSA_CURVE_SECP192R1 && hash_length != ECDSA_SHA_LEN +#if SOC_ECDSA_SUPPORTED + && esp_efuse_is_ecdsa_p192_curve_supported() +#endif + ) || (opaque_key->curve == ESP_ECDSA_CURVE_SECP256R1 && hash_length != ECDSA_SHA_LEN +#if SOC_ECDSA_SUPPORTED + && esp_efuse_is_ecdsa_p256_curve_supported() +#endif + ) +#if SOC_ECDSA_SUPPORT_CURVE_P384 + || (opaque_key->curve == ESP_ECDSA_CURVE_SECP384R1 && hash_length != ECDSA_SHA_LEN_P384) +#endif + ) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + memset(operation, 0, sizeof(esp_ecdsa_opaque_sign_hash_operation_t)); + + operation->key_len = component_len; + +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + if (opaque_key->tee_key_id) { + // The ESP-TEE API expects the hash in big endian order + memcpy(operation->sha, hash, component_len); + } else +#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */ + { + change_endianess(hash, operation->sha, component_len); + } + + operation->opaque_key = opaque_key; + operation->alg = alg; + operation->sha_len = hash_length; + + return PSA_SUCCESS; +} + +psa_status_t esp_ecdsa_opaque_sign_hash_complete( + esp_ecdsa_opaque_sign_hash_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length) +{ + if (!operation || !signature || !signature_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + size_t component_len = operation->key_len; + + if (signature_size < 2 * component_len) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + esp_ecdsa_opaque_key_t *opaque_key = operation->opaque_key; + if (opaque_key->tee_key_id) { + esp_tee_sec_storage_type_t tee_sec_storage_type = esp_ecdsa_curve_to_tee_sec_storage_type(opaque_key->curve); + if (tee_sec_storage_type == (esp_tee_sec_storage_type_t) -1) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + esp_tee_sec_storage_key_cfg_t cfg = { + .id = opaque_key->tee_key_id, + .type = tee_sec_storage_type + }; + + esp_tee_sec_storage_ecdsa_sign_t sign = {}; + esp_err_t err = esp_tee_sec_storage_ecdsa_sign(&cfg, operation->sha, operation->sha_len, &sign); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to get signature: 0x%08lx", err); + return PSA_ERROR_INVALID_ARGUMENT; + } + + memcpy(signature, sign.signature, 2 * component_len); + *signature_length = 2 * component_len; + + } else +#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */ + { +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN + // Check if the ECDSA peripheral is supported on this chip revision + if (!ecdsa_ll_is_supported()) { + ESP_LOGE(TAG, "ECDSA peripheral not supported on this chip revision"); + return PSA_ERROR_NOT_SUPPORTED; + } + + ecdsa_sign_type_t k_type = ECDSA_K_TYPE_TRNG; + +#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE + if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) { + if (ecdsa_ll_is_deterministic_mode_supported()) { + k_type = ECDSA_K_TYPE_DETERMINISITIC; + } else { + return PSA_ERROR_NOT_SUPPORTED; + } + } +#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ + + uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; + + // Acquire hardware + esp_ecdsa_acquire_hardware(); + + bool process_again = false; + +#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP + uint16_t deterministic_loop_number __attribute__((unused)) = 1; +#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */ + + do { + ecdsa_hal_config_t conf = { + .mode = ECDSA_MODE_SIGN_GEN, + .curve = operation->opaque_key->curve, + .sha_mode = ECDSA_Z_USER_PROVIDED, + .sign_type = k_type, + }; + +#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP + if (k_type == ECDSA_K_TYPE_DETERMINISITIC) { + conf.loop_number = deterministic_loop_number++; + } +#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */ + + // Set key source (consistent with esp_ecdsa_pk_conf_t) + if (operation->opaque_key->use_km_key) { + conf.use_km_key = 1; + } else { + conf.efuse_key_blk = operation->opaque_key->efuse_block; + } + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM + uint64_t sig_time = esp_timer_get_time(); +#endif + // Generate signature + ecdsa_hal_gen_signature(&conf, operation->sha, operation->r, operation->s, component_len); + +#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM + if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) { + sig_time = esp_timer_get_time() - sig_time; + if (sig_time < ECDSA_CM_FIXED_SIG_TIME) { + esp_rom_delay_us(ECDSA_CM_FIXED_SIG_TIME - sig_time); + } + } +#endif + // Check if we need to retry (zero signature or operation failed) + process_again = !ecdsa_hal_get_operation_result() + || !memcmp(operation->r, zeroes, component_len) + || !memcmp(operation->s, zeroes, component_len); + +#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP + if (k_type == ECDSA_K_TYPE_DETERMINISITIC) { + process_again |= !ecdsa_hal_det_signature_k_check(); + } +#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */ + } while (process_again); + + esp_ecdsa_release_hardware(); + + // Convert r from little-endian to big-endian and copy to output + change_endianess(operation->r, signature, component_len); + // Convert s from little-endian to big-endian and copy to output + change_endianess(operation->s, signature + component_len, component_len); +#else + // This is an invalid operation as the hardware ECDSA signing is not supported on this chip + // and still the key is opaque. + return PSA_ERROR_NOT_SUPPORTED; +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ + } + + *signature_length = 2 * component_len; + + return PSA_SUCCESS; +} + +psa_status_t esp_ecdsa_opaque_sign_hash_abort(esp_ecdsa_opaque_sign_hash_operation_t *operation) +{ + if (operation) { + memset(operation, 0, sizeof(esp_ecdsa_opaque_sign_hash_operation_t)); + } + return PSA_SUCCESS; +} + + +psa_status_t esp_ecdsa_opaque_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + esp_ecdsa_opaque_sign_hash_operation_t operation; + + status = esp_ecdsa_opaque_sign_hash_start(&operation, attributes, key_buffer, key_buffer_size, alg, hash, hash_length); + if (status != PSA_SUCCESS) { + esp_ecdsa_opaque_sign_hash_abort(&operation); + return status; + } + + status = esp_ecdsa_opaque_sign_hash_complete(&operation, signature, signature_size, signature_length); + if (status != PSA_SUCCESS) { + esp_ecdsa_opaque_sign_hash_abort(&operation); + return status; + } + + return esp_ecdsa_opaque_sign_hash_abort(&operation); +} + +psa_status_t esp_ecdsa_opaque_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + if (!attributes || !key_buffer || !data || !data_length) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (key_buffer_size < sizeof(esp_ecdsa_opaque_key_t)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + const esp_ecdsa_opaque_key_t *opaque_key = (const esp_ecdsa_opaque_key_t *) key_buffer; + status = validate_ecdsa_opaque_key_attributes(attributes, opaque_key); + if (status != PSA_SUCCESS) { + return status; + } + + // Get curve parameters from attributes + size_t key_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)); + + // As the ESP ECDSA driver only supports uncompressed point format, + // the public key is exported in uncompressed point format (ECDSA_UNCOMPRESSED_POINT_FORMAT || x || y) + // Need 1 byte for format + key_len bytes for x + key_len bytes for y + size_t required_size = 1 + (2 * key_len); + if (data_size < required_size) { + return PSA_ERROR_BUFFER_TOO_SMALL; + } + +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + if (opaque_key->tee_key_id) { + esp_tee_sec_storage_type_t tee_sec_storage_type = esp_ecdsa_curve_to_tee_sec_storage_type(opaque_key->curve); + if (tee_sec_storage_type == (esp_tee_sec_storage_type_t) -1) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + esp_tee_sec_storage_key_cfg_t cfg = { + .id = opaque_key->tee_key_id, + .type = tee_sec_storage_type, + }; + + esp_tee_sec_storage_ecdsa_pubkey_t pubkey; + if (esp_tee_sec_storage_ecdsa_get_pubkey(&cfg, &pubkey) != ESP_OK) { + ESP_LOGE(TAG, "Failed to get public key from secure storage"); + return PSA_ERROR_GENERIC_ERROR; + } + + data[0] = ECDSA_UNCOMPRESSED_POINT_FORMAT; + memcpy(data + 1, pubkey.pub_x, key_len); + memcpy(data + 1 + key_len, pubkey.pub_y, key_len); + } + else +#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */ + { +#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY + // Check if the ECDSA peripheral is supported on this chip revision + if (!ecdsa_ll_is_supported()) { + ESP_LOGE(TAG, "ECDSA peripheral not supported on this chip revision"); + return PSA_ERROR_NOT_SUPPORTED; + } + + uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0}; + uint8_t qx[MAX_ECDSA_COMPONENT_LEN]; + uint8_t qy[MAX_ECDSA_COMPONENT_LEN]; + + ecdsa_hal_config_t conf = { + .mode = ECDSA_MODE_EXPORT_PUBKEY, + .curve = opaque_key->curve, + }; + + if (opaque_key->use_km_key) { + conf.use_km_key = 1; + } else { + conf.efuse_key_blk = opaque_key->efuse_block; + } + + esp_ecdsa_acquire_hardware(); + bool process_again = false; + + do { + ecdsa_hal_export_pubkey(&conf, qx, qy, key_len); + + process_again = !ecdsa_hal_get_operation_result() + || !memcmp(qx, zeroes, key_len) + || !memcmp(qy, zeroes, key_len); + + } while (process_again); + + esp_ecdsa_release_hardware(); + + // Format: uncompressed point (ECDSA_UNCOMPRESSED_POINT_FORMAT byte followed by x and y coordinates) + data[0] = ECDSA_UNCOMPRESSED_POINT_FORMAT; + + // Convert qx from little-endian to big-endian and copy to output + change_endianess(qx, data + 1, key_len); + + // Convert qy from little-endian to big-endian and copy to output + change_endianess(qy, data + 1 + key_len, key_len); +#else + // This is an invalid operation as the export public key is not supported on this chip + // and still the key is opaque + return PSA_ERROR_NOT_SUPPORTED; +#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ + } + + *data_length = required_size; + + return PSA_SUCCESS; +} + +size_t esp_ecdsa_opaque_size_function( + psa_key_type_t key_type, + size_t key_bits) +{ + (void)key_type; + (void)key_bits; + + // Opaque keys always use the same size structure + return sizeof(esp_ecdsa_opaque_key_t); +} +#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ diff --git a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa.h b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa.h new file mode 100644 index 0000000000..63e747e0c4 --- /dev/null +++ b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa.h @@ -0,0 +1,241 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#if defined(ESP_ECDSA_DRIVER_ENABLED) +#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#endif + +#include "psa/crypto.h" +#include "psa/crypto_types.h" +#include "soc/soc_caps.h" + +#include "psa_crypto_driver_esp_ecdsa_contexts.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief ESP ECDSA PSA driver location + * + * Vendor-specific location for ESP hardware ECDSA keys. + * Bits 8-31 are location, using vendor flag (0x800000) + ESP vendor ID. + */ +#define PSA_KEY_LOCATION_ESP_ECDSA ((psa_key_location_t) 0x800001) + +/** + * @brief Construct a lifetime for ESP ECDSA keys with default persistence + */ +#define PSA_KEY_LIFETIME_ESP_ECDSA \ + PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \ + PSA_KEY_PERSISTENCE_DEFAULT, \ + PSA_KEY_LOCATION_ESP_ECDSA) + +/** + * @brief Construct a volatile lifetime for ESP ECDSA keys + */ +#define PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE \ + PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( \ + PSA_KEY_PERSISTENCE_VOLATILE, \ + PSA_KEY_LOCATION_ESP_ECDSA) + +/** + * @brief Sign a hash using ESP ECDSA opaque driver + * + * @param attributes Key attributes + * @param key_buffer Opaque key buffer (esp_ecdsa_opaque_key_t) + * @param key_buffer_size Size of key buffer + * @param alg Signing algorithm + * @param hash Hash to sign + * @param hash_length Length of hash + * @param signature Output buffer for signature + * @param signature_size Size of signature buffer + * @param signature_length Actual signature length + * @return psa_status_t + */ +psa_status_t esp_ecdsa_opaque_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * @brief Import an ESP ECDSA key reference (not actual key material) + * + * This function imports an opaque reference to a key stored in eFuse or Key Manager. + * The import data should contain the esp_ecdsa_opaque_key_t structure. + * + * @param attributes Key attributes + * @param data Import data (esp_ecdsa_opaque_key_t) + * @param data_length Length of import data + * @param key_buffer Output buffer for opaque key + * @param key_buffer_size Size of output buffer + * @param key_buffer_length Actual key buffer length + * @param bits Key size in bits + * @return psa_status_t + */ +psa_status_t esp_ecdsa_opaque_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length, + size_t *bits); + +/** + * @brief Export the public key from an ESP ECDSA opaque key + * + * @param attributes Key attributes + * @param key_buffer Opaque key buffer + * @param key_buffer_size Size of key buffer + * @param data Output buffer for public key + * @param data_size Size of output buffer + * @param data_length Actual public key length + * @return psa_status_t + */ +psa_status_t esp_ecdsa_opaque_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * @brief Get the key buffer size for an ESP ECDSA opaque key + * + * @param key_type Key type + * @param key_bits Key size in bits + * @return size_t Required buffer size + */ +size_t esp_ecdsa_opaque_size_function( + psa_key_type_t key_type, + size_t key_bits); + +/** + * @brief Verify a hash using ESP ECDSA transparent driver + * + * @param attributes Key attributes + * @param key_buffer Key buffer + * @param key_buffer_size Size of key buffer + * @param alg Algorithm + * @param hash Hash to verify + * @param hash_length Length of hash + * @param signature Signature to verify + * @param signature_length Length of signature + * @return psa_status_t + */ +psa_status_t esp_ecdsa_transparent_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * @brief Start a hash verification operation using ESP ECDSA transparent driver + * + * @param operation Operation context + * @param attributes Key attributes + * @param key_buffer Key buffer + * @param key_buffer_size Size of key buffer + * @param alg Algorithm + * @param hash Hash to verify + * @param hash_length Length of hash + * @param signature Signature to verify + * @param signature_length Length of signature + * @return psa_status_t + */ +psa_status_t esp_ecdsa_transparent_verify_hash_start( + esp_ecdsa_transparent_verify_hash_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * @brief Complete a hash verification operation using ESP ECDSA transparent driver + * + * @param operation Operation context + * @return psa_status_t + */ +psa_status_t esp_ecdsa_transparent_verify_hash_complete( + esp_ecdsa_transparent_verify_hash_operation_t *operation); + +/** + * @brief Abort a hash verification operation using ESP ECDSA transparent driver + * + * @param operation Operation context + * @return psa_status_t + */ +psa_status_t esp_ecdsa_transparent_verify_hash_abort( + esp_ecdsa_transparent_verify_hash_operation_t *operation); + +/** + * @brief Start a hash signing operation using ESP ECDSA opaque driver + * + * @param operation Operation context + * @param attributes Key attributes + * @param key_buffer Key buffer + * @param key_buffer_size Size of key buffer + * @param alg Algorithm + * @param hash Hash to sign + * @param hash_length Length of hash + * @return psa_status_t + */ +psa_status_t esp_ecdsa_opaque_sign_hash_start( + esp_ecdsa_opaque_sign_hash_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length); + +/** + * @brief Complete a hash signing operation using ESP ECDSA opaque driver + * + * @param operation Operation context + * @param signature Signature buffer + * @param signature_size Size of signature buffer + * @param signature_length Actual signature length + * @return psa_status_t + */ +psa_status_t esp_ecdsa_opaque_sign_hash_complete( + esp_ecdsa_opaque_sign_hash_operation_t *operation, + uint8_t *signature, size_t signature_size, + size_t *signature_length); + +/** + * @brief Abort a hash signing operation using ESP ECDSA opaque driver + * + * @param operation Operation context + * @return psa_status_t + */ +psa_status_t esp_ecdsa_opaque_sign_hash_abort( + esp_ecdsa_opaque_sign_hash_operation_t *operation); + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_ECDSA_DRIVER_ENABLED */ diff --git a/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa_contexts.h b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa_contexts.h new file mode 100644 index 0000000000..a1c9743850 --- /dev/null +++ b/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa_contexts.h @@ -0,0 +1,80 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD +* +* SPDX-License-Identifier: Apache-2.0 +*/ + +#pragma once + +#include "stdint.h" +#include "stdbool.h" +#include "soc/soc_caps.h" +#include "psa/crypto.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_ECDSA_SUPPORT_CURVE_P384 +#define MAX_ECDSA_COMPONENT_LEN 48 +#define MAX_ECDSA_SHA_LEN 48 +#else +#define MAX_ECDSA_COMPONENT_LEN 32 +#define MAX_ECDSA_SHA_LEN 32 +#endif + +#define ECDSA_SHA_LEN 32 +#if SOC_ECDSA_SUPPORT_CURVE_P384 +#define ECDSA_SHA_LEN_P384 48 +#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ + +/** + * @brief ECDSA curve options + */ +typedef enum { + ESP_ECDSA_CURVE_SECP192R1, + ESP_ECDSA_CURVE_SECP256R1, + ESP_ECDSA_CURVE_SECP384R1, + ESP_ECDSA_CURVE_MAX, +} esp_ecdsa_curve_t; + +/** + * @brief Structure to store opaque key metadata. + */ +typedef struct { + esp_ecdsa_curve_t curve; /**< ECDSA curve */ +#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN + const char *tee_key_id; /**< TEE secure storage key id */ +#endif + bool use_km_key; /**< Use key deployed in the key manager */ + uint8_t efuse_block; /**< eFuse block id for ECDSA private key */ +} esp_ecdsa_opaque_key_t; + +#if !(__DOXYGEN__) // No need to document these structures, these are internal to the driver +/* The buffers are stored in the little-endian format */ +typedef struct { + esp_ecdsa_curve_t curve; + uint8_t r[MAX_ECDSA_COMPONENT_LEN]; + uint8_t s[MAX_ECDSA_COMPONENT_LEN]; + uint8_t qx[MAX_ECDSA_COMPONENT_LEN]; + uint8_t qy[MAX_ECDSA_COMPONENT_LEN]; + uint8_t sha[MAX_ECDSA_SHA_LEN]; + size_t sha_len; + size_t key_len; +} esp_ecdsa_transparent_verify_hash_operation_t; + +/* The buffers are stored in the little-endian format */ +typedef struct { + psa_algorithm_t alg; + esp_ecdsa_opaque_key_t *opaque_key; + uint8_t r[MAX_ECDSA_COMPONENT_LEN]; + uint8_t s[MAX_ECDSA_COMPONENT_LEN]; + uint8_t sha[MAX_ECDSA_SHA_LEN]; + size_t sha_len; + size_t key_len; +} esp_ecdsa_opaque_sign_hash_operation_t; +#endif /* !(__DOXYGEN__) */ +#ifdef __cplusplus +} +#endif diff --git a/components/mbedtls/test_apps/main/test_gcm.c b/components/mbedtls/test_apps/main/test_gcm.c deleted file mode 100644 index b7e86866a5..0000000000 --- a/components/mbedtls/test_apps/main/test_gcm.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Unlicense OR CC0-1.0 - */ -#include -#include -#include "sys/param.h" -#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS -#include "esp_heap_caps.h" -#include "mbedtls/gcm.h" -#include "mbedtls/private/gcm.h" -#include "sdkconfig.h" -#include "unity.h" - - -#if CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER - -typedef struct { - uint8_t *plaintext; - size_t plaintext_length; - uint8_t *aad_buf; - size_t aad_length; - uint8_t *iv; - size_t iv_length; - uint8_t *key; - size_t key_bits; - size_t tag_len; -} gcm_test_cfg_t; - -typedef struct { - const uint8_t *expected_tag; - const uint8_t *ciphertext_last_block; // Last block of the ciphertext -} gcm_test_expected_res_t; - -typedef enum { - GCM_TEST_CRYPT_N_TAG, - GCM_TEST_START_UPDATE_FINISH, -} gcm_test_type_t; - -static void gcm_test(gcm_test_cfg_t *cfg, gcm_test_expected_res_t *res, gcm_test_type_t gcm_type) -{ - mbedtls_gcm_context ctx; - mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_ARIA; - - uint8_t tag_buf_encrypt[16] = {}; - uint8_t tag_buf_decrypt[16] = {}; - uint8_t iv_buf[16] = {}; - uint8_t *ciphertext = malloc(cfg->plaintext_length); - uint8_t *output = malloc(cfg->plaintext_length); - size_t olen; - - if (cfg->plaintext_length != 0) { - TEST_ASSERT_NOT_NULL(ciphertext); - TEST_ASSERT_NOT_NULL(output); - } - - memset(ciphertext, 0, cfg->plaintext_length); - memset(output, 0, cfg->plaintext_length); - memcpy(iv_buf, cfg->iv, cfg->iv_length); - - mbedtls_gcm_init(&ctx); - TEST_ASSERT(mbedtls_gcm_setkey(&ctx, cipher, cfg->key, cfg->key_bits) == 0); - - if (gcm_type == GCM_TEST_CRYPT_N_TAG) { - mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->aad_buf, cfg->aad_length, cfg->plaintext, ciphertext, cfg->tag_len, tag_buf_encrypt); - } else if (gcm_type == GCM_TEST_START_UPDATE_FINISH) { - TEST_ASSERT(mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT, iv_buf, cfg->iv_length) == 0); - TEST_ASSERT(mbedtls_gcm_update_ad(&ctx, cfg->aad_buf, cfg->aad_length) == 0); - TEST_ASSERT(mbedtls_gcm_update(&ctx, cfg->plaintext, cfg->plaintext_length, ciphertext, cfg->plaintext_length, &olen) == 0); - TEST_ASSERT(mbedtls_gcm_finish(&ctx, ciphertext, cfg->plaintext_length, &olen, tag_buf_encrypt, cfg->tag_len) == 0); - } - - size_t offset = cfg->plaintext_length > 16 ? cfg->plaintext_length - 16 : 0; - /* Sanity check: make sure the last ciphertext block matches what we expect to see. */ - TEST_ASSERT_EQUAL_HEX8_ARRAY(res->ciphertext_last_block, ciphertext + offset, MIN(16, cfg->plaintext_length)); - TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_encrypt, cfg->tag_len); - - - if (gcm_type == GCM_TEST_CRYPT_N_TAG) { - TEST_ASSERT(mbedtls_gcm_auth_decrypt(&ctx, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->aad_buf, cfg->aad_length, res->expected_tag, cfg->tag_len, ciphertext, output) == 0); - } else if (gcm_type == GCM_TEST_START_UPDATE_FINISH) { - TEST_ASSERT(mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv_buf, cfg->iv_length) == 0); - TEST_ASSERT(mbedtls_gcm_update_ad(&ctx, cfg->aad_buf, cfg->aad_length) == 0); - TEST_ASSERT(mbedtls_gcm_update(&ctx, ciphertext, cfg->plaintext_length, output, cfg->plaintext_length, &olen) == 0); - TEST_ASSERT(mbedtls_gcm_finish(&ctx, output, cfg->plaintext_length, &olen, tag_buf_decrypt, cfg->tag_len) == 0); - - /* mbedtls_gcm_auth_decrypt already checks tag so only needed for GCM_TEST_START_UPDATE_FINISH */ - TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_decrypt, cfg->tag_len); - } - - TEST_ASSERT_EQUAL_HEX8_ARRAY(cfg->plaintext, output, cfg->plaintext_length); - - mbedtls_gcm_free(&ctx); - free(ciphertext); - free(output); -} - - -TEST_CASE("mbedtls ARIA GCM test", "[gcm]") -{ - const unsigned SZ = 1600; - uint8_t aad[16]; - uint8_t iv[16]; - uint8_t key[16]; - - const uint8_t expected_last_block[] = { - 0xbe, 0x96, 0xf1, 0x57, 0x34, 0x07, 0x3f, 0x9d, - 0x87, 0x6b, 0x39, 0x22, 0xe4, 0xef, 0xff, 0xf0, - }; - const uint8_t expected_tag[] = { - 0xef, 0x4e, 0xa8, 0x24, 0x07, 0x65, 0x36, 0x12, - 0xb1, 0xde, 0x7e, 0x23, 0xda, 0xea, 0x7c, 0x6b, - }; - - uint8_t *plaintext = malloc(SZ); - TEST_ASSERT_NOT_NULL(plaintext); - - memset(plaintext, 0xAA, SZ); - memset(iv, 0xEE, 16); - memset(key, 0x44, 16); - memset(aad, 0x76, 16); - - gcm_test_cfg_t cfg = { - .plaintext = plaintext, - .plaintext_length = SZ, - .iv = iv, - .iv_length = sizeof(iv), - .key = key, - .key_bits = 8 * sizeof(key), - .aad_buf = aad, - .aad_length = sizeof(aad), - .tag_len = 16 - }; - - gcm_test_expected_res_t res = { - .expected_tag = expected_tag, - .ciphertext_last_block = expected_last_block, - }; - - gcm_test(&cfg, &res, GCM_TEST_CRYPT_N_TAG); - gcm_test(&cfg, &res, GCM_TEST_START_UPDATE_FINISH); - free(plaintext); -} - -#endif /* CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER */ diff --git a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c b/components/mbedtls/test_apps/main/test_psa_ecdsa.c similarity index 53% rename from components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c rename to components/mbedtls/test_apps/main/test_psa_ecdsa.c index ba7df72bde..d714df6981 100644 --- a/components/mbedtls/test_apps/main/test_mbedtls_ecdsa.c +++ b/components/mbedtls/test_apps/main/test_psa_ecdsa.c @@ -1,6 +1,6 @@ /* mbedTLS Elliptic Curve Digital Signature performance tests * - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,12 +9,10 @@ #include #include #include -#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS -#include -#include -#include -#include + #include "psa/crypto.h" +#include "psa_crypto_driver_esp_ecdsa_contexts.h" +#include "psa_crypto_driver_esp_ecdsa.h" #include "hal/efuse_ll.h" #include "esp_efuse.h" @@ -26,7 +24,6 @@ #include "esp_heap_caps.h" #include "crypto_performance.h" -#include "ecdsa/ecdsa_alt.h" #if SOC_KEY_MANAGER_SUPPORTED #include "esp_key_mgr.h" #include "hal/key_mgr_ll.h" @@ -62,6 +59,8 @@ #define ECDSA_P192_HASH_COMPONENT_LEN 24 #define ECDSA_P256_HASH_COMPONENT_LEN 32 +#define ECDSA_UNCOMPRESSED_POINT_FORMAT 0x04 + __attribute__((unused)) static const char * TAG = "mbedtls_test"; /* @@ -172,106 +171,73 @@ const uint8_t ecdsa192_pub_y[] = { 0x23, 0xae, 0x7e, 0x0f, 0x1f, 0x4d, 0x69, 0xd5 }; -void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8_t *r_comp, const uint8_t *s_comp, +void test_ecdsa_verify(esp_ecdsa_curve_t curve, const uint8_t *hash, const uint8_t *r_comp, const uint8_t *s_comp, const uint8_t *pub_x, const uint8_t *pub_y) { - size_t hash_len = HASH_LEN; + size_t hash_len = 0; int64_t elapsed_time; - mbedtls_mpi r, s; - - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - - mbedtls_ecdsa_context ecdsa_context; - mbedtls_ecdsa_init(&ecdsa_context); - - mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), id); - size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P); - - TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&r, r_comp, plen)); - TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&s, s_comp, plen)); - - TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), pub_x, plen)); - TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), pub_y, plen)); - TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1)); - + size_t plen; psa_key_id_t key_id; psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; - if (id != MBEDTLS_ECP_DP_SECP192R1) { - psa_key_type_t curve_family = PSA_ECC_FAMILY_SECP_R1; - psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve_family)); - if (id == MBEDTLS_ECP_DP_SECP256R1) { - psa_set_key_bits(&key_attr, 256); - } - #if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (id == MBEDTLS_ECP_DP_SECP384R1) { - psa_set_key_bits(&key_attr, 384); - } - #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ - psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH); - psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); - uint8_t psa_key[2 * plen + 1]; - psa_key[0] = 0x04; // Uncompressed point indicator - memcpy(&psa_key[1], pub_x, plen); - memcpy(&psa_key[1 + plen], pub_y, plen); - - psa_status_t status = psa_import_key(&key_attr, psa_key, sizeof(psa_key), &key_id); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - } - - if (id == MBEDTLS_ECP_DP_SECP192R1 || id == MBEDTLS_ECP_DP_SECP256R1) { - hash_len = HASH_LEN; - } + switch (curve) { + case ESP_ECDSA_CURVE_SECP192R1: + plen = 192; + hash_len = HASH_LEN; + break; + case ESP_ECDSA_CURVE_SECP256R1: + plen = 256; + hash_len = HASH_LEN; + break; #if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (id == MBEDTLS_ECP_DP_SECP384R1) { - hash_len = HASH_LEN_P384; - } + case ESP_ECDSA_CURVE_SECP384R1: + plen = 384; + hash_len = HASH_LEN_P384; + break; #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ + default: + TEST_FAIL_MESSAGE("Invalid curve"); + break; + } + + psa_set_key_bits(&key_attr, plen); + size_t plen_bytes = plen / 8; + + uint8_t psa_key[2 * MAX_ECDSA_COMPONENT_LEN + 1]; + size_t psa_key_len = 2 * plen_bytes + 1; + + psa_key[0] = ECDSA_UNCOMPRESSED_POINT_FORMAT; + + memcpy(psa_key + 1, pub_x, plen_bytes); + memcpy(psa_key + 1 + plen_bytes, pub_y, plen_bytes); + + psa_status_t status = psa_import_key(&key_attr, psa_key, psa_key_len, &key_id); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + uint8_t signature[2 * MAX_ECDSA_COMPONENT_LEN]; + memcpy(signature, r_comp, plen_bytes); + memcpy(signature + plen_bytes, s_comp, plen_bytes); 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)); + status = psa_verify_hash(key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash, hash_len, signature, 2 * plen_bytes); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); elapsed_time = ccomp_timer_stop(); - if (id == MBEDTLS_ECP_DP_SECP192R1) { + if (curve == ESP_ECDSA_CURVE_SECP192R1) { TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P192_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); - } else if (id == MBEDTLS_ECP_DP_SECP256R1) { + } else if (curve == ESP_ECDSA_CURVE_SECP256R1) { TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P256_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); } #if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (id == MBEDTLS_ECP_DP_SECP384R1) { + else if (curve == ESP_ECDSA_CURVE_SECP384R1) { TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P384_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); } #endif - - if (id != MBEDTLS_ECP_DP_SECP192R1) { - uint8_t signature[2 * plen]; - TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&r, signature, plen)); - TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&s, signature + plen, plen)); - - ccomp_timer_start(); - psa_status_t status = psa_verify_hash(key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash, hash_len, - signature, sizeof(signature)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - elapsed_time = ccomp_timer_stop(); - - if (id == MBEDTLS_ECP_DP_SECP192R1) { - TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P192_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); - } else if (id == MBEDTLS_ECP_DP_SECP256R1) { - TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P256_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); - } - #if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (id == MBEDTLS_ECP_DP_SECP384R1) { - TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P384_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time)); - } - #endif - psa_destroy_key(key_id); - psa_reset_key_attributes(&key_attr); - } - - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - mbedtls_ecdsa_free(&ecdsa_context); + psa_destroy_key(key_id); + psa_reset_key_attributes(&key_attr); } TEST_CASE("mbedtls ECDSA signature verification performance on SECP192R1", "[mbedtls]") @@ -281,8 +247,7 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP192R1", "[mbe TEST_IGNORE_MESSAGE("ECDSA is not supported"); } #endif - test_ecdsa_verify(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_r, ecdsa192_s, - ecdsa192_pub_x, ecdsa192_pub_y); + test_ecdsa_verify(ESP_ECDSA_CURVE_SECP192R1, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y); } TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbedtls]") @@ -292,8 +257,7 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbe TEST_IGNORE_MESSAGE("ECDSA is not supported"); } #endif - test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_r, ecdsa256_s, - ecdsa256_pub_x, ecdsa256_pub_y); + test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y); } #ifdef SOC_ECDSA_SUPPORT_CURVE_P384 @@ -304,14 +268,14 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP384R1", "[mbe TEST_IGNORE_MESSAGE("ECDSA is not supported"); } #endif - test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_r, ecdsa384_s, - ecdsa384_pub_x, ecdsa384_pub_y); + test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_r, ecdsa384_s, ecdsa384_pub_x, ecdsa384_pub_y); } #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ #endif /* CONFIG_MBEDTLS_HARDWARE_ECC */ #if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN +#define USE_ECDSA_KEY_FROM_KEY_MANAGER INT_MAX /* * This test assumes that ECDSA private key has been burnt in efuse. @@ -343,66 +307,76 @@ const uint8_t k1_ecdsa192_encrypt[] = { 0xde, 0xe9, 0x9c, 0x89, 0xf2, 0x3b, 0x29, 0xb7, 0x9e, 0x33, 0xec, 0x76, 0x75, 0x2f, 0x3e, 0xab, 0x61, 0x06, 0x4d, 0xea, 0x05, 0x2c, 0xc3, 0x29, 0x1c, 0x7f, 0xb7, 0x3d, 0xb8, 0x1c, 0xb2, 0x17, }; -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, int efuse_key_block) +void test_ecdsa_sign(esp_ecdsa_curve_t curve, const uint8_t *hash, const uint8_t *pub_x, const uint8_t *pub_y, bool is_deterministic, int efuse_key_block) { size_t hash_len = HASH_LEN; - uint8_t r_be[MAX_ECDSA_COMPONENT_LEN] = {0}; - uint8_t s_be[MAX_ECDSA_COMPONENT_LEN] = {0}; + uint8_t signature[2 * MAX_ECDSA_COMPONENT_LEN]; + size_t signature_len = 0; + size_t plen = 0; + psa_algorithm_t sha_alg = 0; - mbedtls_mpi r, s; - mbedtls_mpi key_mpi; - - mbedtls_mpi_init(&r); - mbedtls_mpi_init(&s); - - mbedtls_ecdsa_context ecdsa_context; - mbedtls_ecdsa_init(&ecdsa_context); - - if (id == MBEDTLS_ECP_DP_SECP192R1) { - mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP192R1); - } else if (id == MBEDTLS_ECP_DP_SECP256R1) { - mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1); - } + switch (curve) { + case ESP_ECDSA_CURVE_SECP192R1: + hash_len = HASH_LEN; + plen = 192; + sha_alg = PSA_ALG_SHA_256; + break; + case ESP_ECDSA_CURVE_SECP256R1: + hash_len = HASH_LEN; + plen = 256; + sha_alg = PSA_ALG_SHA_256; + break; #if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (id == MBEDTLS_ECP_DP_SECP384R1) { - mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP384R1); - } -#endif - esp_ecdsa_privkey_load_mpi(&key_mpi, efuse_key_block); - - if (id == MBEDTLS_ECP_DP_SECP192R1 || id == MBEDTLS_ECP_DP_SECP256R1) { - hash_len = HASH_LEN; - } -#if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (id == MBEDTLS_ECP_DP_SECP384R1) { - hash_len = HASH_LEN_P384; - } + case ESP_ECDSA_CURVE_SECP384R1: + hash_len = HASH_LEN_P384; + plen = 384; + sha_alg = PSA_ALG_SHA_384; + break; #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ + default: + TEST_FAIL_MESSAGE("Invalid curve"); + break; + } - if (is_deterministic) { - mbedtls_ecdsa_sign_det_ext(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, hash_len, 0, NULL, NULL); + size_t plen_bytes = plen / 8; + psa_key_id_t priv_key_id = 0; + psa_key_attributes_t priv_attr = PSA_KEY_ATTRIBUTES_INIT; + + esp_ecdsa_opaque_key_t opaque_key = { + .curve = curve, + }; + + if (efuse_key_block == USE_ECDSA_KEY_FROM_KEY_MANAGER) { + opaque_key.use_km_key = true; } else { - mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, hash_len, NULL, NULL); + opaque_key.efuse_block = efuse_key_block; } - mbedtls_mpi_write_binary(&r, r_be, MAX_ECDSA_COMPONENT_LEN); - mbedtls_mpi_write_binary(&s, s_be, MAX_ECDSA_COMPONENT_LEN); + psa_algorithm_t alg = (is_deterministic ? PSA_ALG_DETERMINISTIC_ECDSA(sha_alg) : PSA_ALG_ECDSA(sha_alg)); - 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); - } 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); - } -#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); - } -#endif + // Set attributes for opaque private key + psa_set_key_type(&priv_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&priv_attr, plen); + psa_set_key_usage_flags(&priv_attr, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&priv_attr, alg); + psa_set_key_lifetime(&priv_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE); // Opaque key - mbedtls_mpi_free(&r); - mbedtls_mpi_free(&s); - mbedtls_mpi_free(&key_mpi); + // Import opaque key reference + psa_status_t status = psa_import_key(&priv_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id); + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_NOT_EQUAL(0, priv_key_id); + + status = psa_sign_hash(priv_key_id, + alg, + hash, hash_len, + signature, 2 * plen_bytes, + &signature_len); + + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_TRUE(signature_len == 2 * plen_bytes); + test_ecdsa_verify(curve, sha, signature, signature + plen_bytes, pub_x, pub_y); + psa_destroy_key(priv_key_id); + psa_reset_key_attributes(&priv_attr); } TEST_CASE("mbedtls ECDSA signature generation on SECP192R1", "[mbedtls][efuse_key]") @@ -410,7 +384,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP192R1", "[mbedtls][efuse_ke if (!ecdsa_ll_is_supported()) { TEST_IGNORE_MESSAGE("ECDSA is not supported"); } - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, SECP192R1_EFUSE_BLOCK); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, SECP192R1_EFUSE_BLOCK); } TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][efuse_key]") @@ -418,8 +392,9 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][efuse_ke if (!ecdsa_ll_is_supported()) { TEST_IGNORE_MESSAGE("ECDSA is not supported"); } - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, SECP256R1_EFUSE_BLOCK); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, SECP256R1_EFUSE_BLOCK); } + #ifdef SOC_ECDSA_SUPPORT_CURVE_P384 TEST_CASE("mbedtls ECDSA signature generation on SECP384R1", "[mbedtls][efuse_key]") { @@ -427,7 +402,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP384R1", "[mbedtls][efuse_ke TEST_IGNORE_MESSAGE("ECDSA is not supported"); } uint8_t efuse_key_block = HAL_ECDSA_COMBINE_KEY_BLOCKS(SECP384R1_EFUSE_BLOCK_HIGH, SECP384R1_EFUSE_BLOCK_LOW); - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, efuse_key_block); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, efuse_key_block); } #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ @@ -469,7 +444,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP192R1", "[mbedtls][key_mana } deploy_key_in_key_manager(k1_ecdsa192_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_192); - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, USE_ECDSA_KEY_FROM_KEY_MANAGER); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, USE_ECDSA_KEY_FROM_KEY_MANAGER); esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY); } @@ -483,7 +458,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][key_mana } deploy_key_in_key_manager(k1_ecdsa256_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_256); - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, USE_ECDSA_KEY_FROM_KEY_MANAGER); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, USE_ECDSA_KEY_FROM_KEY_MANAGER); esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY); } #endif /* SOC_KEY_MANAGER_SUPPORTED */ @@ -497,7 +472,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP192R1", "[mbe if (!ecdsa_ll_is_deterministic_mode_supported()) { ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported."); } else { - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, true, SECP192R1_EFUSE_BLOCK); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, true, SECP192R1_EFUSE_BLOCK); } } @@ -509,7 +484,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe if (!ecdsa_ll_is_deterministic_mode_supported()) { ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported."); } else { - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, true, SECP256R1_EFUSE_BLOCK); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, true, SECP256R1_EFUSE_BLOCK); } } @@ -520,7 +495,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP384R1", "[mbe TEST_IGNORE_MESSAGE("ECDSA is not supported"); } uint8_t efuse_key_block = HAL_ECDSA_COMBINE_KEY_BLOCKS(SECP384R1_EFUSE_BLOCK_HIGH, SECP384R1_EFUSE_BLOCK_LOW); - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, true, efuse_key_block); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, true, efuse_key_block); } #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ @@ -538,7 +513,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP192R1", "[mbe ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported."); } else { deploy_key_in_key_manager(k1_ecdsa192_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_192); - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, true, USE_ECDSA_KEY_FROM_KEY_MANAGER); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, true, USE_ECDSA_KEY_FROM_KEY_MANAGER); esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY); } } @@ -556,7 +531,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported."); } else { deploy_key_in_key_manager(k1_ecdsa256_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_256); - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, true, USE_ECDSA_KEY_FROM_KEY_MANAGER); + test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, true, USE_ECDSA_KEY_FROM_KEY_MANAGER); esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY); } } @@ -564,48 +539,70 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe #endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */ #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, int efuse_key_block) +void test_ecdsa_export_pubkey(esp_ecdsa_curve_t curve, const uint8_t *pub_x, const uint8_t *pub_y, int efuse_key_block) { - uint8_t export_pub_x[48] = {0}; - uint8_t export_pub_y[48] = {0}; - int len = 0; + uint8_t export_pub_key[1 + 2 * MAX_ECDSA_COMPONENT_LEN] = {0}; + size_t len = 0; - esp_ecdsa_pk_conf_t pk_conf = { - .grp_id = id, - .load_pubkey = true, + psa_key_id_t priv_key_id = 0; + psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT; + + esp_ecdsa_opaque_key_t opaque_key = { + .curve = curve, }; - if (efuse_key_block == USE_ECDSA_KEY_FROM_KEY_MANAGER) { - pk_conf.use_km_key = true; - } else { - pk_conf.efuse_block = efuse_key_block; - } + size_t plen = 0; + psa_algorithm_t sha_alg = 0; - if (id == MBEDTLS_ECP_DP_SECP192R1) { - len = 24; - } else if (id == MBEDTLS_ECP_DP_SECP256R1) { - len = 32; - } + switch (curve) { + case ESP_ECDSA_CURVE_SECP192R1: + plen = 192; + sha_alg = PSA_ALG_SHA_256; + break; + case ESP_ECDSA_CURVE_SECP256R1: + plen = 256; + sha_alg = PSA_ALG_SHA_256; + break; #if SOC_ECDSA_SUPPORT_CURVE_P384 - else if (id == MBEDTLS_ECP_DP_SECP384R1) { - len = 48; + case ESP_ECDSA_CURVE_SECP384R1: + plen = 384; + sha_alg = PSA_ALG_SHA_384; + break; +#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ + default: + TEST_FAIL_MESSAGE("Invalid curve"); + break; } -#endif + size_t plen_bytes = plen / 8; - mbedtls_pk_context key_ctx; + if (efuse_key_block == USE_ECDSA_KEY_FROM_KEY_MANAGER) { + opaque_key.use_km_key = true; + } else { + opaque_key.efuse_block = efuse_key_block; + } + // Set attributes for opaque private key + psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&key_attr, plen); + psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(sha_alg)); + psa_set_key_lifetime(&key_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE); // Opaque key - int ret = esp_ecdsa_set_pk_context(&key_ctx, &pk_conf); - TEST_ASSERT_EQUAL(0, ret); + // Import opaque key reference + psa_status_t status = psa_import_key(&key_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id); + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_NOT_EQUAL(0, priv_key_id); - mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(key_ctx); - mbedtls_mpi_write_binary(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), export_pub_x, len); - mbedtls_mpi_write_binary(&(keypair->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), export_pub_y, len); + status = psa_export_public_key(priv_key_id, export_pub_key, sizeof(export_pub_key), &len); - TEST_ASSERT_EQUAL_HEX8_ARRAY(pub_x, export_pub_x, len); - TEST_ASSERT_EQUAL_HEX8_ARRAY(pub_y, export_pub_y, len); + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_TRUE(len == 1 + 2 * plen_bytes); - /* Use esp_ecdsa_free_pk_context instead of manual cleanup to avoid memory leak */ - esp_ecdsa_free_pk_context(&key_ctx); + TEST_ASSERT_EQUAL_HEX8(ECDSA_UNCOMPRESSED_POINT_FORMAT, export_pub_key[0]); + TEST_ASSERT_EQUAL_HEX8_ARRAY(pub_x, export_pub_key + 1, plen_bytes); + TEST_ASSERT_EQUAL_HEX8_ARRAY(pub_y, export_pub_key + 1 + plen_bytes, plen_bytes); + + psa_destroy_key(priv_key_id); + psa_reset_key_attributes(&key_attr); } TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][efuse_key]") @@ -613,7 +610,7 @@ TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][efuse_key]" if (!ecdsa_ll_is_supported()) { TEST_IGNORE_MESSAGE("ECDSA is not supported"); } - test_ecdsa_export_pubkey(MBEDTLS_ECP_DP_SECP192R1, ecdsa192_pub_x, ecdsa192_pub_y, SECP192R1_EFUSE_BLOCK); + test_ecdsa_export_pubkey(ESP_ECDSA_CURVE_SECP192R1, ecdsa192_pub_x, ecdsa192_pub_y, SECP192R1_EFUSE_BLOCK); } TEST_CASE("mbedtls ECDSA export public key on SECP256R1", "[mbedtls][efuse_key]") @@ -621,7 +618,7 @@ TEST_CASE("mbedtls ECDSA export public key on SECP256R1", "[mbedtls][efuse_key]" if (!ecdsa_ll_is_supported()) { TEST_IGNORE_MESSAGE("ECDSA is not supported"); } - test_ecdsa_export_pubkey(MBEDTLS_ECP_DP_SECP256R1, ecdsa256_pub_x, ecdsa256_pub_y, SECP256R1_EFUSE_BLOCK); + test_ecdsa_export_pubkey(ESP_ECDSA_CURVE_SECP256R1, ecdsa256_pub_x, ecdsa256_pub_y, SECP256R1_EFUSE_BLOCK); } #ifdef SOC_ECDSA_SUPPORT_CURVE_P384 @@ -631,7 +628,7 @@ TEST_CASE("mbedtls ECDSA export public key on SECP384R1", "[mbedtls][efuse_key]" TEST_IGNORE_MESSAGE("ECDSA is not supported"); } uint8_t efuse_key_block = HAL_ECDSA_COMBINE_KEY_BLOCKS(SECP384R1_EFUSE_BLOCK_HIGH, SECP384R1_EFUSE_BLOCK_LOW); - test_ecdsa_export_pubkey(MBEDTLS_ECP_DP_SECP384R1, ecdsa384_pub_x, ecdsa384_pub_y, efuse_key_block); + test_ecdsa_export_pubkey(ESP_ECDSA_CURVE_SECP384R1, ecdsa384_pub_x, ecdsa384_pub_y, efuse_key_block); } #endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ @@ -646,7 +643,7 @@ TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][key_manager } deploy_key_in_key_manager(k1_ecdsa192_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_192); - test_ecdsa_export_pubkey(MBEDTLS_ECP_DP_SECP192R1, ecdsa192_pub_x, ecdsa192_pub_y, USE_ECDSA_KEY_FROM_KEY_MANAGER); + test_ecdsa_export_pubkey(ESP_ECDSA_CURVE_SECP192R1, ecdsa192_pub_x, ecdsa192_pub_y, USE_ECDSA_KEY_FROM_KEY_MANAGER); esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY); } @@ -660,9 +657,161 @@ TEST_CASE("mbedtls ECDSA export public key on SECP256R1", "[mbedtls][key_manager } deploy_key_in_key_manager(k1_ecdsa256_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_256); - test_ecdsa_export_pubkey(MBEDTLS_ECP_DP_SECP256R1, ecdsa256_pub_x, ecdsa256_pub_y, USE_ECDSA_KEY_FROM_KEY_MANAGER); + test_ecdsa_export_pubkey(ESP_ECDSA_CURVE_SECP256R1, ecdsa256_pub_x, ecdsa256_pub_y, USE_ECDSA_KEY_FROM_KEY_MANAGER); esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY); } #endif + +void test_ecdsa_sign_verify_import_export_error_codes(esp_ecdsa_curve_t curve, const uint8_t *hash, const uint8_t *r_comp, const uint8_t *s_comp, const uint8_t *pub_x, const uint8_t *pub_y, int efuse_key_block) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + size_t hash_len = 0; + size_t plen = 0; + psa_algorithm_t sha_alg = 0; + + switch (curve) { + case ESP_ECDSA_CURVE_SECP192R1: + hash_len = HASH_LEN; + plen = 192; + sha_alg = PSA_ALG_SHA_256; + break; + case ESP_ECDSA_CURVE_SECP256R1: + hash_len = HASH_LEN; + plen = 256; + sha_alg = PSA_ALG_SHA_256; + break; +#if SOC_ECDSA_SUPPORT_CURVE_P384 + case ESP_ECDSA_CURVE_SECP384R1: + hash_len = HASH_LEN_P384; + plen = 384; + sha_alg = PSA_ALG_SHA_384; + break; +#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */ + default: + TEST_FAIL_MESSAGE("Invalid curve"); + break; + } + + size_t plen_bytes = plen / 8; + + // 1. Signature Verification + psa_key_id_t pub_key_id; + psa_key_attributes_t pub_key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&pub_key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_usage_flags(&pub_key_attr, PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&pub_key_attr, PSA_ALG_ECDSA(sha_alg)); + psa_set_key_bits(&pub_key_attr, plen); + + uint8_t psa_key[2 * MAX_ECDSA_COMPONENT_LEN + 1]; + size_t psa_key_len = 2 * plen_bytes + 1; + + psa_key[0] = ECDSA_UNCOMPRESSED_POINT_FORMAT; + + memcpy(psa_key + 1, pub_x, plen_bytes); + memcpy(psa_key + 1 + plen_bytes, pub_y, plen_bytes); + + status = psa_import_key(&pub_key_attr, psa_key, psa_key_len, &pub_key_id); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + uint8_t signature[2 * MAX_ECDSA_COMPONENT_LEN]; + memcpy(signature, r_comp, plen_bytes); + memcpy(signature + plen_bytes, s_comp, plen_bytes); + + // 1.1 Incorrect signature buffer length + status = psa_verify_hash(pub_key_id, PSA_ALG_ECDSA(sha_alg), hash, hash_len, signature, 2 * plen_bytes - 1); + TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, status); + + psa_destroy_key(pub_key_id); + psa_reset_key_attributes(&pub_key_attr); + + // 2. Import Opaque Private Key + psa_key_id_t priv_key_id = 0; + psa_key_attributes_t priv_attr = PSA_KEY_ATTRIBUTES_INIT; + esp_ecdsa_opaque_key_t opaque_key = { 0 }; + opaque_key.curve = curve; + opaque_key.efuse_block = efuse_key_block; + + // Set attributes for opaque private key + psa_set_key_type(&priv_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&priv_attr, plen); + psa_set_key_usage_flags(&priv_attr, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&priv_attr, PSA_ALG_ECDSA(sha_alg)); + psa_set_key_lifetime(&priv_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE); // Opaque + + // incorrect opaque key buffer length + status = psa_import_key(&priv_attr, (uint8_t*) &opaque_key, sizeof(opaque_key) - 1, &priv_key_id); + TEST_ASSERT_EQUAL_HEX32(PSA_ERROR_BUFFER_TOO_SMALL, status); + + // incorrect curve + opaque_key.curve = curve + 1; + status = psa_import_key(&priv_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id); + TEST_ASSERT_EQUAL_HEX32(PSA_ERROR_INVALID_ARGUMENT, status); + + // incorrect efuse block + opaque_key.efuse_block = 9; // EFUSE_BLK_KEY5 [EFUSE_BLK_KEY0 to EFUSE_BLK_KEY4 are used for the ECDSA tests] + status = psa_import_key(&priv_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id); + TEST_ASSERT_EQUAL_HEX32(PSA_ERROR_INVALID_ARGUMENT, status); + + opaque_key.efuse_block = efuse_key_block; + opaque_key.curve = curve; + status = psa_import_key(&priv_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id); + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_NOT_EQUAL(0, priv_key_id); + + // Signature Generation + psa_algorithm_t alg = PSA_ALG_ECDSA(sha_alg); + + memset(signature, 0, sizeof(signature)); + size_t signature_len = 0; + + // Invalid hash length + status = psa_sign_hash(priv_key_id, + alg, + hash, hash_len - 1, + signature, 2 * plen_bytes, + &signature_len); + TEST_ASSERT_EQUAL_HEX32(PSA_ERROR_INVALID_ARGUMENT, status); + + // Invalid signature buffer length + status = psa_sign_hash(priv_key_id, + alg, + hash, hash_len, + signature, 2 * plen_bytes - 1, + &signature_len); + TEST_ASSERT_EQUAL_HEX32(PSA_ERROR_BUFFER_TOO_SMALL, status); + + status = psa_sign_hash(priv_key_id, + alg, + hash, hash_len, + signature, 2 * plen_bytes, + &signature_len); + + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + TEST_ASSERT_TRUE(signature_len == 2 * plen_bytes); + + + // Export Public Key + uint8_t export_pub_key[1 + 2 * MAX_ECDSA_COMPONENT_LEN] = {0}; + size_t export_pub_key_len = 0; + + // incorrect export public key buffer length + status = psa_export_public_key(priv_key_id, export_pub_key, (2 * plen_bytes), &export_pub_key_len); + TEST_ASSERT_EQUAL_HEX32(PSA_ERROR_BUFFER_TOO_SMALL, status); + + // correct export public key buffer length + status = psa_export_public_key(priv_key_id, export_pub_key, sizeof(export_pub_key), &export_pub_key_len); + TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status); + psa_destroy_key(priv_key_id); + psa_reset_key_attributes(&priv_attr); +} + +TEST_CASE("mbedtls ECDSA signature generation verification, import and export error codes", "[mbedtls][efuse_key]") +{ + if (!ecdsa_ll_is_supported()) { + TEST_IGNORE_MESSAGE("ECDSA is not supported"); + } + test_ecdsa_sign_verify_import_export_error_codes(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y, SECP256R1_EFUSE_BLOCK); +} + #endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */ #endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */ diff --git a/components/protocomm/test_apps/main/test_protocomm.c b/components/protocomm/test_apps/main/test_protocomm.c index a056597cc3..85e6931ad5 100644 --- a/components/protocomm/test_apps/main/test_protocomm.c +++ b/components/protocomm/test_apps/main/test_protocomm.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "psa/crypto_struct.h" -#include "psa/crypto_types.h" #include #include #include diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index c1675b6e5f..0548a3fa02 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -296,7 +296,7 @@ INPUT = \ $(PROJECT_PATH)/components/lwip/include/apps/esp_sntp.h \ $(PROJECT_PATH)/components/lwip/include/apps/ping/ping_sock.h \ $(PROJECT_PATH)/components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h \ - $(PROJECT_PATH)/components/mbedtls/port/include/ecdsa/ecdsa_alt.h \ + $(PROJECT_PATH)/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa_contexts.h \ $(PROJECT_PATH)/components/nvs_flash/include/nvs_flash.h \ $(PROJECT_PATH)/components/nvs_flash/include/nvs.h \ $(PROJECT_PATH)/components/nvs_flash/include/nvs_bootloader.h \ diff --git a/docs/en/api-reference/peripherals/ecdsa.rst b/docs/en/api-reference/peripherals/ecdsa.rst index c1fd7a1195..6a2e5a1602 100644 --- a/docs/en/api-reference/peripherals/ecdsa.rst +++ b/docs/en/api-reference/peripherals/ecdsa.rst @@ -134,7 +134,8 @@ The ECDSA peripheral in Mbed TLS stack is integrated by overriding the ECDSA sig For a particular TLS context, additional APIs have been supplied to populate certain fields (e.g., private key ctx) to differentiate routing to hardware. ESP-TLS layer integrates these APIs internally and hence no additional work is required at the application layer. However, for custom use-cases please refer to API details below. + API Reference ------------- -.. include-build-file:: inc/ecdsa_alt.inc +.. include-build-file:: inc/psa_crypto_driver_esp_ecdsa_contexts.inc diff --git a/docs/en/migration-guides/release-6.x/6.0/security.rst b/docs/en/migration-guides/release-6.x/6.0/security.rst index 4a7f17d18b..707e7354e0 100644 --- a/docs/en/migration-guides/release-6.x/6.0/security.rst +++ b/docs/en/migration-guides/release-6.x/6.0/security.rst @@ -26,7 +26,7 @@ ESP-IDF v6.0 updates to Mbed TLS v4.0, where **PSA Crypto is the primary cryptog - **Breaking change**: In Mbed TLS v4.0, **most legacy cryptography APIs have been removed** and PSA Crypto is the primary interface. If your application directly uses legacy ``mbedtls_*`` cryptography primitives, you may need to migrate to PSA Crypto APIs. - **Breaking change**: ``psa_crypto_init()`` must be called before any cryptographic operation, including indirect operations such as parsing keys/certificates or starting a TLS handshake. ESP-IDF initializes PSA during normal startup; however, code that runs earlier than the normal startup sequence must call ``psa_crypto_init()`` explicitly. -- **New API**: ``esp_ecdsa_free_pk_context(mbedtls_pk_context *key_ctx)`` was added (``ecdsa/ecdsa_alt.h``). If your application initializes a PK context with a hardware-backed ECDSA key using ``esp_ecdsa_set_pk_context()``, use ``esp_ecdsa_free_pk_context()`` to free it. With PSA-backed Mbed TLS v4.x, ``mbedtls_pk_free()`` does not deallocate the manually created keypair structure in this case. +- **Breaking change**: ``esp_ecdsa_load_pubkey()``, ``esp_ecdsa_privkey_load_mpi()``, ``esp_ecdsa_privkey_load_pk_context()``, ``esp_ecdsa_set_pk_context()``, ``esp_ecdsa_tee_load_pubkey()`` and ``esp_ecdsa_tee_set_pk_context()`` have been deprecated and removed. The legacy ``esp_ecdsa_pk_conf_t`` configuration is replaced by ``esp_ecdsa_opaque_key_t``, which represents an hardware-backed ECDSA opaque key. Applications can populate this structure and import it via ``psa_import_key()``, enabling all ECDSA operations through standard PSA Crypto APIs. - **Breaking change**: APIs that previously required an application-provided RNG callback (``f_rng``, ``p_rng``) have changed in Mbed TLS v4.0 to use the PSA RNG instead. Update application code to the new prototypes (for example X.509 write APIs, SSL cookie setup, and SSL ticket setup). - **Breaking change**: TLS 1.2 / DTLS 1.2 interoperability may be affected because Mbed TLS v4.0 removes support for key exchanges based on finite-field DHE and RSA key exchange without forward secrecy (and static ECDH). If a peer requires removed suites, TLS connections may fail; update server/client cipher suite configuration accordingly. - **Breaking change**: certificates/peers using elliptic curves of less than 250 bits (for example secp192r1/secp224r1) are no longer supported in certificates and in TLS. diff --git a/docs/sphinx-known-warnings.txt b/docs/sphinx-known-warnings.txt index 1d198b855d..816701f158 100644 --- a/docs/sphinx-known-warnings.txt +++ b/docs/sphinx-known-warnings.txt @@ -184,16 +184,6 @@ If declarator-id: struct esp_cam_ctlr_csi_config_t --------------------------------^ -ecdsa_alt.inc:line: WARNING: Error in declarator or parameters-and-qualifiers -If pointer to member declarator: - Invalid C++ declaration: Expected identifier in nested name. [error at 25] - union esp_ecdsa_pk_conf_t - -------------------------^ -If declarator-id: - Invalid C++ declaration: Expected identifier in nested name. [error at 25] - union esp_ecdsa_pk_conf_t - -------------------------^ - i2c_master.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/peripherals/i2c:line. Declaration is '.. cpp:member:: uint8_t * data'. isp_types.inc:line: WARNING: Error in declarator or parameters-and-qualifiers diff --git a/docs/zh_CN/api-reference/peripherals/ecdsa.rst b/docs/zh_CN/api-reference/peripherals/ecdsa.rst index d6fe18bfa3..00dabc7c0b 100644 --- a/docs/zh_CN/api-reference/peripherals/ecdsa.rst +++ b/docs/zh_CN/api-reference/peripherals/ecdsa.rst @@ -137,4 +137,4 @@ ECDSA 外设依靠硬件真随机数生成器 (TRNG) 来满足其内部熵要求 API 参考 -------- -.. include-build-file:: inc/ecdsa_alt.inc +.. include-build-file:: inc/psa_crypto_driver_esp_ecdsa_contexts.inc diff --git a/docs/zh_CN/migration-guides/release-6.x/6.0/security.rst b/docs/zh_CN/migration-guides/release-6.x/6.0/security.rst index 090b493247..26621ffa9a 100644 --- a/docs/zh_CN/migration-guides/release-6.x/6.0/security.rst +++ b/docs/zh_CN/migration-guides/release-6.x/6.0/security.rst @@ -26,7 +26,7 @@ ESP-IDF v6.0 已升级至 Mbed TLS v4.0,**PSA Crypto 成为主要加密接口* - **重大变更**:在 Mbed TLS v4.0 中,**大多数传统加密 API 已被移除**,PSA Crypto 成为主要接口。如果应用直接使用传统的 ``mbedtls_*`` 加密原语,则无法直接兼容,需迁移到 PSA Crypto API。 - **重大变更**:在执行任何加密操作之前(包括解析密钥/证书或启动 TLS 握手等操作),必须调用 ``psa_crypto_init()``。ESP-IDF 在常规启动过程中会初始化 PSA,因此大多数应用保持兼容;但对于早于常规启动流程运行的代码,需显式调用 ``psa_crypto_init()``。 -- **新增 API**:新增 ``esp_ecdsa_free_pk_context(mbedtls_pk_context *key_ctx)``,参见 ``ecdsa/ecdsa_alt.h``。如果应用使用 ``esp_ecdsa_set_pk_context()`` 初始化包含硬件 ECDSA 密钥的 PK 上下文,应使用 ``esp_ecdsa_free_pk_context()`` 进行释放。在基于 PSA 的 Mbed TLS v4.x 中,``mbedtls_pk_free()`` 无法释放此种情况下手动创建的密钥对结构。 +- **重大变更**:``esp_ecdsa_load_pubkey()``、``esp_ecdsa_privkey_load_mpi()``、``esp_ecdsa_privkey_load_pk_context()``、``esp_ecdsa_set_pk_context()``、``esp_ecdsa_tee_load_pubkey()`` 和 ``esp_ecdsa_tee_set_pk_context()`` 已被弃用并移除。旧的 ``esp_ecdsa_pk_conf_t`` 配置已被 ``esp_ecdsa_opaque_key_t`` 取代,后者支持由 ECDSA 硬件提供的不透明密钥。应用程序可以配置该结构体并通过 ``psa_import_key()`` 导入,从而使用标准 PSA Crypto API 启用所有 ECDSA 操作。 - **重大变更**:原需应用提供 RNG 回调(``f_rng``、``p_rng``)的 API,在 Mbed TLS v4.0 中已改为使用 PSA RNG。使用旧函数原型的代码将无法直接兼容,需要更新为新的 API 定义(例如 X.509 写入 API、SSL cookie 设置以及 SSL ticket 设置)。 - **重大变更**:TLS 1.2 / DTLS 1.2 的互操作性可能受到影响,因为 Mbed TLS v4.0 移除了对基于有限域 DHE、无前向保密的 RSA 密钥交换(以及静态 ECDH)的支持。如果对等端需要使用已移除的密码套件,TLS 连接将不兼容并可能失败;需相应更新服务器或客户端的密码套件配置。 - **重大变更**:证书或对等端中使用的椭圆曲线位数小于 250 位(例如 secp192r1/secp224r1)已不再受支持。 diff --git a/examples/security/tee/tee_secure_storage/main/tee_main.c b/examples/security/tee/tee_secure_storage/main/tee_main.c index c1211de891..cb6fb13bfc 100644 --- a/examples/security/tee/tee_secure_storage/main/tee_main.c +++ b/examples/security/tee/tee_secure_storage/main/tee_main.c @@ -1,7 +1,7 @@ /* * TEE Secure Storage example * - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -16,6 +16,7 @@ #include "freertos/task.h" #include "psa/crypto.h" +#include "psa_crypto_driver_esp_ecdsa.h" #include "esp_tee_sec_storage.h" #include "secure_service_num.h" @@ -34,9 +35,9 @@ static const char *message = "Lorem ipsum dolor sit amet, consectetur adipiscing static const char *TAG = "example_tee_sec_stg"; -static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_ecdsa_pubkey_t *pubkey, const esp_tee_sec_storage_ecdsa_sign_t *sign) +static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const uint8_t *pub_key, size_t pub_key_len, const uint8_t *signature, size_t signature_len) { - if (pubkey == NULL || digest == NULL || sign == NULL) { + if (pub_key == NULL || pub_key_len == 0 || digest == NULL || len == 0 || signature == NULL || signature_len == 0) { return ESP_ERR_INVALID_ARG; } @@ -46,29 +47,24 @@ static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, esp_err_t err = ESP_FAIL; - psa_key_id_t key_id = 0; - psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); - psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH); - psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); + psa_key_id_t pub_key_id = 0; + psa_key_attributes_t pub_key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type(&pub_key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_usage_flags(&pub_key_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH); + psa_set_key_algorithm(&pub_key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256)); - uint8_t pub_key[2 * ECDSA_SECP256R1_KEY_LEN + 1]; - pub_key[0] = 0x04; - memcpy(pub_key + 1, pubkey->pub_x, ECDSA_SECP256R1_KEY_LEN); - memcpy(pub_key + 1 + ECDSA_SECP256R1_KEY_LEN, pubkey->pub_y, ECDSA_SECP256R1_KEY_LEN); - - psa_status_t status = psa_import_key(&key_attributes, pub_key, sizeof(pub_key), &key_id); + psa_status_t status = psa_import_key(&pub_key_attr, pub_key, pub_key_len, &pub_key_id); if (status != PSA_SUCCESS) { goto exit; } - status = psa_verify_hash(key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), digest, len, sign->signature, sizeof(sign->signature)); + status = psa_verify_hash(pub_key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), digest, len, signature, signature_len); if (status != PSA_SUCCESS) { goto exit; } - psa_destroy_key(key_id); - psa_reset_key_attributes(&key_attributes); + psa_destroy_key(pub_key_id); + psa_reset_key_attributes(&pub_key_attr); err = ESP_OK; @@ -107,23 +103,46 @@ static void example_tee_sec_stg_sign_verify(void *pvParameter) goto exit; } - esp_tee_sec_storage_ecdsa_sign_t sign = {}; - err = esp_tee_sec_storage_ecdsa_sign(&cfg, msg_digest, msg_digest_len, &sign); - if (err != ESP_OK) { + esp_ecdsa_opaque_key_t opaque_key = { + .curve = ESP_ECDSA_CURVE_SECP256R1, + .tee_key_id = cfg.id, + }; + + psa_key_id_t priv_key_id = 0; + psa_key_attributes_t priv_key_attr = PSA_KEY_ATTRIBUTES_INIT; + psa_algorithm_t alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256); + + psa_set_key_type(&priv_key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)); + psa_set_key_bits(&priv_key_attr, ECDSA_SECP256R1_KEY_LEN * 8); + psa_set_key_usage_flags(&priv_key_attr, PSA_KEY_USAGE_SIGN_HASH); + psa_set_key_algorithm(&priv_key_attr, alg); + psa_set_key_lifetime(&priv_key_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE); + + status = psa_import_key(&priv_key_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id); + if (status != PSA_SUCCESS) { + ESP_LOGE(TAG, "Failed to import private key!"); + goto exit; + } + + uint8_t signature[2 * ECDSA_SECP256R1_KEY_LEN]; + size_t signature_len = 0; + status = psa_sign_hash(priv_key_id, alg, msg_digest, msg_digest_len, signature, sizeof(signature), &signature_len); + if (status != PSA_SUCCESS) { ESP_LOGE(TAG, "Failed to generate signature!"); goto exit; } - ESP_LOG_BUFFER_HEX("Signature", &sign, sizeof(sign)); + ESP_LOG_BUFFER_HEX("Signature", signature, signature_len); - esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {}; - err = esp_tee_sec_storage_ecdsa_get_pubkey(&cfg, &pubkey); - if (err != ESP_OK) { + uint8_t pub_key[2 * ECDSA_SECP256R1_KEY_LEN + 1]; + size_t pub_key_len = 0; + status = psa_export_public_key(priv_key_id, pub_key, sizeof(pub_key), &pub_key_len); + if (status != PSA_SUCCESS) { ESP_LOGE(TAG, "Failed to fetch public-key!"); goto exit; } - err = verify_ecdsa_secp256r1_sign(msg_digest, msg_digest_len, &pubkey, &sign); + err = verify_ecdsa_secp256r1_sign(msg_digest, msg_digest_len, pub_key, pub_key_len, signature, signature_len); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to verify signature!"); goto exit; @@ -132,6 +151,8 @@ static void example_tee_sec_stg_sign_verify(void *pvParameter) ESP_LOGI(TAG, "Signature verified successfully!"); exit: + psa_destroy_key(priv_key_id); + psa_reset_key_attributes(&priv_key_attr); vTaskDelete(NULL); }