mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(mbedtls/ecdsa): Introduce PSA ECDSA driver
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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -24,8 +24,8 @@
|
|||||||
#include "mbedtls/esp_mbedtls_dynamic.h"
|
#include "mbedtls/esp_mbedtls_dynamic.h"
|
||||||
#include "mbedtls/private/pk_private.h"
|
#include "mbedtls/private/pk_private.h"
|
||||||
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||||
#include "mbedtls/ecp.h"
|
#include "psa_crypto_driver_esp_ecdsa.h"
|
||||||
#include "ecdsa/ecdsa_alt.h"
|
#include "hal/ecdsa_types.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
|
#ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
|
||||||
@@ -66,23 +66,31 @@ static mbedtls_x509_crt *global_cacert = NULL;
|
|||||||
|
|
||||||
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||||
/**
|
/**
|
||||||
* @brief Convert ESP-TLS ECDSA curve enum to mbedTLS group ID
|
* @brief Convert ESP-TLS ECDSA curve enum to ESP ECDSA curve
|
||||||
* @param curve ESP-TLS ECDSA curve enum value
|
* @param tls_curve ESP-TLS ECDSA curve enum value
|
||||||
* @param grp_id Pointer to store the converted mbedTLS group ID
|
* @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
|
* @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:
|
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;
|
break;
|
||||||
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
case ESP_TLS_ECDSA_CURVE_SECP384R1:
|
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;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
|
*curve_bits = 0;
|
||||||
|
*sha_alg = 0;
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@@ -513,12 +521,14 @@ void esp_mbedtls_cleanup(esp_tls_t *tls)
|
|||||||
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||||
/* In mbedtls v4.0, ECDSA keys require manual cleanup of the keypair structure */
|
/* In mbedtls v4.0, ECDSA keys require manual cleanup of the keypair structure */
|
||||||
if (mbedtls_pk_get_type(&tls->clientkey) == MBEDTLS_PK_ECDSA) {
|
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);
|
mbedtls_ecp_keypair *keypair = tls->clientkey.MBEDTLS_PRIVATE(pk_ctx);
|
||||||
if (keypair != NULL) {
|
if (keypair != NULL) {
|
||||||
mbedtls_ecp_keypair_free(keypair);
|
mbedtls_ecp_keypair_free(keypair);
|
||||||
mbedtls_free(keypair);
|
mbedtls_free(keypair);
|
||||||
keypair = NULL;
|
keypair = NULL;
|
||||||
}
|
}
|
||||||
|
psa_destroy_key(tls->clientkey.MBEDTLS_PRIVATE(priv_id));
|
||||||
tls->clientkey.MBEDTLS_PRIVATE(pk_ctx) = NULL;
|
tls->clientkey.MBEDTLS_PRIVATE(pk_ctx) = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,6 +540,7 @@ void esp_mbedtls_cleanup(esp_tls_t *tls)
|
|||||||
mbedtls_free(keypair);
|
mbedtls_free(keypair);
|
||||||
keypair = NULL;
|
keypair = NULL;
|
||||||
}
|
}
|
||||||
|
psa_destroy_key(tls->serverkey.MBEDTLS_PRIVATE(priv_id));
|
||||||
tls->serverkey.MBEDTLS_PRIVATE(pk_ctx) = NULL;
|
tls->serverkey.MBEDTLS_PRIVATE(pk_ctx) = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -599,23 +610,51 @@ static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||||
if (tls->use_ecdsa_peripheral) {
|
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
|
// 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_esp_ecdsa_curve(tls->ecdsa_curve, &curve, &curve_bits, &sha_alg);
|
||||||
esp_err_t esp_ret = esp_tls_ecdsa_curve_to_mbedtls_group_id(tls->ecdsa_curve, &grp_id);
|
if (esp_ret != ESP_OK || curve == ESP_ECDSA_CURVE_MAX || curve_bits == 0 || sha_alg == 0) {
|
||||||
if (esp_ret != ESP_OK) {
|
|
||||||
return esp_ret;
|
return esp_ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_ecdsa_pk_conf_t conf = {
|
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
|
||||||
.grp_id = grp_id,
|
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,
|
.efuse_block = tls->ecdsa_efuse_blk,
|
||||||
|
.use_km_key = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
ret = esp_ecdsa_set_pk_context(pki->pk_key, &conf);
|
// Import opaque key reference
|
||||||
if (ret != ESP_OK) {
|
psa_status_t status = psa_import_key(&key_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id);
|
||||||
ESP_LOGE(TAG, "Failed to initialize pk context for ecdsa peripheral with the key stored in efuse block %d", tls->ecdsa_efuse_blk);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
psa_reset_key_attributes(&key_attr);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (pki->privkey_pem_buf != NULL) {
|
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;
|
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
|
// Create dynamic ciphersuite array based on curve
|
||||||
static int ecdsa_peripheral_supported_ciphersuites[4] = {0}; // Max 4 elements
|
static int ecdsa_peripheral_supported_ciphersuites[4] = {0}; // Max 4 elements
|
||||||
int ciphersuite_count = 0;
|
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;
|
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;
|
ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_MBEDTLS_SSL_PROTO_TLS1_3
|
#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;
|
ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS1_3_AES_256_GCM_SHA384;
|
||||||
} else {
|
} else {
|
||||||
ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS1_3_AES_128_GCM_SHA256;
|
ecdsa_peripheral_supported_ciphersuites[ciphersuite_count++] = MBEDTLS_TLS1_3_AES_128_GCM_SHA256;
|
||||||
|
|||||||
@@ -8,18 +8,18 @@
|
|||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "esp_partition.h"
|
#include "esp_partition.h"
|
||||||
#include "ecdsa/ecdsa_alt.h"
|
|
||||||
|
|
||||||
#include "esp_tee.h"
|
#include "esp_tee.h"
|
||||||
#include "esp_tee_sec_storage.h"
|
#include "esp_tee_sec_storage.h"
|
||||||
#include "secure_service_num.h"
|
#include "secure_service_num.h"
|
||||||
#include "psa/initial_attestation.h"
|
#include "psa/initial_attestation.h"
|
||||||
|
#include "psa/crypto.h"
|
||||||
|
#include "psa_crypto_driver_esp_ecdsa.h"
|
||||||
|
|
||||||
#include "esp_random.h"
|
#include "esp_random.h"
|
||||||
#include "nvs.h"
|
#include "nvs.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "ecdsa/ecdsa_alt.h"
|
|
||||||
|
|
||||||
/* Note: negative value here so that assert message prints a grep-able
|
/* Note: negative value here so that assert message prints a grep-able
|
||||||
error hex value (mbedTLS uses -N for error codes) */
|
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
|
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;
|
esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_TYPE_MAX;
|
||||||
size_t key_len = 0;
|
size_t key_len = 0;
|
||||||
size_t sha_len = SHA256_DIGEST_SZ;
|
size_t sha_len = SHA256_DIGEST_SZ;
|
||||||
|
|
||||||
switch (gid) {
|
psa_algorithm_t sha_alg = 0;
|
||||||
case MBEDTLS_ECP_DP_SECP256R1:
|
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_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1;
|
||||||
key_len = ECDSA_SECP256R1_KEY_LEN;
|
key_len = ECDSA_SECP256R1_KEY_LEN;
|
||||||
|
sha_alg = PSA_ALG_SHA_256;
|
||||||
break;
|
break;
|
||||||
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
|
#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_type = ESP_SEC_STG_KEY_ECDSA_SECP384R1;
|
||||||
key_len = ECDSA_SECP384R1_KEY_LEN;
|
key_len = ECDSA_SECP384R1_KEY_LEN;
|
||||||
sha_len = SHA384_DIGEST_SZ;
|
sha_len = SHA384_DIGEST_SZ;
|
||||||
|
sha_alg = PSA_ALG_SHA_384;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
ESP_LOGE(TAG, "Unsupported curve ID: %d", gid);
|
ESP_LOGE(TAG, "Unsupported curve ID: %d", curve);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const char *key_id = "ecdsa_k0";
|
const char *key_id = "ecdsa_k0";
|
||||||
@@ -523,53 +532,75 @@ static void test_ecdsa_sign(mbedtls_ecp_group_id gid)
|
|||||||
esp_err_t err = esp_tee_sec_storage_clear_key(key_cfg.id);
|
esp_err_t err = esp_tee_sec_storage_clear_key(key_cfg.id);
|
||||||
TEST_ASSERT_TRUE(err == ESP_OK || err == ESP_ERR_NOT_FOUND);
|
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));
|
TEST_ESP_OK(esp_tee_sec_storage_gen_key(&key_cfg));
|
||||||
|
|
||||||
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {};
|
psa_key_id_t priv_key_id = 0;
|
||||||
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey));
|
psa_key_attributes_t priv_key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
|
|
||||||
mbedtls_mpi r, s;
|
psa_key_id_t pub_key_id = 0;
|
||||||
mbedtls_mpi_init(&r);
|
psa_key_attributes_t pub_key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
mbedtls_mpi_init(&s);
|
|
||||||
|
|
||||||
mbedtls_ecdsa_context ecdsa_context;
|
esp_ecdsa_opaque_key_t opaque_key = {
|
||||||
mbedtls_ecdsa_init(&ecdsa_context);
|
.curve = curve,
|
||||||
|
|
||||||
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,
|
|
||||||
.tee_key_id = key_id,
|
.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);
|
psa_algorithm_t alg = PSA_ALG_ECDSA(sha_alg);
|
||||||
mbedtls_mpi key_mpi = keypair->MBEDTLS_PRIVATE(d);
|
|
||||||
|
|
||||||
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 = {};
|
status = psa_import_key(&priv_key_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id);
|
||||||
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));
|
|
||||||
|
|
||||||
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);
|
size_t pub_key_len = 0;
|
||||||
mbedtls_ecdsa_free(&ecdsa_context);
|
status = psa_export_public_key(priv_key_id, export_pub_key, sizeof(export_pub_key), &pub_key_len);
|
||||||
mbedtls_mpi_free(&r);
|
|
||||||
mbedtls_mpi_free(&s);
|
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||||
|
TEST_ASSERT_EQUAL(pub_key_len, 1 + 2 * key_len);
|
||||||
|
|
||||||
|
status = psa_sign_hash(priv_key_id,
|
||||||
|
alg,
|
||||||
|
sha, sha_len,
|
||||||
|
signature, 2 * key_len,
|
||||||
|
&signature_len);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||||
|
TEST_ASSERT_EQUAL(signature_len, 2 * key_len);
|
||||||
|
|
||||||
|
psa_set_key_type(&pub_key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
|
||||||
|
psa_set_key_bits(&pub_key_attr, key_len * 8);
|
||||||
|
psa_set_key_usage_flags(&pub_key_attr, PSA_KEY_USAGE_VERIFY_HASH);
|
||||||
|
psa_set_key_algorithm(&pub_key_attr, alg);
|
||||||
|
psa_set_key_lifetime(&pub_key_attr, PSA_KEY_PERSISTENCE_VOLATILE);
|
||||||
|
|
||||||
|
status = psa_import_key(&pub_key_attr, export_pub_key, pub_key_len, &pub_key_id);
|
||||||
|
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||||
|
TEST_ASSERT_NOT_EQUAL(0, pub_key_id);
|
||||||
|
|
||||||
|
status = psa_verify_hash(pub_key_id, alg, sha, sha_len, signature, 2 * key_len);
|
||||||
|
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||||
|
|
||||||
TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id));
|
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_CASE("Test TEE Secure Storage - mbedtls ECDSA signing", "[mbedtls]")
|
||||||
{
|
{
|
||||||
test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1);
|
test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1);
|
||||||
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
|
#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
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
|
|||||||
|
|
||||||
if(esp_tee_build)
|
if(esp_tee_build)
|
||||||
include(${COMPONENT_DIR}/esp_tee/esp_tee_mbedtls.cmake)
|
include(${COMPONENT_DIR}/esp_tee/esp_tee_mbedtls.cmake)
|
||||||
return()
|
return()
|
||||||
|
|
||||||
elseif(BOOTLOADER_BUILD) # TODO: IDF-11673
|
elseif(BOOTLOADER_BUILD) # TODO: IDF-11673
|
||||||
if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER)
|
if(CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL_BOOTLOADER)
|
||||||
@@ -415,47 +415,28 @@ if(CONFIG_MBEDTLS_HARDWARE_GCM OR CONFIG_MBEDTLS_HARDWARE_AES)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_MBEDTLS_HARDWARE_ECC)
|
if(CONFIG_SOC_ECC_SUPPORTED)
|
||||||
target_sources(builtin PRIVATE "${COMPONENT_DIR}/port/ecc/esp_ecc.c"
|
target_sources(builtin PRIVATE "${COMPONENT_DIR}/port/ecc/esp_ecc.c")
|
||||||
"${COMPONENT_DIR}/port/ecc/ecc_alt.c")
|
if(CONFIG_MBEDTLS_HARDWARE_ECC)
|
||||||
include_directories("${COMPONENT_DIR}/tf-psa-crypto/drivers/builtin/include/mbedtls")
|
target_sources(builtin PRIVATE "${COMPONENT_DIR}/port/ecc/ecc_alt.c")
|
||||||
|
include_directories("${COMPONENT_DIR}/tf-psa-crypto/drivers/builtin/include/mbedtls")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR
|
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN)
|
||||||
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_sources(builtin PRIVATE "${COMPONENT_DIR}/port/ecdsa/ecdsa_alt.c")
|
target_compile_definitions(tfpsacrypto PUBLIC ESP_ECDSA_DRIVER_ENABLED)
|
||||||
|
|
||||||
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_TEE_SEC_STG_ECDSA_SIGN)
|
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN)
|
||||||
foreach(wrap ${WRAP_FUNCTIONS_SIGN})
|
target_compile_definitions(tfpsacrypto PRIVATE ESP_ECDSA_SIGN_DRIVER_ENABLED)
|
||||||
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()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY)
|
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY)
|
||||||
foreach(wrap ${WRAP_FUNCTIONS_VERIFY})
|
target_compile_definitions(tfpsacrypto PRIVATE ESP_ECDSA_VERIFY_DRIVER_ENABLED)
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}")
|
|
||||||
endforeach()
|
|
||||||
endif()
|
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)
|
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()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -508,10 +489,6 @@ if(CONFIG_PM_ENABLE)
|
|||||||
target_link_libraries(tfpsacrypto PRIVATE idf::esp_pm)
|
target_link_libraries(tfpsacrypto PRIVATE idf::esp_pm)
|
||||||
endif()
|
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})
|
target_link_libraries(${COMPONENT_LIB} ${linkage_type} ${mbedtls_targets})
|
||||||
|
|
||||||
# Ensure PSA crypto initialization is included in the build
|
# Ensure PSA crypto initialization is included in the build
|
||||||
@@ -529,7 +506,7 @@ function(builtin_optional_deps component_name)
|
|||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM)
|
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()
|
endif()
|
||||||
|
|
||||||
# # Link esp-cryptoauthlib to mbedtls
|
# # Link esp-cryptoauthlib to mbedtls
|
||||||
|
|||||||
Submodule components/mbedtls/mbedtls updated: 41dc25dd2f...ccdb388c27
@@ -21,8 +21,6 @@
|
|||||||
#include "esp_aes_internal.h"
|
#include "esp_aes_internal.h"
|
||||||
#include "hal/aes_hal.h"
|
#include "hal/aes_hal.h"
|
||||||
|
|
||||||
#include "mbedtls/gcm.h"
|
|
||||||
|
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "soc/soc_caps.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
|
#undef MBEDTLS_MPI_MUL_MPI_ALT
|
||||||
#endif
|
#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
|
#ifdef CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN
|
||||||
#define MBEDTLS_ECDSA_SIGN_ALT
|
#define MBEDTLS_ECDSA_SIGN_ALT
|
||||||
#endif
|
#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,865 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ESP ECDSA PSA Crypto Opaque Driver
|
||||||
|
*
|
||||||
|
* This driver provides PSA Crypto API integration for ESP ECDSA hardware.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <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
|
||||||
|
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
|
int high_blk;
|
||||||
|
HAL_ECDSA_EXTRACT_KEY_BLOCKS(efuse_blk, high_blk, low_blk);
|
||||||
|
if (!is_efuse_blk_valid(high_blk, low_blk)) {
|
||||||
|
ESP_LOGE(TAG, "Invalid efuse block selected");
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
esp_efuse_purpose_t expected_key_purpose_high;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (curve) {
|
||||||
|
case ESP_ECDSA_CURVE_SECP192R1:
|
||||||
|
expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P192;
|
||||||
|
break;
|
||||||
|
case ESP_ECDSA_CURVE_SECP256R1:
|
||||||
|
expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P256;
|
||||||
|
break;
|
||||||
|
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
|
case ESP_ECDSA_CURVE_SECP384R1:
|
||||||
|
expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_L;
|
||||||
|
expected_key_purpose_high = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY_P384_H;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ESP_LOGE(TAG, "Unsupported ECDSA curve: %ld", curve);
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
#else /* SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */
|
||||||
|
expected_key_purpose_low = ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY;
|
||||||
|
#endif /* !SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES */
|
||||||
|
|
||||||
|
if (expected_key_purpose_low != esp_efuse_get_key_purpose((esp_efuse_block_t)low_blk)) {
|
||||||
|
ESP_LOGE(TAG, "Key burned in efuse has incorrect purpose, expected: %d, got: %d, low_blk: %d", expected_key_purpose_low, esp_efuse_get_key_purpose((esp_efuse_block_t)low_blk), low_blk);
|
||||||
|
return PSA_ERROR_NOT_PERMITTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES && SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
|
// Only check high block purpose for P384 curves that actually use it
|
||||||
|
if (curve == ESP_ECDSA_CURVE_SECP384R1 &&
|
||||||
|
expected_key_purpose_high != esp_efuse_get_key_purpose((esp_efuse_block_t)high_blk)) {
|
||||||
|
ESP_LOGE(TAG, "Key burned in efuse has incorrect purpose for high block");
|
||||||
|
return PSA_ERROR_NOT_PERMITTED;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return PSA_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
|
||||||
|
static psa_status_t validate_ecdsa_opaque_key_attributes(const psa_key_attributes_t *attributes, const esp_ecdsa_opaque_key_t *opaque_key)
|
||||||
|
{
|
||||||
|
esp_ecdsa_curve_t expected_curve = psa_bits_to_ecdsa_curve(PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)));
|
||||||
|
|
||||||
|
if (expected_curve != opaque_key->curve) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||||
|
if (!(opaque_key->use_km_key
|
||||||
|
#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
|
||||||
|
|| opaque_key->tee_key_id
|
||||||
|
#endif
|
||||||
|
)) {
|
||||||
|
psa_status_t status = esp_ecdsa_validate_efuse_block(opaque_key->curve, opaque_key->efuse_block);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
|
||||||
|
return PSA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
psa_status_t esp_ecdsa_opaque_import_key(
|
||||||
|
const psa_key_attributes_t *attributes,
|
||||||
|
const uint8_t *data,
|
||||||
|
size_t data_length,
|
||||||
|
uint8_t *key_buffer,
|
||||||
|
size_t key_buffer_size,
|
||||||
|
size_t *key_buffer_length,
|
||||||
|
size_t *bits)
|
||||||
|
{
|
||||||
|
if (!attributes || !data || data_length < 1 || !key_buffer || !key_buffer_length || !bits) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_buffer_size < sizeof(esp_ecdsa_opaque_key_t) || data_length < sizeof(esp_ecdsa_opaque_key_t)) {
|
||||||
|
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const esp_ecdsa_opaque_key_t *opaque_key = (const esp_ecdsa_opaque_key_t *) data;
|
||||||
|
psa_status_t status = validate_ecdsa_opaque_key_attributes(attributes, opaque_key);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(key_buffer, opaque_key, sizeof(esp_ecdsa_opaque_key_t));
|
||||||
|
*key_buffer_length = sizeof(esp_ecdsa_opaque_key_t);
|
||||||
|
*bits = psa_get_key_bits(attributes);
|
||||||
|
return PSA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
psa_status_t esp_ecdsa_opaque_sign_hash_start(
|
||||||
|
esp_ecdsa_opaque_sign_hash_operation_t *operation,
|
||||||
|
const psa_key_attributes_t *attributes,
|
||||||
|
const uint8_t *key_buffer,
|
||||||
|
size_t key_buffer_size,
|
||||||
|
psa_algorithm_t alg,
|
||||||
|
const uint8_t *hash,
|
||||||
|
size_t hash_length)
|
||||||
|
{
|
||||||
|
if (!operation || !attributes || !key_buffer || !hash) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_buffer_size < sizeof(esp_ecdsa_opaque_key_t)) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if ECDSA algorithm
|
||||||
|
if (!PSA_ALG_IS_ECDSA(alg)) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_ecdsa_opaque_key_t *opaque_key = (esp_ecdsa_opaque_key_t *) key_buffer;
|
||||||
|
psa_status_t status = validate_ecdsa_opaque_key_attributes(attributes, opaque_key);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = validate_ecdsa_sha_alg(alg, opaque_key->curve);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t component_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes));
|
||||||
|
|
||||||
|
// Validate hash length
|
||||||
|
if ((opaque_key->curve == ESP_ECDSA_CURVE_SECP192R1 && hash_length != ECDSA_SHA_LEN
|
||||||
|
#if SOC_ECDSA_SUPPORTED
|
||||||
|
&& esp_efuse_is_ecdsa_p192_curve_supported()
|
||||||
|
#endif
|
||||||
|
) || (opaque_key->curve == ESP_ECDSA_CURVE_SECP256R1 && hash_length != ECDSA_SHA_LEN
|
||||||
|
#if SOC_ECDSA_SUPPORTED
|
||||||
|
&& esp_efuse_is_ecdsa_p256_curve_supported()
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
|
|| (opaque_key->curve == ESP_ECDSA_CURVE_SECP384R1 && hash_length != ECDSA_SHA_LEN_P384)
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(operation, 0, sizeof(esp_ecdsa_opaque_sign_hash_operation_t));
|
||||||
|
|
||||||
|
operation->key_len = component_len;
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
|
||||||
|
if (opaque_key->tee_key_id) {
|
||||||
|
// The ESP-TEE API expects the hash in big endian order
|
||||||
|
memcpy(operation->sha, hash, component_len);
|
||||||
|
} else
|
||||||
|
#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */
|
||||||
|
{
|
||||||
|
change_endianess(hash, operation->sha, component_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
operation->opaque_key = opaque_key;
|
||||||
|
operation->alg = alg;
|
||||||
|
operation->sha_len = hash_length;
|
||||||
|
|
||||||
|
return PSA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
psa_status_t esp_ecdsa_opaque_sign_hash_complete(
|
||||||
|
esp_ecdsa_opaque_sign_hash_operation_t *operation,
|
||||||
|
uint8_t *signature, size_t signature_size,
|
||||||
|
size_t *signature_length)
|
||||||
|
{
|
||||||
|
if (!operation || !signature || !signature_length) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t component_len = operation->key_len;
|
||||||
|
|
||||||
|
if (signature_size < 2 * component_len) {
|
||||||
|
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
|
||||||
|
esp_ecdsa_opaque_key_t *opaque_key = operation->opaque_key;
|
||||||
|
if (opaque_key->tee_key_id) {
|
||||||
|
esp_tee_sec_storage_type_t tee_sec_storage_type = esp_ecdsa_curve_to_tee_sec_storage_type(opaque_key->curve);
|
||||||
|
if (tee_sec_storage_type == (esp_tee_sec_storage_type_t) -1) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_tee_sec_storage_key_cfg_t cfg = {
|
||||||
|
.id = opaque_key->tee_key_id,
|
||||||
|
.type = tee_sec_storage_type
|
||||||
|
};
|
||||||
|
|
||||||
|
esp_tee_sec_storage_ecdsa_sign_t sign = {};
|
||||||
|
esp_err_t err = esp_tee_sec_storage_ecdsa_sign(&cfg, operation->sha, operation->sha_len, &sign);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to get signature: 0x%08lx", err);
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(signature, sign.signature, 2 * component_len);
|
||||||
|
*signature_length = 2 * component_len;
|
||||||
|
|
||||||
|
} else
|
||||||
|
#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */
|
||||||
|
{
|
||||||
|
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||||
|
// Check if the ECDSA peripheral is supported on this chip revision
|
||||||
|
if (!ecdsa_ll_is_supported()) {
|
||||||
|
ESP_LOGE(TAG, "ECDSA peripheral not supported on this chip revision");
|
||||||
|
return PSA_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecdsa_sign_type_t k_type = ECDSA_K_TYPE_TRNG;
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
|
||||||
|
if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) {
|
||||||
|
if (ecdsa_ll_is_deterministic_mode_supported()) {
|
||||||
|
k_type = ECDSA_K_TYPE_DETERMINISITIC;
|
||||||
|
} else {
|
||||||
|
return PSA_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
|
||||||
|
|
||||||
|
uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0};
|
||||||
|
|
||||||
|
// Acquire hardware
|
||||||
|
esp_ecdsa_acquire_hardware();
|
||||||
|
|
||||||
|
bool process_again = false;
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP
|
||||||
|
uint16_t deterministic_loop_number __attribute__((unused)) = 1;
|
||||||
|
#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */
|
||||||
|
|
||||||
|
do {
|
||||||
|
ecdsa_hal_config_t conf = {
|
||||||
|
.mode = ECDSA_MODE_SIGN_GEN,
|
||||||
|
.curve = operation->opaque_key->curve,
|
||||||
|
.sha_mode = ECDSA_Z_USER_PROVIDED,
|
||||||
|
.sign_type = k_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP
|
||||||
|
if (k_type == ECDSA_K_TYPE_DETERMINISITIC) {
|
||||||
|
conf.loop_number = deterministic_loop_number++;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */
|
||||||
|
|
||||||
|
// Set key source (consistent with esp_ecdsa_pk_conf_t)
|
||||||
|
if (operation->opaque_key->use_km_key) {
|
||||||
|
conf.use_km_key = 1;
|
||||||
|
} else {
|
||||||
|
conf.efuse_key_blk = operation->opaque_key->efuse_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM
|
||||||
|
uint64_t sig_time = esp_timer_get_time();
|
||||||
|
#endif
|
||||||
|
// Generate signature
|
||||||
|
ecdsa_hal_gen_signature(&conf, operation->sha, operation->r, operation->s, component_len);
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM
|
||||||
|
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) {
|
||||||
|
sig_time = esp_timer_get_time() - sig_time;
|
||||||
|
if (sig_time < ECDSA_CM_FIXED_SIG_TIME) {
|
||||||
|
esp_rom_delay_us(ECDSA_CM_FIXED_SIG_TIME - sig_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Check if we need to retry (zero signature or operation failed)
|
||||||
|
process_again = !ecdsa_hal_get_operation_result()
|
||||||
|
|| !memcmp(operation->r, zeroes, component_len)
|
||||||
|
|| !memcmp(operation->s, zeroes, component_len);
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP
|
||||||
|
if (k_type == ECDSA_K_TYPE_DETERMINISITIC) {
|
||||||
|
process_again |= !ecdsa_hal_det_signature_k_check();
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MBEDTLS_ECDSA_DETERMINISTIC && SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && !SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */
|
||||||
|
} while (process_again);
|
||||||
|
|
||||||
|
esp_ecdsa_release_hardware();
|
||||||
|
|
||||||
|
// Convert r from little-endian to big-endian and copy to output
|
||||||
|
change_endianess(operation->r, signature, component_len);
|
||||||
|
// Convert s from little-endian to big-endian and copy to output
|
||||||
|
change_endianess(operation->s, signature + component_len, component_len);
|
||||||
|
#else
|
||||||
|
// This is an invalid operation as the hardware ECDSA signing is not supported on this chip
|
||||||
|
// and still the key is opaque.
|
||||||
|
return PSA_ERROR_NOT_SUPPORTED;
|
||||||
|
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
|
||||||
|
}
|
||||||
|
|
||||||
|
*signature_length = 2 * component_len;
|
||||||
|
|
||||||
|
return PSA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
psa_status_t esp_ecdsa_opaque_sign_hash_abort(esp_ecdsa_opaque_sign_hash_operation_t *operation)
|
||||||
|
{
|
||||||
|
if (operation) {
|
||||||
|
memset(operation, 0, sizeof(esp_ecdsa_opaque_sign_hash_operation_t));
|
||||||
|
}
|
||||||
|
return PSA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
psa_status_t esp_ecdsa_opaque_sign_hash(
|
||||||
|
const psa_key_attributes_t *attributes,
|
||||||
|
const uint8_t *key_buffer,
|
||||||
|
size_t key_buffer_size,
|
||||||
|
psa_algorithm_t alg,
|
||||||
|
const uint8_t *hash,
|
||||||
|
size_t hash_length,
|
||||||
|
uint8_t *signature,
|
||||||
|
size_t signature_size,
|
||||||
|
size_t *signature_length)
|
||||||
|
{
|
||||||
|
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
|
||||||
|
|
||||||
|
esp_ecdsa_opaque_sign_hash_operation_t operation;
|
||||||
|
|
||||||
|
status = esp_ecdsa_opaque_sign_hash_start(&operation, attributes, key_buffer, key_buffer_size, alg, hash, hash_length);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
|
esp_ecdsa_opaque_sign_hash_abort(&operation);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = esp_ecdsa_opaque_sign_hash_complete(&operation, signature, signature_size, signature_length);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
|
esp_ecdsa_opaque_sign_hash_abort(&operation);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
return esp_ecdsa_opaque_sign_hash_abort(&operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
psa_status_t esp_ecdsa_opaque_export_public_key(
|
||||||
|
const psa_key_attributes_t *attributes,
|
||||||
|
const uint8_t *key_buffer,
|
||||||
|
size_t key_buffer_size,
|
||||||
|
uint8_t *data,
|
||||||
|
size_t data_size,
|
||||||
|
size_t *data_length)
|
||||||
|
{
|
||||||
|
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
|
||||||
|
|
||||||
|
if (!attributes || !key_buffer || !data || !data_length) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_buffer_size < sizeof(esp_ecdsa_opaque_key_t)) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
const esp_ecdsa_opaque_key_t *opaque_key = (const esp_ecdsa_opaque_key_t *) key_buffer;
|
||||||
|
status = validate_ecdsa_opaque_key_attributes(attributes, opaque_key);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get curve parameters from attributes
|
||||||
|
size_t key_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes));
|
||||||
|
|
||||||
|
// As the ESP ECDSA driver only supports uncompressed point format,
|
||||||
|
// the public key is exported in uncompressed point format (ECDSA_UNCOMPRESSED_POINT_FORMAT || x || y)
|
||||||
|
// Need 1 byte for format + key_len bytes for x + key_len bytes for y
|
||||||
|
size_t required_size = 1 + (2 * key_len);
|
||||||
|
if (data_size < required_size) {
|
||||||
|
return PSA_ERROR_BUFFER_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
|
||||||
|
if (opaque_key->tee_key_id) {
|
||||||
|
esp_tee_sec_storage_type_t tee_sec_storage_type = esp_ecdsa_curve_to_tee_sec_storage_type(opaque_key->curve);
|
||||||
|
if (tee_sec_storage_type == (esp_tee_sec_storage_type_t) -1) {
|
||||||
|
return PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_tee_sec_storage_key_cfg_t cfg = {
|
||||||
|
.id = opaque_key->tee_key_id,
|
||||||
|
.type = tee_sec_storage_type,
|
||||||
|
};
|
||||||
|
|
||||||
|
esp_tee_sec_storage_ecdsa_pubkey_t pubkey;
|
||||||
|
if (esp_tee_sec_storage_ecdsa_get_pubkey(&cfg, &pubkey) != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Failed to get public key from secure storage");
|
||||||
|
return PSA_ERROR_GENERIC_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
data[0] = ECDSA_UNCOMPRESSED_POINT_FORMAT;
|
||||||
|
memcpy(data + 1, pubkey.pub_x, key_len);
|
||||||
|
memcpy(data + 1 + key_len, pubkey.pub_y, key_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */
|
||||||
|
{
|
||||||
|
#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
|
||||||
|
// Check if the ECDSA peripheral is supported on this chip revision
|
||||||
|
if (!ecdsa_ll_is_supported()) {
|
||||||
|
ESP_LOGE(TAG, "ECDSA peripheral not supported on this chip revision");
|
||||||
|
return PSA_ERROR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0};
|
||||||
|
uint8_t qx[MAX_ECDSA_COMPONENT_LEN];
|
||||||
|
uint8_t qy[MAX_ECDSA_COMPONENT_LEN];
|
||||||
|
|
||||||
|
ecdsa_hal_config_t conf = {
|
||||||
|
.mode = ECDSA_MODE_EXPORT_PUBKEY,
|
||||||
|
.curve = opaque_key->curve,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (opaque_key->use_km_key) {
|
||||||
|
conf.use_km_key = 1;
|
||||||
|
} else {
|
||||||
|
conf.efuse_key_blk = opaque_key->efuse_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_ecdsa_acquire_hardware();
|
||||||
|
bool process_again = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ecdsa_hal_export_pubkey(&conf, qx, qy, key_len);
|
||||||
|
|
||||||
|
process_again = !ecdsa_hal_get_operation_result()
|
||||||
|
|| !memcmp(qx, zeroes, key_len)
|
||||||
|
|| !memcmp(qy, zeroes, key_len);
|
||||||
|
|
||||||
|
} while (process_again);
|
||||||
|
|
||||||
|
esp_ecdsa_release_hardware();
|
||||||
|
|
||||||
|
// Format: uncompressed point (ECDSA_UNCOMPRESSED_POINT_FORMAT byte followed by x and y coordinates)
|
||||||
|
data[0] = ECDSA_UNCOMPRESSED_POINT_FORMAT;
|
||||||
|
|
||||||
|
// Convert qx from little-endian to big-endian and copy to output
|
||||||
|
change_endianess(qx, data + 1, key_len);
|
||||||
|
|
||||||
|
// Convert qy from little-endian to big-endian and copy to output
|
||||||
|
change_endianess(qy, data + 1 + key_len, key_len);
|
||||||
|
#else
|
||||||
|
// This is an invalid operation as the export public key is not supported on this chip
|
||||||
|
// and still the key is opaque
|
||||||
|
return PSA_ERROR_NOT_SUPPORTED;
|
||||||
|
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
|
||||||
|
}
|
||||||
|
|
||||||
|
*data_length = required_size;
|
||||||
|
|
||||||
|
return PSA_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t esp_ecdsa_opaque_size_function(
|
||||||
|
psa_key_type_t key_type,
|
||||||
|
size_t key_bits)
|
||||||
|
{
|
||||||
|
(void)key_type;
|
||||||
|
(void)key_bits;
|
||||||
|
|
||||||
|
// Opaque keys always use the same size structure
|
||||||
|
return sizeof(esp_ecdsa_opaque_key_t);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
|
||||||
@@ -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
-188
@@ -1,6 +1,6 @@
|
|||||||
/* mbedTLS Elliptic Curve Digital Signature performance tests
|
/* mbedTLS Elliptic Curve Digital Signature performance tests
|
||||||
*
|
*
|
||||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -9,12 +9,10 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <esp_log.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.h"
|
||||||
|
#include "psa_crypto_driver_esp_ecdsa_contexts.h"
|
||||||
|
#include "psa_crypto_driver_esp_ecdsa.h"
|
||||||
|
|
||||||
#include "hal/efuse_ll.h"
|
#include "hal/efuse_ll.h"
|
||||||
#include "esp_efuse.h"
|
#include "esp_efuse.h"
|
||||||
@@ -26,7 +24,6 @@
|
|||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "crypto_performance.h"
|
#include "crypto_performance.h"
|
||||||
|
|
||||||
#include "ecdsa/ecdsa_alt.h"
|
|
||||||
#if SOC_KEY_MANAGER_SUPPORTED
|
#if SOC_KEY_MANAGER_SUPPORTED
|
||||||
#include "esp_key_mgr.h"
|
#include "esp_key_mgr.h"
|
||||||
#include "hal/key_mgr_ll.h"
|
#include "hal/key_mgr_ll.h"
|
||||||
@@ -62,6 +59,8 @@
|
|||||||
#define ECDSA_P192_HASH_COMPONENT_LEN 24
|
#define ECDSA_P192_HASH_COMPONENT_LEN 24
|
||||||
#define ECDSA_P256_HASH_COMPONENT_LEN 32
|
#define ECDSA_P256_HASH_COMPONENT_LEN 32
|
||||||
|
|
||||||
|
#define ECDSA_UNCOMPRESSED_POINT_FORMAT 0x04
|
||||||
|
|
||||||
__attribute__((unused)) static const char * TAG = "mbedtls_test";
|
__attribute__((unused)) static const char * TAG = "mbedtls_test";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -172,106 +171,73 @@ const uint8_t ecdsa192_pub_y[] = {
|
|||||||
0x23, 0xae, 0x7e, 0x0f, 0x1f, 0x4d, 0x69, 0xd5
|
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)
|
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;
|
int64_t elapsed_time;
|
||||||
mbedtls_mpi r, s;
|
size_t plen;
|
||||||
|
|
||||||
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));
|
|
||||||
|
|
||||||
psa_key_id_t key_id;
|
psa_key_id_t key_id;
|
||||||
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
if (id != MBEDTLS_ECP_DP_SECP192R1) {
|
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
|
||||||
psa_key_type_t curve_family = PSA_ECC_FAMILY_SECP_R1;
|
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH);
|
||||||
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve_family));
|
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
|
||||||
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));
|
|
||||||
|
|
||||||
uint8_t psa_key[2 * plen + 1];
|
switch (curve) {
|
||||||
psa_key[0] = 0x04; // Uncompressed point indicator
|
case ESP_ECDSA_CURVE_SECP192R1:
|
||||||
memcpy(&psa_key[1], pub_x, plen);
|
plen = 192;
|
||||||
memcpy(&psa_key[1 + plen], pub_y, plen);
|
hash_len = HASH_LEN;
|
||||||
|
break;
|
||||||
psa_status_t status = psa_import_key(&key_attr, psa_key, sizeof(psa_key), &key_id);
|
case ESP_ECDSA_CURVE_SECP256R1:
|
||||||
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
|
plen = 256;
|
||||||
}
|
hash_len = HASH_LEN;
|
||||||
|
break;
|
||||||
if (id == MBEDTLS_ECP_DP_SECP192R1 || id == MBEDTLS_ECP_DP_SECP256R1) {
|
|
||||||
hash_len = HASH_LEN;
|
|
||||||
}
|
|
||||||
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
|
case ESP_ECDSA_CURVE_SECP384R1:
|
||||||
hash_len = HASH_LEN_P384;
|
plen = 384;
|
||||||
}
|
hash_len = HASH_LEN_P384;
|
||||||
|
break;
|
||||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
#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();
|
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();
|
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));
|
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));
|
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
|
#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));
|
TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P384_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
psa_destroy_key(key_id);
|
||||||
if (id != MBEDTLS_ECP_DP_SECP192R1) {
|
psa_reset_key_attributes(&key_attr);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("mbedtls ECDSA signature verification performance on SECP192R1", "[mbedtls]")
|
TEST_CASE("mbedtls ECDSA signature verification performance on SECP192R1", "[mbedtls]")
|
||||||
@@ -281,8 +247,7 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP192R1", "[mbe
|
|||||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
test_ecdsa_verify(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_r, ecdsa192_s,
|
test_ecdsa_verify(ESP_ECDSA_CURVE_SECP192R1, sha, ecdsa192_r, ecdsa192_s, ecdsa192_pub_x, ecdsa192_pub_y);
|
||||||
ecdsa192_pub_x, ecdsa192_pub_y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbedtls]")
|
TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbedtls]")
|
||||||
@@ -292,8 +257,7 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP256R1", "[mbe
|
|||||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
test_ecdsa_verify(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_r, ecdsa256_s,
|
test_ecdsa_verify(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_r, ecdsa256_s, ecdsa256_pub_x, ecdsa256_pub_y);
|
||||||
ecdsa256_pub_x, ecdsa256_pub_y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
@@ -304,14 +268,14 @@ TEST_CASE("mbedtls ECDSA signature verification performance on SECP384R1", "[mbe
|
|||||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
test_ecdsa_verify(MBEDTLS_ECP_DP_SECP384R1, sha, ecdsa384_r, ecdsa384_s,
|
test_ecdsa_verify(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_r, ecdsa384_s, ecdsa384_pub_x, ecdsa384_pub_y);
|
||||||
ecdsa384_pub_x, ecdsa384_pub_y);
|
|
||||||
}
|
}
|
||||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||||
|
|
||||||
#endif /* CONFIG_MBEDTLS_HARDWARE_ECC */
|
#endif /* CONFIG_MBEDTLS_HARDWARE_ECC */
|
||||||
|
|
||||||
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
#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.
|
* This test assumes that ECDSA private key has been burnt in efuse.
|
||||||
@@ -343,66 +307,76 @@ const uint8_t k1_ecdsa192_encrypt[] = {
|
|||||||
0xde, 0xe9, 0x9c, 0x89, 0xf2, 0x3b, 0x29, 0xb7, 0x9e, 0x33, 0xec, 0x76, 0x75, 0x2f, 0x3e, 0xab, 0x61, 0x06, 0x4d, 0xea, 0x05, 0x2c, 0xc3, 0x29, 0x1c, 0x7f, 0xb7, 0x3d, 0xb8, 0x1c, 0xb2, 0x17,
|
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;
|
size_t hash_len = HASH_LEN;
|
||||||
uint8_t r_be[MAX_ECDSA_COMPONENT_LEN] = {0};
|
uint8_t signature[2 * MAX_ECDSA_COMPONENT_LEN];
|
||||||
uint8_t s_be[MAX_ECDSA_COMPONENT_LEN] = {0};
|
size_t signature_len = 0;
|
||||||
|
size_t plen = 0;
|
||||||
|
psa_algorithm_t sha_alg = 0;
|
||||||
|
|
||||||
mbedtls_mpi r, s;
|
switch (curve) {
|
||||||
mbedtls_mpi key_mpi;
|
case ESP_ECDSA_CURVE_SECP192R1:
|
||||||
|
hash_len = HASH_LEN;
|
||||||
mbedtls_mpi_init(&r);
|
plen = 192;
|
||||||
mbedtls_mpi_init(&s);
|
sha_alg = PSA_ALG_SHA_256;
|
||||||
|
break;
|
||||||
mbedtls_ecdsa_context ecdsa_context;
|
case ESP_ECDSA_CURVE_SECP256R1:
|
||||||
mbedtls_ecdsa_init(&ecdsa_context);
|
hash_len = HASH_LEN;
|
||||||
|
plen = 256;
|
||||||
if (id == MBEDTLS_ECP_DP_SECP192R1) {
|
sha_alg = PSA_ALG_SHA_256;
|
||||||
mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP192R1);
|
break;
|
||||||
} else if (id == MBEDTLS_ECP_DP_SECP256R1) {
|
|
||||||
mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
|
|
||||||
}
|
|
||||||
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
|
case ESP_ECDSA_CURVE_SECP384R1:
|
||||||
mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP384R1);
|
hash_len = HASH_LEN_P384;
|
||||||
}
|
plen = 384;
|
||||||
#endif
|
sha_alg = PSA_ALG_SHA_384;
|
||||||
esp_ecdsa_privkey_load_mpi(&key_mpi, efuse_key_block);
|
break;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||||
|
default:
|
||||||
|
TEST_FAIL_MESSAGE("Invalid curve");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_deterministic) {
|
size_t plen_bytes = plen / 8;
|
||||||
mbedtls_ecdsa_sign_det_ext(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, hash_len, 0, NULL, NULL);
|
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 {
|
} 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);
|
psa_algorithm_t alg = (is_deterministic ? PSA_ALG_DETERMINISTIC_ECDSA(sha_alg) : PSA_ALG_ECDSA(sha_alg));
|
||||||
mbedtls_mpi_write_binary(&s, s_be, MAX_ECDSA_COMPONENT_LEN);
|
|
||||||
|
|
||||||
if (id == MBEDTLS_ECP_DP_SECP192R1) {
|
// Set attributes for opaque private key
|
||||||
// Skip the initial zeroes
|
psa_set_key_type(&priv_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
|
||||||
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);
|
psa_set_key_bits(&priv_attr, plen);
|
||||||
} else if (id == MBEDTLS_ECP_DP_SECP256R1) {
|
psa_set_key_usage_flags(&priv_attr, PSA_KEY_USAGE_SIGN_HASH);
|
||||||
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);
|
psa_set_key_algorithm(&priv_attr, alg);
|
||||||
}
|
psa_set_key_lifetime(&priv_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE); // Opaque key
|
||||||
#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
|
|
||||||
|
|
||||||
mbedtls_mpi_free(&r);
|
// Import opaque key reference
|
||||||
mbedtls_mpi_free(&s);
|
psa_status_t status = psa_import_key(&priv_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id);
|
||||||
mbedtls_mpi_free(&key_mpi);
|
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]")
|
TEST_CASE("mbedtls ECDSA signature generation on SECP192R1", "[mbedtls][efuse_key]")
|
||||||
@@ -410,7 +384,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP192R1", "[mbedtls][efuse_ke
|
|||||||
if (!ecdsa_ll_is_supported()) {
|
if (!ecdsa_ll_is_supported()) {
|
||||||
TEST_IGNORE_MESSAGE("ECDSA is not 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]")
|
TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][efuse_key]")
|
||||||
@@ -418,8 +392,9 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][efuse_ke
|
|||||||
if (!ecdsa_ll_is_supported()) {
|
if (!ecdsa_ll_is_supported()) {
|
||||||
TEST_IGNORE_MESSAGE("ECDSA is not 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
|
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
TEST_CASE("mbedtls ECDSA signature generation on SECP384R1", "[mbedtls][efuse_key]")
|
TEST_CASE("mbedtls ECDSA signature generation on SECP384R1", "[mbedtls][efuse_key]")
|
||||||
{
|
{
|
||||||
@@ -427,7 +402,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP384R1", "[mbedtls][efuse_ke
|
|||||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
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);
|
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 */
|
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||||
|
|
||||||
@@ -469,7 +444,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP192R1", "[mbedtls][key_mana
|
|||||||
}
|
}
|
||||||
|
|
||||||
deploy_key_in_key_manager(k1_ecdsa192_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_192);
|
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);
|
esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -483,7 +458,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][key_mana
|
|||||||
}
|
}
|
||||||
|
|
||||||
deploy_key_in_key_manager(k1_ecdsa256_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_256);
|
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);
|
esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY);
|
||||||
}
|
}
|
||||||
#endif /* SOC_KEY_MANAGER_SUPPORTED */
|
#endif /* SOC_KEY_MANAGER_SUPPORTED */
|
||||||
@@ -497,7 +472,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP192R1", "[mbe
|
|||||||
if (!ecdsa_ll_is_deterministic_mode_supported()) {
|
if (!ecdsa_ll_is_deterministic_mode_supported()) {
|
||||||
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
||||||
} else {
|
} else {
|
||||||
test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, true, SECP192R1_EFUSE_BLOCK);
|
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, true, SECP192R1_EFUSE_BLOCK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +484,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe
|
|||||||
if (!ecdsa_ll_is_deterministic_mode_supported()) {
|
if (!ecdsa_ll_is_deterministic_mode_supported()) {
|
||||||
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
||||||
} else {
|
} else {
|
||||||
test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, true, SECP256R1_EFUSE_BLOCK);
|
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, true, SECP256R1_EFUSE_BLOCK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,7 +495,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP384R1", "[mbe
|
|||||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
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);
|
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 */
|
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||||
|
|
||||||
@@ -538,7 +513,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP192R1", "[mbe
|
|||||||
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
||||||
} else {
|
} else {
|
||||||
deploy_key_in_key_manager(k1_ecdsa192_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_192);
|
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);
|
esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -556,7 +531,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe
|
|||||||
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
||||||
} else {
|
} else {
|
||||||
deploy_key_in_key_manager(k1_ecdsa256_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_256);
|
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);
|
esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -564,48 +539,70 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe
|
|||||||
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
|
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
|
||||||
|
|
||||||
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
|
#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_key[1 + 2 * MAX_ECDSA_COMPONENT_LEN] = {0};
|
||||||
uint8_t export_pub_y[48] = {0};
|
size_t len = 0;
|
||||||
int len = 0;
|
|
||||||
|
|
||||||
esp_ecdsa_pk_conf_t pk_conf = {
|
psa_key_id_t priv_key_id = 0;
|
||||||
.grp_id = id,
|
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
.load_pubkey = true,
|
|
||||||
|
esp_ecdsa_opaque_key_t opaque_key = {
|
||||||
|
.curve = curve,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (efuse_key_block == USE_ECDSA_KEY_FROM_KEY_MANAGER) {
|
size_t plen = 0;
|
||||||
pk_conf.use_km_key = true;
|
psa_algorithm_t sha_alg = 0;
|
||||||
} else {
|
|
||||||
pk_conf.efuse_block = efuse_key_block;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == MBEDTLS_ECP_DP_SECP192R1) {
|
switch (curve) {
|
||||||
len = 24;
|
case ESP_ECDSA_CURVE_SECP192R1:
|
||||||
} else if (id == MBEDTLS_ECP_DP_SECP256R1) {
|
plen = 192;
|
||||||
len = 32;
|
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
|
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
|
case ESP_ECDSA_CURVE_SECP384R1:
|
||||||
len = 48;
|
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);
|
// Import opaque key reference
|
||||||
TEST_ASSERT_EQUAL(0, ret);
|
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);
|
status = psa_export_public_key(priv_key_id, export_pub_key, sizeof(export_pub_key), &len);
|
||||||
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);
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(pub_x, export_pub_x, len);
|
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(pub_y, export_pub_y, len);
|
TEST_ASSERT_TRUE(len == 1 + 2 * plen_bytes);
|
||||||
|
|
||||||
/* Use esp_ecdsa_free_pk_context instead of manual cleanup to avoid memory leak */
|
TEST_ASSERT_EQUAL_HEX8(ECDSA_UNCOMPRESSED_POINT_FORMAT, export_pub_key[0]);
|
||||||
esp_ecdsa_free_pk_context(&key_ctx);
|
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]")
|
TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][efuse_key]")
|
||||||
@@ -613,7 +610,7 @@ TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][efuse_key]"
|
|||||||
if (!ecdsa_ll_is_supported()) {
|
if (!ecdsa_ll_is_supported()) {
|
||||||
TEST_IGNORE_MESSAGE("ECDSA is not 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]")
|
TEST_CASE("mbedtls ECDSA export public key on SECP256R1", "[mbedtls][efuse_key]")
|
||||||
@@ -621,7 +618,7 @@ TEST_CASE("mbedtls ECDSA export public key on SECP256R1", "[mbedtls][efuse_key]"
|
|||||||
if (!ecdsa_ll_is_supported()) {
|
if (!ecdsa_ll_is_supported()) {
|
||||||
TEST_IGNORE_MESSAGE("ECDSA is not 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
|
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
||||||
@@ -631,7 +628,7 @@ TEST_CASE("mbedtls ECDSA export public key on SECP384R1", "[mbedtls][efuse_key]"
|
|||||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
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);
|
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 */
|
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||||
|
|
||||||
@@ -646,7 +643,7 @@ TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][key_manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
deploy_key_in_key_manager(k1_ecdsa192_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_192);
|
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);
|
esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,9 +657,161 @@ TEST_CASE("mbedtls ECDSA export public key on SECP256R1", "[mbedtls][key_manager
|
|||||||
}
|
}
|
||||||
|
|
||||||
deploy_key_in_key_manager(k1_ecdsa256_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_256);
|
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);
|
esp_key_mgr_deactivate_key(ESP_KEY_MGR_ECDSA_KEY);
|
||||||
}
|
}
|
||||||
#endif
|
#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 /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
|
||||||
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
|
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
|
||||||
@@ -4,8 +4,6 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "psa/crypto_struct.h"
|
|
||||||
#include "psa/crypto_types.h"
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ INPUT = \
|
|||||||
$(PROJECT_PATH)/components/lwip/include/apps/esp_sntp.h \
|
$(PROJECT_PATH)/components/lwip/include/apps/esp_sntp.h \
|
||||||
$(PROJECT_PATH)/components/lwip/include/apps/ping/ping_sock.h \
|
$(PROJECT_PATH)/components/lwip/include/apps/ping/ping_sock.h \
|
||||||
$(PROJECT_PATH)/components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h \
|
$(PROJECT_PATH)/components/mbedtls/esp_crt_bundle/include/esp_crt_bundle.h \
|
||||||
$(PROJECT_PATH)/components/mbedtls/port/include/ecdsa/ecdsa_alt.h \
|
$(PROJECT_PATH)/components/mbedtls/port/psa_driver/include/psa_crypto_driver_esp_ecdsa_contexts.h \
|
||||||
$(PROJECT_PATH)/components/nvs_flash/include/nvs_flash.h \
|
$(PROJECT_PATH)/components/nvs_flash/include/nvs_flash.h \
|
||||||
$(PROJECT_PATH)/components/nvs_flash/include/nvs.h \
|
$(PROJECT_PATH)/components/nvs_flash/include/nvs.h \
|
||||||
$(PROJECT_PATH)/components/nvs_flash/include/nvs_bootloader.h \
|
$(PROJECT_PATH)/components/nvs_flash/include/nvs_bootloader.h \
|
||||||
|
|||||||
@@ -134,7 +134,8 @@ The ECDSA peripheral in Mbed TLS stack is integrated by overriding the ECDSA sig
|
|||||||
|
|
||||||
For a particular TLS context, additional APIs have been supplied to populate certain fields (e.g., private key ctx) to differentiate routing to hardware. ESP-TLS layer integrates these APIs internally and hence no additional work is required at the application layer. However, for custom use-cases please refer to API details below.
|
For a particular TLS context, additional APIs have been supplied to populate certain fields (e.g., private key ctx) to differentiate routing to hardware. ESP-TLS layer integrates these APIs internally and hence no additional work is required at the application layer. However, for custom use-cases please refer to API details below.
|
||||||
|
|
||||||
|
|
||||||
API Reference
|
API Reference
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
.. include-build-file:: inc/ecdsa_alt.inc
|
.. include-build-file:: inc/psa_crypto_driver_esp_ecdsa_contexts.inc
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ ESP-IDF v6.0 updates to Mbed TLS v4.0, where **PSA Crypto is the primary cryptog
|
|||||||
|
|
||||||
- **Breaking change**: In Mbed TLS v4.0, **most legacy cryptography APIs have been removed** and PSA Crypto is the primary interface. If your application directly uses legacy ``mbedtls_*`` cryptography primitives, you may need to migrate to PSA Crypto APIs.
|
- **Breaking change**: In Mbed TLS v4.0, **most legacy cryptography APIs have been removed** and PSA Crypto is the primary interface. If your application directly uses legacy ``mbedtls_*`` cryptography primitives, you may need to migrate to PSA Crypto APIs.
|
||||||
- **Breaking change**: ``psa_crypto_init()`` must be called before any cryptographic operation, including indirect operations such as parsing keys/certificates or starting a TLS handshake. ESP-IDF initializes PSA during normal startup; however, code that runs earlier than the normal startup sequence must call ``psa_crypto_init()`` explicitly.
|
- **Breaking change**: ``psa_crypto_init()`` must be called before any cryptographic operation, including indirect operations such as parsing keys/certificates or starting a TLS handshake. ESP-IDF initializes PSA during normal startup; however, code that runs earlier than the normal startup sequence must call ``psa_crypto_init()`` explicitly.
|
||||||
- **New API**: ``esp_ecdsa_free_pk_context(mbedtls_pk_context *key_ctx)`` was added (``ecdsa/ecdsa_alt.h``). If your application initializes a PK context with a hardware-backed ECDSA key using ``esp_ecdsa_set_pk_context()``, use ``esp_ecdsa_free_pk_context()`` to free it. With PSA-backed Mbed TLS v4.x, ``mbedtls_pk_free()`` does not deallocate the manually created keypair structure in this case.
|
- **Breaking change**: ``esp_ecdsa_load_pubkey()``, ``esp_ecdsa_privkey_load_mpi()``, ``esp_ecdsa_privkey_load_pk_context()``, ``esp_ecdsa_set_pk_context()``, ``esp_ecdsa_tee_load_pubkey()`` and ``esp_ecdsa_tee_set_pk_context()`` have been deprecated and removed. The legacy ``esp_ecdsa_pk_conf_t`` configuration is replaced by ``esp_ecdsa_opaque_key_t``, which represents an hardware-backed ECDSA opaque key. Applications can populate this structure and import it via ``psa_import_key()``, enabling all ECDSA operations through standard PSA Crypto APIs.
|
||||||
- **Breaking change**: APIs that previously required an application-provided RNG callback (``f_rng``, ``p_rng``) have changed in Mbed TLS v4.0 to use the PSA RNG instead. Update application code to the new prototypes (for example X.509 write APIs, SSL cookie setup, and SSL ticket setup).
|
- **Breaking change**: APIs that previously required an application-provided RNG callback (``f_rng``, ``p_rng``) have changed in Mbed TLS v4.0 to use the PSA RNG instead. Update application code to the new prototypes (for example X.509 write APIs, SSL cookie setup, and SSL ticket setup).
|
||||||
- **Breaking change**: TLS 1.2 / DTLS 1.2 interoperability may be affected because Mbed TLS v4.0 removes support for key exchanges based on finite-field DHE and RSA key exchange without forward secrecy (and static ECDH). If a peer requires removed suites, TLS connections may fail; update server/client cipher suite configuration accordingly.
|
- **Breaking change**: TLS 1.2 / DTLS 1.2 interoperability may be affected because Mbed TLS v4.0 removes support for key exchanges based on finite-field DHE and RSA key exchange without forward secrecy (and static ECDH). If a peer requires removed suites, TLS connections may fail; update server/client cipher suite configuration accordingly.
|
||||||
- **Breaking change**: certificates/peers using elliptic curves of less than 250 bits (for example secp192r1/secp224r1) are no longer supported in certificates and in TLS.
|
- **Breaking change**: certificates/peers using elliptic curves of less than 250 bits (for example secp192r1/secp224r1) are no longer supported in certificates and in TLS.
|
||||||
|
|||||||
@@ -184,16 +184,6 @@ If declarator-id:
|
|||||||
struct esp_cam_ctlr_csi_config_t
|
struct esp_cam_ctlr_csi_config_t
|
||||||
--------------------------------^
|
--------------------------------^
|
||||||
|
|
||||||
ecdsa_alt.inc:line: WARNING: Error in declarator or parameters-and-qualifiers
|
|
||||||
If pointer to member declarator:
|
|
||||||
Invalid C++ declaration: Expected identifier in nested name. [error at 25]
|
|
||||||
union esp_ecdsa_pk_conf_t
|
|
||||||
-------------------------^
|
|
||||||
If declarator-id:
|
|
||||||
Invalid C++ declaration: Expected identifier in nested name. [error at 25]
|
|
||||||
union esp_ecdsa_pk_conf_t
|
|
||||||
-------------------------^
|
|
||||||
|
|
||||||
i2c_master.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/peripherals/i2c:line.
|
i2c_master.inc:line: WARNING: Duplicate C++ declaration, also defined at api-reference/peripherals/i2c:line.
|
||||||
Declaration is '.. cpp:member:: uint8_t * data'.
|
Declaration is '.. cpp:member:: uint8_t * data'.
|
||||||
isp_types.inc:line: WARNING: Error in declarator or parameters-and-qualifiers
|
isp_types.inc:line: WARNING: Error in declarator or parameters-and-qualifiers
|
||||||
|
|||||||
@@ -137,4 +137,4 @@ ECDSA 外设依靠硬件真随机数生成器 (TRNG) 来满足其内部熵要求
|
|||||||
API 参考
|
API 参考
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. include-build-file:: inc/ecdsa_alt.inc
|
.. include-build-file:: inc/psa_crypto_driver_esp_ecdsa_contexts.inc
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ ESP-IDF v6.0 已升级至 Mbed TLS v4.0,**PSA Crypto 成为主要加密接口*
|
|||||||
|
|
||||||
- **重大变更**:在 Mbed TLS v4.0 中,**大多数传统加密 API 已被移除**,PSA Crypto 成为主要接口。如果应用直接使用传统的 ``mbedtls_*`` 加密原语,则无法直接兼容,需迁移到 PSA Crypto API。
|
- **重大变更**:在 Mbed TLS v4.0 中,**大多数传统加密 API 已被移除**,PSA Crypto 成为主要接口。如果应用直接使用传统的 ``mbedtls_*`` 加密原语,则无法直接兼容,需迁移到 PSA Crypto API。
|
||||||
- **重大变更**:在执行任何加密操作之前(包括解析密钥/证书或启动 TLS 握手等操作),必须调用 ``psa_crypto_init()``。ESP-IDF 在常规启动过程中会初始化 PSA,因此大多数应用保持兼容;但对于早于常规启动流程运行的代码,需显式调用 ``psa_crypto_init()``。
|
- **重大变更**:在执行任何加密操作之前(包括解析密钥/证书或启动 TLS 握手等操作),必须调用 ``psa_crypto_init()``。ESP-IDF 在常规启动过程中会初始化 PSA,因此大多数应用保持兼容;但对于早于常规启动流程运行的代码,需显式调用 ``psa_crypto_init()``。
|
||||||
- **新增 API**:新增 ``esp_ecdsa_free_pk_context(mbedtls_pk_context *key_ctx)``,参见 ``ecdsa/ecdsa_alt.h``。如果应用使用 ``esp_ecdsa_set_pk_context()`` 初始化包含硬件 ECDSA 密钥的 PK 上下文,应使用 ``esp_ecdsa_free_pk_context()`` 进行释放。在基于 PSA 的 Mbed TLS v4.x 中,``mbedtls_pk_free()`` 无法释放此种情况下手动创建的密钥对结构。
|
- **重大变更**:``esp_ecdsa_load_pubkey()``、``esp_ecdsa_privkey_load_mpi()``、``esp_ecdsa_privkey_load_pk_context()``、``esp_ecdsa_set_pk_context()``、``esp_ecdsa_tee_load_pubkey()`` 和 ``esp_ecdsa_tee_set_pk_context()`` 已被弃用并移除。旧的 ``esp_ecdsa_pk_conf_t`` 配置已被 ``esp_ecdsa_opaque_key_t`` 取代,后者支持由 ECDSA 硬件提供的不透明密钥。应用程序可以配置该结构体并通过 ``psa_import_key()`` 导入,从而使用标准 PSA Crypto API 启用所有 ECDSA 操作。
|
||||||
- **重大变更**:原需应用提供 RNG 回调(``f_rng``、``p_rng``)的 API,在 Mbed TLS v4.0 中已改为使用 PSA RNG。使用旧函数原型的代码将无法直接兼容,需要更新为新的 API 定义(例如 X.509 写入 API、SSL cookie 设置以及 SSL ticket 设置)。
|
- **重大变更**:原需应用提供 RNG 回调(``f_rng``、``p_rng``)的 API,在 Mbed TLS v4.0 中已改为使用 PSA RNG。使用旧函数原型的代码将无法直接兼容,需要更新为新的 API 定义(例如 X.509 写入 API、SSL cookie 设置以及 SSL ticket 设置)。
|
||||||
- **重大变更**:TLS 1.2 / DTLS 1.2 的互操作性可能受到影响,因为 Mbed TLS v4.0 移除了对基于有限域 DHE、无前向保密的 RSA 密钥交换(以及静态 ECDH)的支持。如果对等端需要使用已移除的密码套件,TLS 连接将不兼容并可能失败;需相应更新服务器或客户端的密码套件配置。
|
- **重大变更**:TLS 1.2 / DTLS 1.2 的互操作性可能受到影响,因为 Mbed TLS v4.0 移除了对基于有限域 DHE、无前向保密的 RSA 密钥交换(以及静态 ECDH)的支持。如果对等端需要使用已移除的密码套件,TLS 连接将不兼容并可能失败;需相应更新服务器或客户端的密码套件配置。
|
||||||
- **重大变更**:证书或对等端中使用的椭圆曲线位数小于 250 位(例如 secp192r1/secp224r1)已不再受支持。
|
- **重大变更**:证书或对等端中使用的椭圆曲线位数小于 250 位(例如 secp192r1/secp224r1)已不再受支持。
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* TEE Secure Storage example
|
* TEE Secure Storage example
|
||||||
*
|
*
|
||||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
|
||||||
#include "psa/crypto.h"
|
#include "psa/crypto.h"
|
||||||
|
#include "psa_crypto_driver_esp_ecdsa.h"
|
||||||
|
|
||||||
#include "esp_tee_sec_storage.h"
|
#include "esp_tee_sec_storage.h"
|
||||||
#include "secure_service_num.h"
|
#include "secure_service_num.h"
|
||||||
@@ -34,9 +35,9 @@ static const char *message = "Lorem ipsum dolor sit amet, consectetur adipiscing
|
|||||||
|
|
||||||
static const char *TAG = "example_tee_sec_stg";
|
static const char *TAG = "example_tee_sec_stg";
|
||||||
|
|
||||||
static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_ecdsa_pubkey_t *pubkey, const esp_tee_sec_storage_ecdsa_sign_t *sign)
|
static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const uint8_t *pub_key, size_t pub_key_len, const uint8_t *signature, size_t signature_len)
|
||||||
{
|
{
|
||||||
if (pubkey == NULL || digest == NULL || sign == NULL) {
|
if (pub_key == NULL || pub_key_len == 0 || digest == NULL || len == 0 || signature == NULL || signature_len == 0) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,29 +47,24 @@ static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len,
|
|||||||
|
|
||||||
esp_err_t err = ESP_FAIL;
|
esp_err_t err = ESP_FAIL;
|
||||||
|
|
||||||
psa_key_id_t key_id = 0;
|
psa_key_id_t pub_key_id = 0;
|
||||||
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
|
psa_key_attributes_t pub_key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
|
psa_set_key_type(&pub_key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
|
||||||
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH);
|
psa_set_key_usage_flags(&pub_key_attr, 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_set_key_algorithm(&pub_key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
|
||||||
|
|
||||||
uint8_t pub_key[2 * ECDSA_SECP256R1_KEY_LEN + 1];
|
psa_status_t status = psa_import_key(&pub_key_attr, pub_key, pub_key_len, &pub_key_id);
|
||||||
pub_key[0] = 0x04;
|
|
||||||
memcpy(pub_key + 1, pubkey->pub_x, ECDSA_SECP256R1_KEY_LEN);
|
|
||||||
memcpy(pub_key + 1 + ECDSA_SECP256R1_KEY_LEN, pubkey->pub_y, ECDSA_SECP256R1_KEY_LEN);
|
|
||||||
|
|
||||||
psa_status_t status = psa_import_key(&key_attributes, pub_key, sizeof(pub_key), &key_id);
|
|
||||||
if (status != PSA_SUCCESS) {
|
if (status != PSA_SUCCESS) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = psa_verify_hash(key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), digest, len, sign->signature, sizeof(sign->signature));
|
status = psa_verify_hash(pub_key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), digest, len, signature, signature_len);
|
||||||
if (status != PSA_SUCCESS) {
|
if (status != PSA_SUCCESS) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
psa_destroy_key(key_id);
|
psa_destroy_key(pub_key_id);
|
||||||
psa_reset_key_attributes(&key_attributes);
|
psa_reset_key_attributes(&pub_key_attr);
|
||||||
|
|
||||||
err = ESP_OK;
|
err = ESP_OK;
|
||||||
|
|
||||||
@@ -107,23 +103,46 @@ static void example_tee_sec_stg_sign_verify(void *pvParameter)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_tee_sec_storage_ecdsa_sign_t sign = {};
|
esp_ecdsa_opaque_key_t opaque_key = {
|
||||||
err = esp_tee_sec_storage_ecdsa_sign(&cfg, msg_digest, msg_digest_len, &sign);
|
.curve = ESP_ECDSA_CURVE_SECP256R1,
|
||||||
if (err != ESP_OK) {
|
.tee_key_id = cfg.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
psa_key_id_t priv_key_id = 0;
|
||||||
|
psa_key_attributes_t priv_key_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||||
|
psa_algorithm_t alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
|
||||||
|
|
||||||
|
psa_set_key_type(&priv_key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
|
||||||
|
psa_set_key_bits(&priv_key_attr, ECDSA_SECP256R1_KEY_LEN * 8);
|
||||||
|
psa_set_key_usage_flags(&priv_key_attr, PSA_KEY_USAGE_SIGN_HASH);
|
||||||
|
psa_set_key_algorithm(&priv_key_attr, alg);
|
||||||
|
psa_set_key_lifetime(&priv_key_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE);
|
||||||
|
|
||||||
|
status = psa_import_key(&priv_key_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
|
ESP_LOGE(TAG, "Failed to import private key!");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t signature[2 * ECDSA_SECP256R1_KEY_LEN];
|
||||||
|
size_t signature_len = 0;
|
||||||
|
status = psa_sign_hash(priv_key_id, alg, msg_digest, msg_digest_len, signature, sizeof(signature), &signature_len);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
ESP_LOGE(TAG, "Failed to generate signature!");
|
ESP_LOGE(TAG, "Failed to generate signature!");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOG_BUFFER_HEX("Signature", &sign, sizeof(sign));
|
ESP_LOG_BUFFER_HEX("Signature", signature, signature_len);
|
||||||
|
|
||||||
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {};
|
uint8_t pub_key[2 * ECDSA_SECP256R1_KEY_LEN + 1];
|
||||||
err = esp_tee_sec_storage_ecdsa_get_pubkey(&cfg, &pubkey);
|
size_t pub_key_len = 0;
|
||||||
if (err != ESP_OK) {
|
status = psa_export_public_key(priv_key_id, pub_key, sizeof(pub_key), &pub_key_len);
|
||||||
|
if (status != PSA_SUCCESS) {
|
||||||
ESP_LOGE(TAG, "Failed to fetch public-key!");
|
ESP_LOGE(TAG, "Failed to fetch public-key!");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = verify_ecdsa_secp256r1_sign(msg_digest, msg_digest_len, &pubkey, &sign);
|
err = verify_ecdsa_secp256r1_sign(msg_digest, msg_digest_len, pub_key, pub_key_len, signature, signature_len);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to verify signature!");
|
ESP_LOGE(TAG, "Failed to verify signature!");
|
||||||
goto exit;
|
goto exit;
|
||||||
@@ -132,6 +151,8 @@ static void example_tee_sec_stg_sign_verify(void *pvParameter)
|
|||||||
ESP_LOGI(TAG, "Signature verified successfully!");
|
ESP_LOGI(TAG, "Signature verified successfully!");
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
psa_destroy_key(priv_key_id);
|
||||||
|
psa_reset_key_attributes(&priv_key_attr);
|
||||||
vTaskDelete(NULL);
|
vTaskDelete(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user