mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
Merge branch 'feat/opaque_ecdsa_drivers_v6.0' into 'release/v6.0'
Opaque ECDSA driver (v6.0) See merge request espressif/esp-idf!45432
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -492,7 +492,13 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
|
||||
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(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_algorithm_t ecdsa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
|
||||
|
||||
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC
|
||||
ecdsa_alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256);
|
||||
#endif
|
||||
|
||||
psa_set_key_algorithm(&key_attributes, ecdsa_alg);
|
||||
|
||||
uint8_t *priv_key = NULL;
|
||||
size_t priv_key_len = 0;
|
||||
@@ -517,7 +523,7 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
|
||||
|
||||
ESP_LOGD(TAG, "Generating ECDSA signature...");
|
||||
size_t signature_len = 0;
|
||||
status = psa_sign_hash(key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash, hlen, out_sign->signature, sizeof(out_sign->signature), &signature_len);
|
||||
status = psa_sign_hash(key_id, ecdsa_alg, hash, hlen, out_sign->signature, sizeof(out_sign->signature), &signature_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
err = ESP_FAIL;
|
||||
ESP_LOGE(TAG, "Failed to generate ECDSA signature: %ld", status);
|
||||
|
||||
@@ -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,93 @@ 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);
|
||||
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC
|
||||
alg = PSA_ALG_DETERMINISTIC_ECDSA(sha_alg);
|
||||
#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC */
|
||||
|
||||
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);
|
||||
|
||||
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC
|
||||
uint8_t signature_det_verify[2 * ECDSA_SECP384R1_KEY_LEN];
|
||||
size_t signature_det_verify_len = 0;
|
||||
|
||||
status = psa_sign_hash(priv_key_id,
|
||||
alg,
|
||||
sha, sha_len,
|
||||
signature_det_verify, 2 * key_len,
|
||||
&signature_det_verify_len);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||
TEST_ASSERT_EQUAL(signature_det_verify_len, signature_len);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(signature, signature_det_verify, signature_len);
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
@@ -418,47 +418,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()
|
||||
|
||||
@@ -511,10 +492,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
|
||||
@@ -532,7 +509,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
|
||||
|
||||
@@ -58,6 +58,12 @@
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECDSA_C
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_ECDSA_DETERMINISTIC
|
||||
#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1
|
||||
#else
|
||||
#undef PSA_WANT_ALG_DETERMINISTIC_ECDSA
|
||||
#endif
|
||||
|
||||
#if CONFIG_MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#endif
|
||||
|
||||
@@ -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"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,867 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
#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 && ((!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);
|
||||
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 && ((!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 */
|
||||
|
||||
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 && ((!defined(CONFIG_IDF_TARGET_ESP32P4) && SOC_EFUSE_ECDSA_KEY_P384) || EFUSE_LL_HAS_ECDSA_KEY_P384)
|
||||
#if 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 /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES && ((!defined(CONFIG_IDF_TARGET_ESP32P4) && SOC_EFUSE_ECDSA_KEY_P384) || EFUSE_LL_HAS_ECDSA_KEY_P384) */
|
||||
|
||||
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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#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 */
|
||||
+337
-225
@@ -1,6 +1,6 @@
|
||||
/* mbedTLS Elliptic Curve Digital Signature performance tests
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -9,12 +9,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include <esp_log.h>
|
||||
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
|
||||
#include <mbedtls/private/ecdh.h>
|
||||
#include <mbedtls/private/ecdsa.h>
|
||||
#include <mbedtls/private/pk_private.h>
|
||||
#include <mbedtls/error.h>
|
||||
|
||||
#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"
|
||||
@@ -25,7 +23,6 @@
|
||||
#include "unity.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
#include "ecdsa/ecdsa_alt.h"
|
||||
#if SOC_KEY_MANAGER_SUPPORTED
|
||||
#include "esp_key_mgr.h"
|
||||
#include "hal/key_mgr_ll.h"
|
||||
@@ -61,6 +58,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";
|
||||
|
||||
/*
|
||||
@@ -171,106 +170,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]")
|
||||
@@ -280,8 +246,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]")
|
||||
@@ -291,8 +256,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
|
||||
@@ -303,14 +267,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.
|
||||
@@ -342,66 +306,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]")
|
||||
@@ -409,7 +383,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]")
|
||||
@@ -417,16 +391,14 @@ 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]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
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 */
|
||||
|
||||
@@ -460,29 +432,23 @@ static void deploy_key_in_key_manager(const uint8_t *k1_encrypted, esp_key_mgr_k
|
||||
|
||||
TEST_CASE("mbedtls ECDSA signature generation on SECP192R1", "[mbedtls][key_manager_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
if (!key_mgr_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("Key manager is not supported");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][key_manager_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
if (!key_mgr_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("Key manager is not supported");
|
||||
}
|
||||
|
||||
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 */
|
||||
@@ -490,45 +456,33 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][key_mana
|
||||
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
|
||||
TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP192R1", "[mbedtls][efuse_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbedtls][efuse_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP384R1", "[mbedtls][efuse_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
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 */
|
||||
|
||||
#if SOC_KEY_MANAGER_SUPPORTED
|
||||
TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP192R1", "[mbedtls][key_manager_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
if (!key_mgr_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("Key manager is not supported");
|
||||
}
|
||||
@@ -537,25 +491,18 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbedtls][key_manager_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
if (!key_mgr_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("Key manager is not supported");
|
||||
}
|
||||
|
||||
if (!ecdsa_ll_is_deterministic_mode_supported()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -563,48 +510,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]")
|
||||
@@ -612,7 +581,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]")
|
||||
@@ -620,48 +589,191 @@ 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
|
||||
TEST_CASE("mbedtls ECDSA export public key on SECP384R1", "[mbedtls][efuse_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
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 */
|
||||
|
||||
#if SOC_KEY_MANAGER_SUPPORTED
|
||||
TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][key_manager_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
if (!key_mgr_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("Key manager is not supported");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TEST_CASE("mbedtls ECDSA export public key on SECP256R1", "[mbedtls][key_manager_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
if (!key_mgr_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("Key manager is not supported");
|
||||
}
|
||||
|
||||
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 */
|
||||
@@ -4,8 +4,6 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "psa/crypto_struct.h"
|
||||
#include "psa/crypto_types.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
Reference in New Issue
Block a user