mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-27 07:48:07 +03:00
feat(ecdsa): support software key as a key source for esp32s31
Starting from the ESP32-S31, the ECDSA peripheral can use a private key written into its key registers by software, in addition to the eFuse and Key Manager key sources.
This commit is contained in:
committed by
Ashish Sharma
parent
421cdd4d15
commit
363426cbc9
@@ -856,6 +856,15 @@ bool esp_efuse_is_ecdsa_p192_curve_supported(void);
|
||||
* This function checks if the current eFuse configuration supports 256-bit ECDSA curve operations.
|
||||
*/
|
||||
bool esp_efuse_is_ecdsa_p256_curve_supported(void);
|
||||
|
||||
/**
|
||||
* @brief Checks if a software-supplied ECDSA private key is allowed as a key source.
|
||||
*
|
||||
* This function checks if the eFuse configuration allows the ECDSA peripheral to use
|
||||
* a private key written into its key registers by software. Returns false if the chip
|
||||
* does not support a software key source or if it has been permanently disabled by eFuse.
|
||||
*/
|
||||
bool esp_efuse_is_ecdsa_software_key_allowed(void);
|
||||
#endif /* SOC_ECDSA_SUPPORTED*/
|
||||
|
||||
#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED
|
||||
|
||||
@@ -122,6 +122,15 @@ bool esp_efuse_is_ecdsa_p256_curve_supported(void)
|
||||
return true;
|
||||
#endif /* SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED */
|
||||
}
|
||||
|
||||
bool esp_efuse_is_ecdsa_software_key_allowed(void)
|
||||
{
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
return !esp_efuse_read_field_bit(ESP_EFUSE_ECDSA_DISABLE_SOFT_K);
|
||||
#else
|
||||
return false;
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORTED */
|
||||
|
||||
#if SOC_ECDSA_P192_CURVE_DEFAULT_DISABLED
|
||||
|
||||
@@ -39,8 +39,25 @@ void ecdsa_hal_set_efuse_key(ecdsa_curve_t curve, int efuse_blk)
|
||||
|
||||
static void configure_ecdsa_periph(ecdsa_hal_config_t *conf)
|
||||
{
|
||||
bool use_hw_key = true;
|
||||
|
||||
if (conf->use_km_key == 0) {
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
if (conf->use_sw_key) {
|
||||
HAL_ASSERT(conf->sw_key != NULL && "Software key not provided");
|
||||
HAL_ASSERT(!conf->use_km_key && "Software key and Key Manager key are mutually exclusive");
|
||||
|
||||
/* The key itself can only be written during the LOAD state of the operation,
|
||||
* so it is written by the operation functions, not here */
|
||||
ecdsa_ll_set_key_source(ECDSA_KEY_SOURCE_SOFTWARE);
|
||||
use_hw_key = false;
|
||||
} else {
|
||||
/* The hardware defaults to the software key source, so the hardware
|
||||
* key source must be selected explicitly */
|
||||
ecdsa_ll_set_key_source(ECDSA_KEY_SOURCE_HARDWARE);
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
|
||||
if (use_hw_key && conf->use_km_key == 0) {
|
||||
|
||||
ecdsa_hal_set_efuse_key(conf->curve, conf->efuse_key_blk);
|
||||
|
||||
@@ -49,8 +66,7 @@ static void configure_ecdsa_periph(ecdsa_hal_config_t *conf)
|
||||
key_mgr_hal_set_key_usage(ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_USE_EFUSE_KEY);
|
||||
#endif
|
||||
}
|
||||
#if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY
|
||||
else {
|
||||
else if (use_hw_key) {
|
||||
if (!key_mgr_ll_is_supported()) {
|
||||
HAL_ASSERT(false && "Key manager is not supported");
|
||||
}
|
||||
@@ -83,7 +99,7 @@ bool ecdsa_hal_get_operation_result(void)
|
||||
return ecdsa_ll_get_operation_result();
|
||||
}
|
||||
|
||||
static void ecdsa_hal_gen_signature_inner(const uint8_t *hash, uint8_t *r_out,
|
||||
static void ecdsa_hal_gen_signature_inner(ecdsa_hal_config_t *conf, const uint8_t *hash, uint8_t *r_out,
|
||||
uint8_t *s_out, uint16_t len)
|
||||
{
|
||||
ecdsa_ll_set_stage(ECDSA_STAGE_START_CALC);
|
||||
@@ -92,6 +108,13 @@ static void ecdsa_hal_gen_signature_inner(const uint8_t *hash, uint8_t *r_out,
|
||||
;
|
||||
}
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
/* The key registers only accept writes while the peripheral is in the LOAD state */
|
||||
if (conf->use_sw_key) {
|
||||
ecdsa_ll_write_key(conf->sw_key, len);
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
|
||||
ecdsa_ll_write_param(ECDSA_PARAM_Z, hash, len);
|
||||
|
||||
ecdsa_ll_set_stage(ECDSA_STAGE_LOAD_DONE);
|
||||
@@ -111,7 +134,7 @@ static void ecdsa_hal_gen_signature_inner(const uint8_t *hash, uint8_t *r_out,
|
||||
}
|
||||
|
||||
#if HAL_CONFIG(ECDSA_GEN_SIG_CM)
|
||||
__attribute__((optimize("O0"))) static void ecdsa_hal_gen_signature_with_countermeasure(const uint8_t *hash, uint8_t *r_out,
|
||||
__attribute__((optimize("O0"))) static void ecdsa_hal_gen_signature_with_countermeasure(ecdsa_hal_config_t *conf, const uint8_t *hash, uint8_t *r_out,
|
||||
uint8_t *s_out, uint16_t len)
|
||||
{
|
||||
uint8_t tmp_r_out[32] = {};
|
||||
@@ -126,15 +149,15 @@ __attribute__((optimize("O0"))) static void ecdsa_hal_gen_signature_with_counter
|
||||
esp_fill_random(tmp_hash, 64);
|
||||
/* Dummy ecdsa signature operations prior to the actual one */
|
||||
for (int i = 0; i < dummy_op_count_prior; i++) {
|
||||
ecdsa_hal_gen_signature_inner(tmp_hash + ((6 * i) % 32), (uint8_t *) tmp_r_out, (uint8_t *) tmp_s_out, len);
|
||||
ecdsa_hal_gen_signature_inner(conf, tmp_hash + ((6 * i) % 32), (uint8_t *) tmp_r_out, (uint8_t *) tmp_s_out, len);
|
||||
}
|
||||
|
||||
/* Actual ecdsa signature operation */
|
||||
ecdsa_hal_gen_signature_inner(hash, r_out, s_out, len);
|
||||
ecdsa_hal_gen_signature_inner(conf, hash, r_out, s_out, len);
|
||||
|
||||
/* Dummy ecdsa signature operations after the actual one */
|
||||
for (int i = 0; i < dummy_op_count_later; i++) {
|
||||
ecdsa_hal_gen_signature_inner(tmp_hash + ((6 * i) % 32), (uint8_t *)tmp_r_out, (uint8_t *)tmp_s_out, len);
|
||||
ecdsa_hal_gen_signature_inner(conf, tmp_hash + ((6 * i) % 32), (uint8_t *)tmp_r_out, (uint8_t *)tmp_s_out, len);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -164,15 +187,14 @@ void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash,
|
||||
#if HAL_CONFIG(ECDSA_GEN_SIG_CM)
|
||||
#if SOC_IS(ESP32H2)
|
||||
if (!ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 102)) {
|
||||
ecdsa_hal_gen_signature_with_countermeasure(hash, r_out, s_out, len);
|
||||
ecdsa_hal_gen_signature_with_countermeasure(conf, hash, r_out, s_out, len);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
ecdsa_hal_gen_signature_with_countermeasure(hash, r_out, s_out, len);
|
||||
ecdsa_hal_gen_signature_with_countermeasure(conf, hash, r_out, s_out, len);
|
||||
#else /* HAL_CONFIG_ECDSA_GEN_SIG_CM */
|
||||
ecdsa_hal_gen_signature_inner(hash, r_out, s_out, len);
|
||||
ecdsa_hal_gen_signature_inner(conf, hash, r_out, s_out, len);
|
||||
#endif /* !HAL_CONFIG_ECDSA_GEN_SIG_CM */
|
||||
|
||||
}
|
||||
|
||||
int ecdsa_hal_verify_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, const uint8_t *r, const uint8_t *s,
|
||||
@@ -238,6 +260,13 @@ void ecdsa_hal_export_pubkey(ecdsa_hal_config_t *conf, uint8_t *pub_x, uint8_t *
|
||||
;
|
||||
}
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
/* The key registers only accept writes while the peripheral is in the LOAD state */
|
||||
if (conf->use_sw_key) {
|
||||
ecdsa_ll_write_key(conf->sw_key, len);
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
|
||||
ecdsa_ll_set_stage(ECDSA_STAGE_LOAD_DONE);
|
||||
|
||||
while (ecdsa_ll_get_state() != ECDSA_STATE_GET) {
|
||||
|
||||
@@ -64,6 +64,17 @@ typedef enum {
|
||||
ECDSA_SHA_256
|
||||
} ecdsa_ll_sha_type_t;
|
||||
|
||||
/**
|
||||
* @brief Source of the ECDSA private key
|
||||
*/
|
||||
typedef enum {
|
||||
ECDSA_KEY_SOURCE_HARDWARE, /* Key supplied by eFuse or the Key Manager peripheral */
|
||||
ECDSA_KEY_SOURCE_SOFTWARE, /* Key written into the ECDSA key registers by software */
|
||||
} ecdsa_ll_key_source_t;
|
||||
|
||||
/* Total size of the ECDSA_KEY_0..ECDSA_KEY_11 register bank */
|
||||
#define ECDSA_LL_KEY_REG_BYTES 48
|
||||
|
||||
/**
|
||||
* @brief Operation modes of SHA
|
||||
*/
|
||||
@@ -188,13 +199,9 @@ static inline void ecdsa_ll_set_mode(ecdsa_mode_t mode)
|
||||
break;
|
||||
case ECDSA_MODE_SIGN_GEN:
|
||||
REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 1);
|
||||
// TODO: IDF-15656 support software key as key source
|
||||
REG_SET_BIT(ECDSA_CONF_REG, ECDSA_USE_HARDWARE_KEY);
|
||||
break;
|
||||
case ECDSA_MODE_EXPORT_PUBKEY:
|
||||
REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 2);
|
||||
// TODO: IDF-15656 support software key as key source
|
||||
REG_SET_BIT(ECDSA_CONF_REG, ECDSA_USE_HARDWARE_KEY);
|
||||
break;
|
||||
default:
|
||||
HAL_ASSERT(false && "Unsupported mode");
|
||||
@@ -202,6 +209,51 @@ static inline void ecdsa_ll_set_mode(ecdsa_mode_t mode)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the source of the ECDSA private key
|
||||
*
|
||||
* @note The hardware default is the software key source, thus the key source
|
||||
* must be configured explicitly for every operation.
|
||||
*
|
||||
* @param source Source of the private key
|
||||
*/
|
||||
static inline void ecdsa_ll_set_key_source(ecdsa_ll_key_source_t source)
|
||||
{
|
||||
if (source == ECDSA_KEY_SOURCE_SOFTWARE) {
|
||||
REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_USE_HARDWARE_KEY);
|
||||
} else {
|
||||
REG_SET_BIT(ECDSA_CONF_REG, ECDSA_USE_HARDWARE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the software private key into the ECDSA key registers
|
||||
*
|
||||
* @note The key registers only accept writes while the peripheral is in the
|
||||
* LOAD state (writes are silently ignored otherwise), so this must be
|
||||
* called between the START_CALC and LOAD_DONE stages of an operation.
|
||||
* The registers retain the key after the operation and only a module
|
||||
* reset clears them, so the peripheral must be reset after a
|
||||
* software-key operation to avoid leaking the key.
|
||||
*
|
||||
* @param key Private key in little-endian format
|
||||
* @param len Length of the key in bytes (24, 32 or 48 depending on the curve)
|
||||
*/
|
||||
static inline void ecdsa_ll_write_key(const uint8_t *key, uint16_t len)
|
||||
{
|
||||
HAL_ASSERT(((len % 4) == 0) && (len <= ECDSA_LL_KEY_REG_BYTES));
|
||||
uint32_t word;
|
||||
uint16_t i = 0;
|
||||
for (; i < len; i += 4) {
|
||||
memcpy(&word, key + i, 4);
|
||||
REG_WRITE(ECDSA_KEY_0_REG + i, word);
|
||||
}
|
||||
/* Zero out the remaining key registers for keys shorter than P-384 */
|
||||
for (; i < ECDSA_LL_KEY_REG_BYTES; i += 4) {
|
||||
REG_WRITE(ECDSA_KEY_0_REG + i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set curve for ECDSA operation
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -42,6 +42,13 @@ typedef struct {
|
||||
ecdsa_sha_mode_t sha_mode; /* Source of SHA that needs to be signed */
|
||||
int efuse_key_blk; /*!< 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 */
|
||||
bool use_km_key; /* Use an ECDSA key from the Key Manager peripheral */
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
bool use_sw_key; /* Use a software-supplied private key written into the ECDSA key registers.
|
||||
* The key registers retain the key after the operation, so the caller must
|
||||
* reset the ECDSA peripheral once done to scrub the key material (releasing
|
||||
* the peripheral with esp_crypto_ecdsa_enable_periph_clk() takes care of it). */
|
||||
const uint8_t *sw_key; /* Private key in little-endian format, length equal to the curve component length (24/32/48 bytes). Only used when use_sw_key is set */
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
ecdsa_sign_type_t sign_type; /* Type of signature generation */
|
||||
uint16_t loop_number; /* Determines the loop number value in deterministic derivation algorithm to derive K.
|
||||
* When using mbedtls APIs, this member of the config does not need any explicit
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -36,6 +36,13 @@ static void run_all_tests(void)
|
||||
RUN_TEST_GROUP(key_manager);
|
||||
#endif
|
||||
|
||||
#if (CONFIG_SOC_ECDSA_SUPPORTED && CONFIG_CRYPTO_TEST_APP_ENABLE_FPGA_TESTS && CONFIG_CRYPTO_TEST_APP_ENABLE_ECDSA_TESTS) \
|
||||
|| CONFIG_SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
/* The eFuse-key test cases additionally need CONFIG_CRYPTO_TEST_APP_ENABLE_ECDSA_TESTS,
|
||||
* see the gating inside the group runner; the software-key test cases need no eFuse */
|
||||
RUN_TEST_GROUP(ecdsa)
|
||||
#endif
|
||||
|
||||
#if CONFIG_CRYPTO_TEST_APP_ENABLE_FPGA_TESTS
|
||||
|
||||
#if CONFIG_SOC_HMAC_SUPPORTED && CONFIG_CRYPTO_TEST_APP_ENABLE_HMAC_TESTS
|
||||
@@ -46,10 +53,6 @@ static void run_all_tests(void)
|
||||
RUN_TEST_GROUP(ds);
|
||||
#endif
|
||||
|
||||
#if CONFIG_SOC_ECDSA_SUPPORTED && CONFIG_CRYPTO_TEST_APP_ENABLE_ECDSA_TESTS
|
||||
RUN_TEST_GROUP(ecdsa)
|
||||
#endif
|
||||
|
||||
#if CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES && CONFIG_CRYPTO_TEST_APP_ENABLE_XTS_AES_TESTS
|
||||
RUN_TEST_GROUP(xts_aes)
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
@@ -116,3 +116,31 @@ uint8_t ecdsa384_pub_y[] = {
|
||||
0xd1, 0xf1, 0x81, 0x70, 0x7c, 0xce, 0x42, 0xf3,
|
||||
0x3d, 0xa1, 0x64, 0x84, 0x91, 0xac, 0xee, 0xf7,
|
||||
};
|
||||
|
||||
/* Private keys from the ecdsa*_priv_key.pem files in this directory,
|
||||
* for targets that support a software-supplied ECDSA key */
|
||||
|
||||
/* Little endian */
|
||||
uint8_t ecdsa192_priv[] = {
|
||||
0x92, 0x65, 0x26, 0x4f, 0x58, 0x5e, 0x97, 0xbb,
|
||||
0x67, 0x27, 0x51, 0x3c, 0xd3, 0xb7, 0xe6, 0x47,
|
||||
0x78, 0x7c, 0xfe, 0x1c, 0x9e, 0xfc, 0xaf, 0xd6,
|
||||
};
|
||||
|
||||
/* Little endian */
|
||||
uint8_t ecdsa256_priv[] = {
|
||||
0xf3, 0x47, 0x2b, 0x4c, 0xcf, 0xc7, 0xcb, 0x20,
|
||||
0x30, 0x73, 0x10, 0xa3, 0x7f, 0x6d, 0x7e, 0x24,
|
||||
0x3d, 0x36, 0x00, 0x3a, 0x48, 0x4b, 0xac, 0xd1,
|
||||
0x2e, 0x36, 0x15, 0x3e, 0x32, 0x63, 0x25, 0x11,
|
||||
};
|
||||
|
||||
/* Little endian */
|
||||
uint8_t ecdsa384_priv[] = {
|
||||
0x1f, 0x0f, 0x67, 0x51, 0xfe, 0xa6, 0x0d, 0xab,
|
||||
0x02, 0xf3, 0x43, 0x01, 0x47, 0xfd, 0xc5, 0x6b,
|
||||
0x65, 0x01, 0x7f, 0x19, 0xb6, 0xb7, 0x1c, 0xa0,
|
||||
0x41, 0x12, 0x2f, 0xe6, 0x04, 0xc2, 0xc6, 0x6e,
|
||||
0x74, 0xe1, 0x03, 0xb4, 0x2f, 0xd5, 0xec, 0xb8,
|
||||
0xe4, 0xe4, 0x87, 0xb1, 0x71, 0xd3, 0x24, 0x25,
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "esp_crypto_lock.h"
|
||||
#include "esp_efuse_chip.h"
|
||||
#include "esp_crypto_periph_clk.h"
|
||||
#include "esp_private/esp_crypto_lock_internal.h"
|
||||
#include "esp_random.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_efuse.h"
|
||||
@@ -143,7 +144,7 @@ static void test_ecdsa_corrupt_data(ecdsa_curve_t curve, uint8_t* sha, uint8_t*
|
||||
pub_y[r_bit / 8] ^= 1 << (r_bit % 8);
|
||||
}
|
||||
|
||||
void test_ecdsa_sign(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key, ecdsa_sign_type_t k_type)
|
||||
void test_ecdsa_sign(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key, ecdsa_sign_type_t k_type, const uint8_t *sw_key)
|
||||
{
|
||||
uint8_t sha_le[48] = {0};
|
||||
uint8_t zeroes[48] = {0};
|
||||
@@ -159,6 +160,14 @@ void test_ecdsa_sign(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t*
|
||||
.use_km_key = use_km_key,
|
||||
.sign_type = k_type,
|
||||
};
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
if (sw_key) {
|
||||
conf.use_sw_key = true;
|
||||
conf.sw_key = sw_key;
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
|
||||
switch (curve) {
|
||||
case ECDSA_CURVE_SECP192R1:
|
||||
conf.curve = ECDSA_CURVE_SECP192R1;
|
||||
@@ -219,16 +228,16 @@ void test_ecdsa_sign(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t*
|
||||
ecdsa_disable();
|
||||
}
|
||||
|
||||
void test_ecdsa_sign_and_verify(ecdsa_curve_t curve, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key, ecdsa_sign_type_t k_type)
|
||||
void test_ecdsa_sign_and_verify(ecdsa_curve_t curve, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key, ecdsa_sign_type_t k_type, const uint8_t *sw_key)
|
||||
{
|
||||
uint8_t r_le[48] = {0};
|
||||
uint8_t s_le[48] = {0};
|
||||
test_ecdsa_sign(curve, sha, r_le, s_le, use_km_key, k_type);
|
||||
test_ecdsa_sign(curve, sha, r_le, s_le, use_km_key, k_type, sw_key);
|
||||
TEST_ASSERT_EQUAL(0, test_ecdsa_verify(curve, sha, r_le, s_le, pub_x, pub_y));
|
||||
}
|
||||
|
||||
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
|
||||
void test_ecdsa_export_pubkey_inner(ecdsa_curve_t curve, uint8_t *exported_pub_x, uint8_t *exported_pub_y, bool use_km_key, uint16_t *len)
|
||||
void test_ecdsa_export_pubkey_inner(ecdsa_curve_t curve, uint8_t *exported_pub_x, uint8_t *exported_pub_y, bool use_km_key, const uint8_t *sw_key, uint16_t *len)
|
||||
{
|
||||
uint8_t zeroes[48] = {0};
|
||||
ecdsa_hal_config_t conf = {
|
||||
@@ -236,6 +245,13 @@ void test_ecdsa_export_pubkey_inner(ecdsa_curve_t curve, uint8_t *exported_pub_x
|
||||
.use_km_key = use_km_key,
|
||||
};
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
if (sw_key) {
|
||||
conf.use_sw_key = true;
|
||||
conf.sw_key = sw_key;
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
|
||||
switch (curve) {
|
||||
case ECDSA_CURVE_SECP192R1:
|
||||
conf.curve = ECDSA_CURVE_SECP192R1;
|
||||
@@ -279,12 +295,12 @@ void test_ecdsa_export_pubkey_inner(ecdsa_curve_t curve, uint8_t *exported_pub_x
|
||||
|
||||
ecdsa_disable();
|
||||
}
|
||||
void test_ecdsa_export_pubkey(ecdsa_curve_t curve, uint8_t *ecdsa_pub_x, uint8_t *ecdsa_pub_y, bool use_km_key)
|
||||
void test_ecdsa_export_pubkey(ecdsa_curve_t curve, uint8_t *ecdsa_pub_x, uint8_t *ecdsa_pub_y, bool use_km_key, const uint8_t *sw_key)
|
||||
{
|
||||
uint8_t pub_x[48] = {0};
|
||||
uint8_t pub_y[48] = {0};
|
||||
uint16_t len;
|
||||
test_ecdsa_export_pubkey_inner(curve, pub_x, pub_y, use_km_key, &len);
|
||||
test_ecdsa_export_pubkey_inner(curve, pub_x, pub_y, use_km_key, sw_key, &len);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa_pub_x, pub_x, len);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(ecdsa_pub_y, pub_y, len);
|
||||
@@ -321,7 +337,7 @@ TEST(ecdsa, ecdsa_SECP192R1_sign_and_verify)
|
||||
} else if (!esp_efuse_is_ecdsa_p192_curve_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled.");
|
||||
} else {
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_TRNG);
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_TRNG, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +362,7 @@ TEST(ecdsa, ecdsa_SECP256R1_sign_and_verify)
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA is not supported.");
|
||||
} else {
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_TRNG);
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_TRNG, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,7 +385,7 @@ TEST(ecdsa, ecdsa_SECP192R1_det_sign_and_verify)
|
||||
} else if (!esp_efuse_is_ecdsa_p192_curve_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled.");
|
||||
} else {
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC);
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP192R1, sha, ecdsa192_pub_x, ecdsa192_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +396,7 @@ TEST(ecdsa, ecdsa_SECP256R1_det_sign_and_verify)
|
||||
} else if (!ecdsa_ll_is_deterministic_mode_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
||||
} else {
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC);
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
|
||||
@@ -393,7 +409,7 @@ TEST(ecdsa, ecdsa_SECP192R1_export_pubkey)
|
||||
} else if (!esp_efuse_is_ecdsa_p192_curve_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled.");
|
||||
} else {
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP192R1, ecdsa192_pub_x, ecdsa192_pub_y, 0);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP192R1, ecdsa192_pub_x, ecdsa192_pub_y, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +418,7 @@ TEST(ecdsa, ecdsa_SECP256R1_export_pubkey)
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA is not supported.");
|
||||
} else {
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP256R1, ecdsa256_pub_x, ecdsa256_pub_y, 0);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP256R1, ecdsa256_pub_x, ecdsa256_pub_y, 0, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
|
||||
@@ -422,7 +438,7 @@ TEST(ecdsa, ecdsa_SECP384R1_sign_and_verify)
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA is not supported.");
|
||||
} else {
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, ECDSA_K_TYPE_TRNG);
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, ECDSA_K_TYPE_TRNG, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,7 +459,7 @@ TEST(ecdsa, ecdsa_SECP384R1_det_sign_and_verify)
|
||||
} else if (!ecdsa_ll_is_deterministic_mode_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
||||
} else {
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC);
|
||||
test_ecdsa_sign_and_verify(ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, ECDSA_K_TYPE_DETERMINISITIC, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
|
||||
@@ -454,14 +470,89 @@ TEST(ecdsa, ecdsa_SECP384R1_export_pubkey)
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA is not supported.");
|
||||
} else {
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP384R1, ecdsa384_pub_x, ecdsa384_pub_y, 0);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP384R1, ecdsa384_pub_x, ecdsa384_pub_y, 0, NULL);
|
||||
}
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
/* Software-key test cases do not need any key burnt in eFuse, so they are kept
|
||||
* in a separate test group that runs without CONFIG_CRYPTO_TEST_APP_ENABLE_ECDSA_TESTS */
|
||||
|
||||
static void test_ecdsa_sw_key_on_curve(ecdsa_curve_t curve, uint8_t *pub_x, uint8_t *pub_y, const uint8_t *priv)
|
||||
{
|
||||
test_ecdsa_sign_and_verify(curve, sha, pub_x, pub_y, false, ECDSA_K_TYPE_TRNG, priv);
|
||||
#ifdef SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
|
||||
test_ecdsa_sign_and_verify(curve, sha, pub_x, pub_y, false, ECDSA_K_TYPE_DETERMINISITIC, priv);
|
||||
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
|
||||
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
|
||||
test_ecdsa_export_pubkey(curve, pub_x, pub_y, 0, priv);
|
||||
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
|
||||
}
|
||||
|
||||
TEST(ecdsa, sw_key_SECP192R1_operations)
|
||||
{
|
||||
if (!esp_efuse_is_ecdsa_software_key_allowed()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA software key is disabled by eFuse.");
|
||||
} else if (!esp_efuse_is_ecdsa_p192_curve_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA 192-curve operations are disabled.");
|
||||
} else {
|
||||
test_ecdsa_sw_key_on_curve(ECDSA_CURVE_SECP192R1, ecdsa192_pub_x, ecdsa192_pub_y, ecdsa192_priv);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ecdsa, sw_key_SECP256R1_operations)
|
||||
{
|
||||
if (!esp_efuse_is_ecdsa_software_key_allowed()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA software key is disabled by eFuse.");
|
||||
} else {
|
||||
test_ecdsa_sw_key_on_curve(ECDSA_CURVE_SECP256R1, ecdsa256_pub_x, ecdsa256_pub_y, ecdsa256_priv);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
TEST(ecdsa, sw_key_SECP384R1_operations)
|
||||
{
|
||||
if (!esp_efuse_is_ecdsa_software_key_allowed()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA software key is disabled by eFuse.");
|
||||
} else {
|
||||
test_ecdsa_sw_key_on_curve(ECDSA_CURVE_SECP384R1, ecdsa384_pub_x, ecdsa384_pub_y, ecdsa384_priv);
|
||||
}
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
|
||||
TEST(ecdsa, sw_key_registers_cleared_after_use)
|
||||
{
|
||||
if (!esp_efuse_is_ecdsa_software_key_allowed()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA software key is disabled by eFuse.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t r_le[48] = {0};
|
||||
uint8_t s_le[48] = {0};
|
||||
test_ecdsa_sign(ECDSA_CURVE_SECP256R1, sha, r_le, s_le, false, ECDSA_K_TYPE_DETERMINISITIC, ecdsa256_priv);
|
||||
|
||||
/* Releasing the peripheral must have scrubbed the key registers.
|
||||
* Re-enable only the bus clock (without the reset that a regular acquire
|
||||
* performs) so that any leftover key material would still be visible. */
|
||||
ECDSA_RCC_ATOMIC() {
|
||||
ecdsa_ll_enable_bus_clock(true);
|
||||
}
|
||||
for (uint16_t i = 0; i < ECDSA_LL_KEY_REG_BYTES; i += 4) {
|
||||
TEST_ASSERT_EQUAL_HEX32(0, REG_READ(ECDSA_KEY_0_REG + i));
|
||||
}
|
||||
ECDSA_RCC_ATOMIC() {
|
||||
ecdsa_ll_enable_bus_clock(false);
|
||||
}
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
|
||||
TEST_GROUP_RUNNER(ecdsa)
|
||||
{
|
||||
/* The following test cases need keys provisioned in eFuse,
|
||||
* see CONFIG_CRYPTO_TEST_APP_ENABLE_ECDSA_TESTS */
|
||||
#if CONFIG_CRYPTO_TEST_APP_ENABLE_FPGA_TESTS && CONFIG_CRYPTO_TEST_APP_ENABLE_ECDSA_TESTS
|
||||
/* SECP192R1 test cases */
|
||||
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_signature_verification)
|
||||
RUN_TEST_CASE(ecdsa, ecdsa_SECP192R1_sign_and_verify)
|
||||
@@ -496,4 +587,15 @@ TEST_GROUP_RUNNER(ecdsa)
|
||||
RUN_TEST_CASE(ecdsa, ecdsa_SECP384R1_export_pubkey)
|
||||
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
#endif /* CONFIG_CRYPTO_TEST_APP_ENABLE_FPGA_TESTS && CONFIG_CRYPTO_TEST_APP_ENABLE_ECDSA_TESTS */
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
/* Software-key test cases need no key provisioned in eFuse */
|
||||
RUN_TEST_CASE(ecdsa, sw_key_SECP192R1_operations)
|
||||
RUN_TEST_CASE(ecdsa, sw_key_SECP256R1_operations)
|
||||
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
RUN_TEST_CASE(ecdsa, sw_key_SECP384R1_operations)
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
RUN_TEST_CASE(ecdsa, sw_key_registers_cleared_after_use)
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
}
|
||||
|
||||
@@ -254,13 +254,13 @@ static void key_mgr_test_xts_aes_256_random_mode(void)
|
||||
|
||||
#if SOC_KEY_MANAGER_ECDSA_KEY_DEPLOY
|
||||
#if SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
|
||||
extern void test_ecdsa_export_pubkey(ecdsa_curve_t curve, uint8_t *ecdsa_pub_x, uint8_t *ecdsa_pub_y, bool use_km_key);
|
||||
extern void test_ecdsa_export_pubkey_inner(ecdsa_curve_t curve, uint8_t *exported_pub_x, uint8_t *exported_pub_y, bool use_km_key, uint16_t *len);
|
||||
extern void test_ecdsa_export_pubkey(ecdsa_curve_t curve, uint8_t *ecdsa_pub_x, uint8_t *ecdsa_pub_y, bool use_km_key, const uint8_t *sw_key);
|
||||
extern void test_ecdsa_export_pubkey_inner(ecdsa_curve_t curve, uint8_t *exported_pub_x, uint8_t *exported_pub_y, bool use_km_key, const uint8_t *sw_key, uint16_t *len);
|
||||
#endif
|
||||
|
||||
extern void test_ecdsa_sign(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key, ecdsa_sign_type_t k_type);
|
||||
extern void test_ecdsa_sign(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, bool use_km_key, ecdsa_sign_type_t k_type, const uint8_t *sw_key);
|
||||
extern int test_ecdsa_verify(ecdsa_curve_t curve, uint8_t* sha, uint8_t* r_le, uint8_t* s_le, uint8_t *pub_x, uint8_t *pub_y);
|
||||
extern void test_ecdsa_sign_and_verify(ecdsa_curve_t curve, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key, ecdsa_sign_type_t k_type);
|
||||
extern void test_ecdsa_sign_and_verify(ecdsa_curve_t curve, uint8_t* sha, uint8_t* pub_x, uint8_t* pub_y, bool use_km_key, ecdsa_sign_type_t k_type, const uint8_t *sw_key);
|
||||
|
||||
/*
|
||||
const uint8_t message[32] = { 0xDF, 0xDE, 0xD7, 0x4A, 0x47, 0xB1, 0x4F, 0x73, 0x00, 0x21, 0x62, 0xC7, 0x66, 0x6D, 0xA3, 0x95, 0x66, 0x19, 0x62, 0x7F, 0x71, 0x7B, 0x3C, 0x66, 0x82, 0xD3, 0x9F, 0x71, 0xAC, 0x9C, 0xC3, 0x39 };
|
||||
@@ -270,9 +270,9 @@ uint8_t sha_digest[48] = { 0xF0, 0x94, 0xC4, 0x4A, 0xF0, 0xEE, 0x68, 0xDB, 0x5B,
|
||||
|
||||
void test_ecdsa_key_aes_mode(ecdsa_curve_t curve, uint8_t *sha_digest, uint8_t *pub_x, uint8_t *pub_y, ecdsa_sign_type_t k_type)
|
||||
{
|
||||
test_ecdsa_sign_and_verify(curve, sha_digest, pub_x, pub_y, 1, k_type);
|
||||
test_ecdsa_sign_and_verify(curve, sha_digest, pub_x, pub_y, 1, k_type, NULL);
|
||||
#ifdef SOC_ECDSA_SUPPORT_EXPORT_PUBKEY
|
||||
test_ecdsa_export_pubkey(curve, pub_x, pub_y, 1);
|
||||
test_ecdsa_export_pubkey(curve, pub_x, pub_y, 1, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ void key_mgr_test_ecdsa_key(esp_key_mgr_key_len_t key_len, ecdsa_sign_type_t k_t
|
||||
return;
|
||||
}
|
||||
|
||||
test_ecdsa_sign(curve, sha_digest, r_le, s_le, 1, k_type);
|
||||
test_ecdsa_sign(curve, sha_digest, r_le, s_le, 1, k_type, NULL);
|
||||
|
||||
ESP_LOG_BUFFER_HEXDUMP("ECDSA message digest", sha_digest, sha_digest_len, ESP_LOG_DEBUG);
|
||||
ESP_LOG_BUFFER_HEXDUMP("ECDSA signature r_le", r_le, sizeof(r_le), ESP_LOG_DEBUG);
|
||||
@@ -315,7 +315,7 @@ void key_mgr_test_ecdsa_key(esp_key_mgr_key_len_t key_len, ecdsa_sign_type_t k_t
|
||||
|
||||
// Export the pubkey from ECDSA peripheral
|
||||
uint16_t pubkey_len = 0;
|
||||
test_ecdsa_export_pubkey_inner(curve, pub_x, pub_y, 1, &pubkey_len);
|
||||
test_ecdsa_export_pubkey_inner(curve, pub_x, pub_y, 1, NULL, &pubkey_len);
|
||||
|
||||
ESP_LOG_BUFFER_HEXDUMP("ECDSA key pubx", pub_x, pubkey_len, ESP_LOG_DEBUG);
|
||||
ESP_LOG_BUFFER_HEXDUMP("ECDSA key puby", pub_y, pubkey_len, ESP_LOG_DEBUG);
|
||||
@@ -407,11 +407,11 @@ static void key_mgr_test_ecdsa_key_ecdh0_mode(esp_key_mgr_key_len_t key_len)
|
||||
if (key_len == ESP_KEY_MGR_ECDSA_LEN_256) {
|
||||
uint8_t pub_x_le[32], pub_y_le[32];
|
||||
km_verify_ecdsa_pubkey_from_scalar(P256_LEN, x_be_stage0, 32, pub_x_le, pub_y_le);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP256R1, pub_x_le, pub_y_le, 1);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP256R1, pub_x_le, pub_y_le, 1, NULL);
|
||||
} else if (key_len == ESP_KEY_MGR_ECDSA_LEN_192) {
|
||||
uint8_t pub_x_le[24], pub_y_le[24];
|
||||
km_verify_ecdsa_pubkey_from_scalar(P192_LEN, x_be_stage0 + 8, 24, pub_x_le, pub_y_le);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP192R1, pub_x_le, pub_y_le, 1);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP192R1, pub_x_le, pub_y_le, 1, NULL);
|
||||
}
|
||||
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
else if (key_len == ESP_KEY_MGR_ECDSA_LEN_384) {
|
||||
@@ -423,7 +423,7 @@ static void key_mgr_test_ecdsa_key_ecdh0_mode(esp_key_mgr_key_len_t key_len)
|
||||
memcpy(scalar_be + 16, x_be_stage1, 32);
|
||||
uint8_t pub_x_le[48], pub_y_le[48];
|
||||
km_verify_ecdsa_pubkey_from_scalar(P384_LEN, scalar_be, 48, pub_x_le, pub_y_le);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP384R1, pub_x_le, pub_y_le, 1);
|
||||
test_ecdsa_export_pubkey(ECDSA_CURVE_SECP384R1, pub_x_le, pub_y_le, 1, NULL);
|
||||
}
|
||||
#endif
|
||||
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
|
||||
|
||||
@@ -179,6 +179,15 @@ void esp_crypto_ecdsa_enable_periph_clk(bool enable)
|
||||
esp_crypto_common_clk_enable(true);
|
||||
}
|
||||
ECDSA_RCC_ATOMIC() {
|
||||
esp_crypto_common_clk_enable(enable);
|
||||
#if SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
/* The ECDSA key registers retain a software-supplied key after an
|
||||
* operation and ignore direct writes outside of an operation, so the
|
||||
* peripheral is reset before release to scrub any key material */
|
||||
if (!enable) {
|
||||
ecdsa_ll_reset_register();
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_SOFTWARE_KEY */
|
||||
ecdsa_ll_enable_bus_clock(enable);
|
||||
if (enable) {
|
||||
ecdsa_ll_reset_register();
|
||||
|
||||
@@ -472,8 +472,14 @@ if(CONFIG_SOC_ECC_SUPPORTED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN)
|
||||
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY
|
||||
OR CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN OR CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_SOFTWARE_KEY)
|
||||
target_sources(tfpsacrypto PRIVATE "${COMPONENT_DIR}/port/psa_driver/esp_ecdsa/psa_crypto_driver_esp_ecdsa.c")
|
||||
if(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_SOFTWARE_KEY)
|
||||
target_sources(tfpsacrypto PRIVATE
|
||||
"${COMPONENT_DIR}/port/psa_driver/esp_ecdsa/psa_crypto_driver_esp_ecdsa_transparent.c"
|
||||
)
|
||||
endif()
|
||||
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)
|
||||
|
||||
@@ -1347,6 +1347,22 @@ menu "mbedTLS"
|
||||
The key should be burnt in little endian format. espefuse utility handles it internally
|
||||
but care needs to be taken while burning using esp_efuse APIs
|
||||
|
||||
config MBEDTLS_HARDWARE_ECDSA_SIGN_SOFTWARE_KEY
|
||||
bool "Enable ECDSA signing with software keys using the on-chip ECDSA peripheral"
|
||||
default y
|
||||
depends on SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
help
|
||||
Enable hardware accelerated ECDSA signing with plaintext keys using the
|
||||
ECDSA peripheral's software key source.
|
||||
|
||||
Unlike MBEDTLS_HARDWARE_ECDSA_SIGN, this does not require the private key
|
||||
to be provisioned in an eFuse key block or the Key Manager: any ECC key
|
||||
pair imported through the PSA API is signed by the peripheral.
|
||||
|
||||
Note that deterministic signatures generated by the peripheral use its own
|
||||
deterministic K derivation, which is not RFC 6979. Disable this option if
|
||||
strict RFC 6979 deterministic signatures are required.
|
||||
|
||||
config MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
|
||||
bool "Enable ECDSA signing using TEE secure storage"
|
||||
default y
|
||||
|
||||
Submodule components/mbedtls/mbedtls updated: ce3f3485a1...f5c91881be
@@ -270,7 +270,8 @@
|
||||
#define MBEDTLS_MPI_PRIME_SIEVE_VARIABLE_TIME
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) || defined(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN) || defined(CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN)
|
||||
#if defined(CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) || defined(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN) \
|
||||
|| defined(CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN) || defined(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_SOFTWARE_KEY)
|
||||
#define ESP_ECDSA_DRIVER_ENABLED
|
||||
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY
|
||||
#define ESP_ECDSA_VERIFY_DRIVER_ENABLED
|
||||
@@ -278,6 +279,11 @@
|
||||
#if defined(CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN) || defined(CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN)
|
||||
#define ESP_ECDSA_SIGN_DRIVER_ENABLED
|
||||
#endif
|
||||
#ifdef CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_SOFTWARE_KEY
|
||||
/* Accelerate signing with plaintext (transparent) keys using the ECDSA
|
||||
* peripheral's software key source */
|
||||
#define ESP_ECDSA_TRANSPARENT_SIGN_DRIVER_ENABLED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_SECURE_ELEMENT_DRIVER_ENABLED
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "psa/crypto.h"
|
||||
#include "hal/ecdsa_types.h"
|
||||
#include "psa_crypto_driver_esp_ecdsa_contexts.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Reverse the byte order of a buffer (the ECDSA peripheral uses little endian)
|
||||
*/
|
||||
void esp_ecdsa_change_endianness(const uint8_t *old_point, uint8_t *new_point, uint8_t len);
|
||||
|
||||
/**
|
||||
* @brief Map a key length in bytes to the driver's curve enum
|
||||
*/
|
||||
esp_ecdsa_curve_t esp_ecdsa_bits_to_curve(size_t key_len);
|
||||
|
||||
/**
|
||||
* @brief Check that the hash algorithm matches the curve
|
||||
*/
|
||||
psa_status_t esp_ecdsa_validate_sha_alg(psa_algorithm_t alg, const esp_ecdsa_curve_t curve);
|
||||
|
||||
/**
|
||||
* @brief Map the driver's curve enum to the HAL's curve enum
|
||||
*/
|
||||
ecdsa_curve_t esp_ecdsa_curve_to_hal_curve(esp_ecdsa_curve_t curve);
|
||||
|
||||
/**
|
||||
* @brief Acquire the ECDSA hardware (locks and peripheral clocks)
|
||||
*/
|
||||
void esp_ecdsa_acquire_hardware(void);
|
||||
|
||||
/**
|
||||
* @brief Release the ECDSA hardware
|
||||
*/
|
||||
void esp_ecdsa_release_hardware(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -46,6 +46,7 @@
|
||||
#endif /* SOC_MPI_SUPPORTED && SOC_ECDSA_USES_MPI */
|
||||
|
||||
#include "psa_crypto_driver_esp_ecdsa.h"
|
||||
#include "include/psa_crypto_driver_esp_ecdsa_utilities.h"
|
||||
#include "psa_crypto_driver_esp_opaque_common.h"
|
||||
#include "psa_crypto_driver_wrappers_no_static.h"
|
||||
#include "sdkconfig.h"
|
||||
@@ -244,7 +245,7 @@ static psa_status_t esp_ecdsa_get_expected_storage_size(const uint8_t *key_buffe
|
||||
#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)
|
||||
esp_ecdsa_curve_t esp_ecdsa_bits_to_curve(size_t key_len)
|
||||
{
|
||||
switch (key_len) {
|
||||
case ECDSA_KEY_LEN_P192:
|
||||
@@ -260,11 +261,12 @@ static esp_ecdsa_curve_t psa_bits_to_ecdsa_curve(size_t key_len)
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || (CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN && SOC_ECDSA_SUPPORT_EXPORT_PUBKEY)
|
||||
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || defined(ESP_ECDSA_TRANSPARENT_SIGN_DRIVER_ENABLED) \
|
||||
|| (CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN && SOC_ECDSA_SUPPORT_EXPORT_PUBKEY)
|
||||
/**
|
||||
* @brief Map the driver's esp_ecdsa_curve_t enum to the HAL's ecdsa_curve_t enum.
|
||||
*/
|
||||
static ecdsa_curve_t esp_ecdsa_curve_to_hal_curve(esp_ecdsa_curve_t curve)
|
||||
ecdsa_curve_t esp_ecdsa_curve_to_hal_curve(esp_ecdsa_curve_t curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case ESP_ECDSA_CURVE_SECP192R1: return ECDSA_CURVE_SECP192R1;
|
||||
@@ -275,7 +277,7 @@ static ecdsa_curve_t esp_ecdsa_curve_to_hal_curve(esp_ecdsa_curve_t curve)
|
||||
default: return (ecdsa_curve_t)-1;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || (CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN && SOC_ECDSA_SUPPORT_EXPORT_PUBKEY) */
|
||||
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || ESP_ECDSA_TRANSPARENT_SIGN_DRIVER_ENABLED || (CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN && SOC_ECDSA_SUPPORT_EXPORT_PUBKEY) */
|
||||
|
||||
#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)
|
||||
@@ -293,7 +295,7 @@ static esp_tee_sec_storage_type_t esp_ecdsa_curve_to_tee_sec_storage_type(esp_ec
|
||||
}
|
||||
#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */
|
||||
|
||||
static void change_endianess(const uint8_t *old_point, uint8_t *new_point, uint8_t len)
|
||||
void esp_ecdsa_change_endianness(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);
|
||||
@@ -303,7 +305,7 @@ static void change_endianess(const uint8_t *old_point, uint8_t *new_point, uint8
|
||||
}
|
||||
}
|
||||
|
||||
static psa_status_t validate_ecdsa_sha_alg(psa_algorithm_t alg, const esp_ecdsa_curve_t curve)
|
||||
psa_status_t esp_ecdsa_validate_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
|
||||
@@ -381,7 +383,7 @@ cleanup:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void esp_ecdsa_acquire_hardware(void)
|
||||
void esp_ecdsa_acquire_hardware(void)
|
||||
{
|
||||
esp_crypto_ecdsa_lock_acquire();
|
||||
|
||||
@@ -412,7 +414,7 @@ static void esp_ecdsa_acquire_hardware(void)
|
||||
#endif /* SOC_ECDSA_USES_MPI */
|
||||
}
|
||||
|
||||
static void esp_ecdsa_release_hardware(void)
|
||||
void esp_ecdsa_release_hardware(void)
|
||||
{
|
||||
esp_crypto_ecdsa_enable_periph_clk(false);
|
||||
|
||||
@@ -469,12 +471,12 @@ psa_status_t esp_ecdsa_transparent_verify_hash_start(
|
||||
}
|
||||
|
||||
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);
|
||||
esp_ecdsa_curve_t curve = esp_ecdsa_bits_to_curve(key_len);
|
||||
if (curve == ESP_ECDSA_CURVE_MAX) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
status = validate_ecdsa_sha_alg(alg, curve);
|
||||
status = esp_ecdsa_validate_sha_alg(alg, curve);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
@@ -540,8 +542,8 @@ psa_status_t esp_ecdsa_transparent_verify_hash_start(
|
||||
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);
|
||||
esp_ecdsa_change_endianness(public_key_buffer + 1, point.x, key_len);
|
||||
esp_ecdsa_change_endianness(public_key_buffer + 1 + key_len, point.y, key_len);
|
||||
point.len = key_len;
|
||||
|
||||
/* Reject the identity (point at infinity, all-zero coords) explicitly —
|
||||
@@ -563,15 +565,15 @@ psa_status_t esp_ecdsa_transparent_verify_hash_start(
|
||||
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);
|
||||
esp_ecdsa_change_endianness(hash, operation->sha, key_len);
|
||||
esp_ecdsa_change_endianness(signature, operation->r, key_len);
|
||||
esp_ecdsa_change_endianness(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);
|
||||
esp_ecdsa_change_endianness(public_key_buffer + 1, operation->qx, key_len);
|
||||
esp_ecdsa_change_endianness(public_key_buffer + 1 + key_len, operation->qy, key_len);
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
@@ -633,6 +635,7 @@ psa_status_t esp_ecdsa_transparent_verify_hash(
|
||||
esp_ecdsa_transparent_verify_hash_abort(&operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* SOC_ECDSA_SUPPORTED */
|
||||
|
||||
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||
@@ -738,7 +741,7 @@ static psa_status_t validate_ecdsa_opaque_key_attributes(const psa_key_attribute
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
esp_ecdsa_curve_t expected_curve = psa_bits_to_ecdsa_curve(PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)));
|
||||
esp_ecdsa_curve_t expected_curve = esp_ecdsa_bits_to_curve(PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)));
|
||||
|
||||
if (expected_curve == ESP_ECDSA_CURVE_MAX || expected_curve != opaque_key->curve) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
@@ -775,7 +778,7 @@ static psa_status_t validate_storage_curve(const psa_key_attributes_t *attribute
|
||||
PSA_KEY_TYPE_ECC_GET_FAMILY(key_type) != PSA_ECC_FAMILY_SECP_R1) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
esp_ecdsa_curve_t expected_curve = psa_bits_to_ecdsa_curve(PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)));
|
||||
esp_ecdsa_curve_t expected_curve = esp_ecdsa_bits_to_curve(PSA_BITS_TO_BYTES(psa_get_key_bits(attributes)));
|
||||
if (expected_curve == ESP_ECDSA_CURVE_MAX || expected_curve != stored_curve) {
|
||||
ESP_LOGE(TAG, "Invalid curve expected");
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
@@ -941,7 +944,7 @@ psa_status_t esp_ecdsa_opaque_sign_hash_start(
|
||||
return status;
|
||||
}
|
||||
|
||||
status = validate_ecdsa_sha_alg(alg, curve);
|
||||
status = esp_ecdsa_validate_sha_alg(alg, curve);
|
||||
if (status != PSA_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
@@ -979,7 +982,7 @@ psa_status_t esp_ecdsa_opaque_sign_hash_start(
|
||||
} else
|
||||
#endif /* CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN */
|
||||
{
|
||||
change_endianess(hash, operation->sha, component_len);
|
||||
esp_ecdsa_change_endianness(hash, operation->sha, component_len);
|
||||
}
|
||||
|
||||
operation->key_buffer = key_buffer;
|
||||
@@ -1186,9 +1189,9 @@ psa_status_t esp_ecdsa_opaque_sign_hash_complete(
|
||||
#endif /* SOC_KEY_MANAGER_SUPPORTED */
|
||||
|
||||
// Convert r from little-endian to big-endian and copy to output
|
||||
change_endianess(operation->r, signature, component_len);
|
||||
esp_ecdsa_change_endianness(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);
|
||||
esp_ecdsa_change_endianness(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.
|
||||
@@ -1403,10 +1406,10 @@ psa_status_t esp_ecdsa_opaque_export_public_key(
|
||||
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);
|
||||
esp_ecdsa_change_endianness(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);
|
||||
esp_ecdsa_change_endianness(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
|
||||
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* ESP ECDSA PSA Crypto Transparent Sign Driver
|
||||
*
|
||||
* Signs with a plaintext (transparent) SECP-R1 key pair through the ECDSA
|
||||
* peripheral's software key source, available from the ESP32-S31 onwards.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_efuse.h"
|
||||
|
||||
#include "hal/ecdsa_types.h"
|
||||
#include "hal/ecdsa_hal.h"
|
||||
#include "hal/ecdsa_ll.h"
|
||||
|
||||
#include "psa_crypto_driver_esp_ecdsa.h"
|
||||
#include "include/psa_crypto_driver_esp_ecdsa_utilities.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if defined(ESP_ECDSA_TRANSPARENT_SIGN_DRIVER_ENABLED)
|
||||
|
||||
static const char *TAG = "psa_crypto_driver_esp_ecdsa";
|
||||
|
||||
/* Bound for the zero-signature retry loop, in case the peripheral keeps
|
||||
* failing for a given input */
|
||||
#define ESP_ECDSA_SIGN_MAX_ATTEMPTS 16
|
||||
|
||||
psa_status_t esp_ecdsa_transparent_sign_hash_start(
|
||||
esp_ecdsa_transparent_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;
|
||||
}
|
||||
|
||||
/* Any condition the peripheral cannot handle returns PSA_ERROR_NOT_SUPPORTED
|
||||
* so that the PSA core falls back to the builtin implementation */
|
||||
|
||||
// Check if the ECDSA peripheral is supported on this chip revision
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// Check if the software key source has been permanently disabled by eFuse
|
||||
if (!esp_efuse_is_ecdsa_software_key_allowed()) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!PSA_ALG_IS_ECDSA(alg)) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// Only plaintext SECP-R1 key pairs are supported
|
||||
if (psa_get_key_type(attributes) != PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
|
||||
#if SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP
|
||||
if (!ecdsa_ll_is_deterministic_mode_supported()) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
#else
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE && SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP */
|
||||
}
|
||||
|
||||
size_t key_len = PSA_BITS_TO_BYTES(psa_get_key_bits(attributes));
|
||||
esp_ecdsa_curve_t curve = esp_ecdsa_bits_to_curve(key_len);
|
||||
if (curve == ESP_ECDSA_CURVE_MAX) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (curve == ESP_ECDSA_CURVE_SECP192R1 && !esp_efuse_is_ecdsa_p192_curve_supported()) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
psa_status_t status = esp_ecdsa_validate_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;
|
||||
}
|
||||
|
||||
/* A transparent SECP-R1 key pair is stored as the raw private key in big-endian
|
||||
* format. The PSA core has already validated 1 <= key < n at import time. */
|
||||
if (key_buffer_size != key_len) {
|
||||
return PSA_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
memset(operation, 0, sizeof(esp_ecdsa_transparent_sign_hash_operation_t));
|
||||
operation->alg = alg;
|
||||
operation->curve = curve;
|
||||
operation->key_len = key_len;
|
||||
operation->sha_len = hash_length;
|
||||
esp_ecdsa_change_endianness(key_buffer, operation->key, key_len);
|
||||
esp_ecdsa_change_endianness(hash, operation->sha, key_len);
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t esp_ecdsa_transparent_sign_hash_complete(
|
||||
esp_ecdsa_transparent_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;
|
||||
}
|
||||
|
||||
ecdsa_curve_t hal_curve = esp_ecdsa_curve_to_hal_curve(operation->curve);
|
||||
if (hal_curve == (ecdsa_curve_t)-1) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ecdsa_sign_type_t k_type = ECDSA_K_TYPE_TRNG;
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
|
||||
if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) {
|
||||
k_type = ECDSA_K_TYPE_DETERMINISITIC;
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
|
||||
|
||||
uint8_t zeroes[MAX_ECDSA_COMPONENT_LEN] = {0};
|
||||
|
||||
ecdsa_hal_config_t conf = {
|
||||
.mode = ECDSA_MODE_SIGN_GEN,
|
||||
.curve = hal_curve,
|
||||
.sha_mode = ECDSA_Z_USER_PROVIDED,
|
||||
.sign_type = k_type,
|
||||
.use_sw_key = true,
|
||||
.sw_key = operation->key,
|
||||
};
|
||||
|
||||
esp_ecdsa_acquire_hardware();
|
||||
|
||||
bool process_again = false;
|
||||
int attempts = 0;
|
||||
|
||||
do {
|
||||
ecdsa_hal_gen_signature(&conf, operation->sha, operation->r, operation->s, component_len);
|
||||
|
||||
process_again = !ecdsa_hal_get_operation_result()
|
||||
|| !memcmp(operation->r, zeroes, component_len)
|
||||
|| !memcmp(operation->s, zeroes, component_len);
|
||||
} while (process_again && ++attempts < ESP_ECDSA_SIGN_MAX_ATTEMPTS);
|
||||
|
||||
esp_ecdsa_release_hardware();
|
||||
|
||||
if (process_again) {
|
||||
ESP_LOGE(TAG, "Failed to generate an ECDSA signature using the software key");
|
||||
return PSA_ERROR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
// Convert r and s from little-endian to big-endian and copy to output
|
||||
esp_ecdsa_change_endianness(operation->r, signature, component_len);
|
||||
esp_ecdsa_change_endianness(operation->s, signature + component_len, component_len);
|
||||
|
||||
*signature_length = 2 * component_len;
|
||||
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t esp_ecdsa_transparent_sign_hash_abort(esp_ecdsa_transparent_sign_hash_operation_t *operation)
|
||||
{
|
||||
if (operation) {
|
||||
/* Zeroizes the plaintext private key copy held in the operation context */
|
||||
memset(operation, 0, sizeof(esp_ecdsa_transparent_sign_hash_operation_t));
|
||||
}
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
psa_status_t esp_ecdsa_transparent_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_transparent_sign_hash_operation_t operation;
|
||||
|
||||
status = esp_ecdsa_transparent_sign_hash_start(&operation, attributes, key_buffer, key_buffer_size, alg, hash, hash_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
esp_ecdsa_transparent_sign_hash_abort(&operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = esp_ecdsa_transparent_sign_hash_complete(&operation, signature, signature_size, signature_length);
|
||||
if (status != PSA_SUCCESS) {
|
||||
esp_ecdsa_transparent_sign_hash_abort(&operation);
|
||||
return status;
|
||||
}
|
||||
|
||||
return esp_ecdsa_transparent_sign_hash_abort(&operation);
|
||||
}
|
||||
#endif /* ESP_ECDSA_TRANSPARENT_SIGN_DRIVER_ENABLED */
|
||||
@@ -242,6 +242,84 @@ psa_status_t esp_ecdsa_opaque_sign_hash_complete(
|
||||
psa_status_t esp_ecdsa_opaque_sign_hash_abort(
|
||||
esp_ecdsa_opaque_sign_hash_operation_t *operation);
|
||||
|
||||
#if defined(ESP_ECDSA_TRANSPARENT_SIGN_DRIVER_ENABLED)
|
||||
/**
|
||||
* @brief Sign a hash with a plaintext SECP-R1 key pair using the ECDSA peripheral's
|
||||
* software key source
|
||||
*
|
||||
* Returns PSA_ERROR_NOT_SUPPORTED for any key/algorithm combination the peripheral
|
||||
* cannot handle (or when the software key source is disabled by eFuse) so that the
|
||||
* PSA core falls back to the builtin implementation.
|
||||
*
|
||||
* @param attributes Key attributes
|
||||
* @param key_buffer Key buffer holding the raw private key (big endian)
|
||||
* @param key_buffer_size Size of key buffer
|
||||
* @param alg Algorithm
|
||||
* @param hash Hash to sign
|
||||
* @param hash_length Length of hash
|
||||
* @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_transparent_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 Start a hash signing operation using the ESP ECDSA transparent driver
|
||||
*
|
||||
* @param operation Operation context
|
||||
* @param attributes Key attributes
|
||||
* @param key_buffer Key buffer holding the raw private key (big endian)
|
||||
* @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_transparent_sign_hash_start(
|
||||
esp_ecdsa_transparent_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 the ESP ECDSA transparent 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_transparent_sign_hash_complete(
|
||||
esp_ecdsa_transparent_sign_hash_operation_t *operation,
|
||||
uint8_t *signature, size_t signature_size,
|
||||
size_t *signature_length);
|
||||
|
||||
/**
|
||||
* @brief Abort a hash signing operation using the ESP ECDSA transparent driver
|
||||
*
|
||||
* Zeroizes the private key copy held in the operation context.
|
||||
*
|
||||
* @param operation Operation context
|
||||
* @return psa_status_t
|
||||
*/
|
||||
psa_status_t esp_ecdsa_transparent_sign_hash_abort(
|
||||
esp_ecdsa_transparent_sign_hash_operation_t *operation);
|
||||
#endif /* ESP_ECDSA_TRANSPARENT_SIGN_DRIVER_ENABLED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -80,6 +80,20 @@ typedef struct {
|
||||
size_t key_len;
|
||||
bool is_persistent; /**< Cached persistence flag for use in complete */
|
||||
} esp_ecdsa_opaque_sign_hash_operation_t;
|
||||
|
||||
#if defined(ESP_ECDSA_TRANSPARENT_SIGN_DRIVER_ENABLED)
|
||||
/* The buffers are stored in the little-endian format */
|
||||
typedef struct {
|
||||
psa_algorithm_t alg;
|
||||
esp_ecdsa_curve_t curve;
|
||||
uint8_t key[MAX_ECDSA_COMPONENT_LEN]; /**< Plaintext private key copy, zeroized by the abort function */
|
||||
uint8_t r[MAX_ECDSA_COMPONENT_LEN]; /**< Must be 4-byte aligned for ECDSA HAL MMIO reads */
|
||||
uint8_t s[MAX_ECDSA_COMPONENT_LEN];
|
||||
uint8_t sha[MAX_ECDSA_SHA_LEN];
|
||||
size_t sha_len;
|
||||
size_t key_len;
|
||||
} esp_ecdsa_transparent_sign_hash_operation_t;
|
||||
#endif /* ESP_ECDSA_TRANSPARENT_SIGN_DRIVER_ENABLED */
|
||||
#endif /* !(__DOXYGEN__) */
|
||||
#endif /* ESP_ECDSA_DRIVER_ENABLED */
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -391,7 +391,7 @@ TEST_CASE("mbedtls ECDSA signature verification rejects out-of-range r, s on SEC
|
||||
|
||||
#endif /* CONFIG_MBEDTLS_HARDWARE_ECC */
|
||||
|
||||
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_SOFTWARE_KEY
|
||||
#define USE_ECDSA_KEY_FROM_KEY_MANAGER INT_MAX
|
||||
|
||||
/*
|
||||
@@ -424,7 +424,7 @@ const uint8_t k1_ecdsa384_encrypt[] = {
|
||||
0x31, 0xd4, 0x4f, 0xf4, 0xf6, 0x1d, 0xa1, 0xc7, 0x1f, 0x2c, 0x11, 0xca, 0x9f, 0x21, 0x26, 0xaa, 0x37, 0xcf, 0x5b, 0x9e, 0x08, 0x26, 0x36, 0x31, 0xd7, 0x51, 0x3c, 0x33, 0x0d, 0x5d, 0x03, 0xad,
|
||||
};
|
||||
|
||||
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, void *key_recovery_info)
|
||||
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, void *key_recovery_info, const uint8_t *priv_key)
|
||||
{
|
||||
size_t hash_len = HASH_LEN;
|
||||
uint8_t signature[2 * MAX_ECDSA_COMPONENT_LEN];
|
||||
@@ -468,15 +468,23 @@ void test_ecdsa_sign(esp_ecdsa_curve_t curve, const uint8_t *hash, const uint8_t
|
||||
|
||||
psa_algorithm_t alg = (is_deterministic ? PSA_ALG_DETERMINISTIC_ECDSA(sha_alg) : PSA_ALG_ECDSA(sha_alg));
|
||||
|
||||
// Set attributes for opaque private key
|
||||
// Set attributes for the private key
|
||||
psa_set_key_type(&priv_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
|
||||
psa_set_key_bits(&priv_attr, plen);
|
||||
psa_set_key_usage_flags(&priv_attr, PSA_KEY_USAGE_SIGN_HASH);
|
||||
psa_set_key_algorithm(&priv_attr, alg);
|
||||
psa_set_key_lifetime(&priv_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE); // Opaque key
|
||||
|
||||
// Import opaque key reference
|
||||
psa_status_t status = psa_import_key(&priv_attr, (uint8_t*) &opaque_key, sizeof(opaque_key), &priv_key_id);
|
||||
psa_status_t status;
|
||||
if (priv_key) {
|
||||
/* Plaintext key pair with the default (transparent) lifetime, signed
|
||||
* through the ECDSA peripheral's software key source */
|
||||
status = psa_import_key(&priv_attr, priv_key, plen_bytes, &priv_key_id);
|
||||
} else {
|
||||
psa_set_key_lifetime(&priv_attr, PSA_KEY_LIFETIME_ESP_ECDSA_VOLATILE); // Opaque key
|
||||
|
||||
// Import opaque key reference
|
||||
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);
|
||||
|
||||
@@ -493,12 +501,15 @@ void test_ecdsa_sign(esp_ecdsa_curve_t curve, const uint8_t *hash, const uint8_t
|
||||
psa_reset_key_attributes(&priv_attr);
|
||||
}
|
||||
|
||||
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN
|
||||
/* The following test cases need a key provisioned in eFuse or deployed
|
||||
* through the Key Manager */
|
||||
TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][efuse_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, SECP256R1_EFUSE_BLOCK, NULL);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, SECP256R1_EFUSE_BLOCK, NULL, NULL);
|
||||
}
|
||||
|
||||
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
@@ -508,7 +519,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP384R1", "[mbedtls][efuse_ke
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
uint8_t efuse_key_block = HAL_ECDSA_COMBINE_KEY_BLOCKS(SECP384R1_EFUSE_BLOCK_HIGH, SECP384R1_EFUSE_BLOCK_LOW);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, efuse_key_block, NULL);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, efuse_key_block, NULL, NULL);
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
|
||||
@@ -551,7 +562,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP256R1", "[mbedtls][key_mana
|
||||
TEST_ASSERT_NOT_NULL(key_recovery_info);
|
||||
|
||||
deploy_key_in_key_manager(k1_ecdsa256_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_256, key_recovery_info);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x_km, ecdsa256_pub_y_km, false, USE_ECDSA_KEY_FROM_KEY_MANAGER, (void *) key_recovery_info);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x_km, ecdsa256_pub_y_km, false, USE_ECDSA_KEY_FROM_KEY_MANAGER, (void *) key_recovery_info, NULL);
|
||||
free(key_recovery_info);
|
||||
}
|
||||
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
@@ -569,7 +580,7 @@ TEST_CASE("mbedtls ECDSA signature generation on SECP384R1", "[mbedtls][key_mana
|
||||
TEST_ASSERT_NOT_NULL(key_recovery_info);
|
||||
|
||||
deploy_key_in_key_manager(k1_ecdsa384_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_384, key_recovery_info);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x_km, ecdsa384_pub_y_km, false, USE_ECDSA_KEY_FROM_KEY_MANAGER, (void *) key_recovery_info);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x_km, ecdsa384_pub_y_km, false, USE_ECDSA_KEY_FROM_KEY_MANAGER, (void *) key_recovery_info, NULL);
|
||||
free(key_recovery_info);
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
@@ -585,7 +596,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe
|
||||
if (!ecdsa_ll_is_deterministic_mode_supported()) {
|
||||
ESP_LOGI(TAG, "Skipping test because ECDSA deterministic mode is not supported.");
|
||||
} else {
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, true, SECP256R1_EFUSE_BLOCK, NULL);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, true, SECP256R1_EFUSE_BLOCK, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,7 +607,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP384R1", "[mbe
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
uint8_t efuse_key_block = HAL_ECDSA_COMBINE_KEY_BLOCKS(SECP384R1_EFUSE_BLOCK_HIGH, SECP384R1_EFUSE_BLOCK_LOW);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, true, efuse_key_block, NULL);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, true, efuse_key_block, NULL, NULL);
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
|
||||
@@ -618,7 +629,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP256R1", "[mbe
|
||||
TEST_ASSERT_NOT_NULL(key_recovery_info);
|
||||
|
||||
deploy_key_in_key_manager(k1_ecdsa256_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_256, key_recovery_info);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x_km, ecdsa256_pub_y_km, true, USE_ECDSA_KEY_FROM_KEY_MANAGER, (void *) key_recovery_info);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x_km, ecdsa256_pub_y_km, true, USE_ECDSA_KEY_FROM_KEY_MANAGER, (void *) key_recovery_info, NULL);
|
||||
free(key_recovery_info);
|
||||
}
|
||||
}
|
||||
@@ -641,7 +652,7 @@ TEST_CASE("mbedtls ECDSA deterministic signature generation on SECP384R1", "[mbe
|
||||
TEST_ASSERT_NOT_NULL(key_recovery_info);
|
||||
|
||||
deploy_key_in_key_manager(k1_ecdsa384_encrypt, ESP_KEY_MGR_ECDSA_KEY, ESP_KEY_MGR_ECDSA_LEN_384, key_recovery_info);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x_km, ecdsa384_pub_y_km, true, USE_ECDSA_KEY_FROM_KEY_MANAGER, (void *) key_recovery_info);
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x_km, ecdsa384_pub_y_km, true, USE_ECDSA_KEY_FROM_KEY_MANAGER, (void *) key_recovery_info, NULL);
|
||||
free(key_recovery_info);
|
||||
}
|
||||
}
|
||||
@@ -920,4 +931,99 @@ TEST_CASE("mbedtls ECDSA signature generation verification, import and export er
|
||||
}
|
||||
|
||||
#endif /* SOC_ECDSA_SUPPORT_EXPORT_PUBKEY */
|
||||
|
||||
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN */
|
||||
|
||||
#if CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_SOFTWARE_KEY && (CONFIG_MBEDTLS_HARDWARE_ECC || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY)
|
||||
|
||||
/*
|
||||
* Software-key tests: the private key is a plaintext (transparent) PSA key,
|
||||
* signed by the ECDSA peripheral through its software key source. These tests
|
||||
* do not need any key provisioned in eFuse or the Key Manager.
|
||||
*
|
||||
* The keys below match the ecdsa_key_p256.pem / ecdsa_key_p384.pem files in
|
||||
* the test app directory (and the ecdsa256/384_pub_x/y constants above).
|
||||
*/
|
||||
|
||||
/* Big endian */
|
||||
static const uint8_t ecdsa256_priv[] = {
|
||||
0x11, 0x25, 0x63, 0x32, 0x3e, 0x15, 0x36, 0x2e,
|
||||
0xd1, 0xac, 0x4b, 0x48, 0x3a, 0x00, 0x36, 0x3d,
|
||||
0x24, 0x7e, 0x6d, 0x7f, 0xa3, 0x10, 0x73, 0x30,
|
||||
0x20, 0xcb, 0xc7, 0xcf, 0x4c, 0x2b, 0x47, 0xf3,
|
||||
};
|
||||
|
||||
#if SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
/* Big endian */
|
||||
static const uint8_t ecdsa384_priv[] = {
|
||||
0x25, 0x24, 0xd3, 0x71, 0xb1, 0x87, 0xe4, 0xe4,
|
||||
0xb8, 0xec, 0xd5, 0x2f, 0xb4, 0x03, 0xe1, 0x74,
|
||||
0x6e, 0xc6, 0xc2, 0x04, 0xe6, 0x2f, 0x12, 0x41,
|
||||
0xa0, 0x1c, 0xb7, 0xb6, 0x19, 0x7f, 0x01, 0x65,
|
||||
0x6b, 0xc5, 0xfd, 0x47, 0x01, 0x43, 0xf3, 0x02,
|
||||
0xab, 0x0d, 0xa6, 0xfe, 0x51, 0x67, 0x0f, 0x1f,
|
||||
};
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
|
||||
TEST_CASE("mbedtls ECDSA signature generation with software key on SECP256R1", "[mbedtls][ecdsa_sw_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
if (!esp_efuse_is_ecdsa_software_key_allowed()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA software key is disabled by eFuse");
|
||||
}
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, false, 0, NULL, ecdsa256_priv);
|
||||
#if SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP256R1, sha, ecdsa256_pub_x, ecdsa256_pub_y, true, 0, NULL, ecdsa256_priv);
|
||||
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
|
||||
}
|
||||
|
||||
#ifdef SOC_ECDSA_SUPPORT_CURVE_P384
|
||||
TEST_CASE("mbedtls ECDSA signature generation with software key on SECP384R1", "[mbedtls][ecdsa_sw_key]")
|
||||
{
|
||||
if (!ecdsa_ll_is_supported()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA is not supported");
|
||||
}
|
||||
if (!esp_efuse_is_ecdsa_software_key_allowed()) {
|
||||
TEST_IGNORE_MESSAGE("ECDSA software key is disabled by eFuse");
|
||||
}
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, false, 0, NULL, ecdsa384_priv);
|
||||
#if SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE
|
||||
test_ecdsa_sign(ESP_ECDSA_CURVE_SECP384R1, sha, ecdsa384_pub_x, ecdsa384_pub_y, true, 0, NULL, ecdsa384_priv);
|
||||
#endif /* SOC_ECDSA_SUPPORT_DETERMINISTIC_MODE */
|
||||
}
|
||||
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
|
||||
|
||||
TEST_CASE("mbedtls ECDSA software fallback for combinations unsupported by the peripheral", "[mbedtls][ecdsa_sw_key]")
|
||||
{
|
||||
/* P-256 key with a SHA-384 sized hash is not supported by the transparent
|
||||
* sign driver, so this exercises the software fallback path end-to-end */
|
||||
uint8_t signature[2 * ECDSA_P256_HASH_COMPONENT_LEN];
|
||||
size_t signature_len = 0;
|
||||
psa_key_id_t priv_key_id = 0;
|
||||
psa_key_attributes_t priv_attr = PSA_KEY_ATTRIBUTES_INIT;
|
||||
|
||||
psa_algorithm_t alg = PSA_ALG_ECDSA(PSA_ALG_SHA_384);
|
||||
|
||||
psa_set_key_type(&priv_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
|
||||
psa_set_key_bits(&priv_attr, 256);
|
||||
psa_set_key_usage_flags(&priv_attr, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
|
||||
psa_set_key_algorithm(&priv_attr, alg);
|
||||
|
||||
psa_status_t status = psa_import_key(&priv_attr, ecdsa256_priv, sizeof(ecdsa256_priv), &priv_key_id);
|
||||
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||
|
||||
status = psa_sign_hash(priv_key_id, alg, sha, 48, signature, sizeof(signature), &signature_len);
|
||||
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||
TEST_ASSERT_TRUE(signature_len == sizeof(signature));
|
||||
|
||||
status = psa_verify_hash(priv_key_id, alg, sha, 48, signature, signature_len);
|
||||
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||
|
||||
psa_destroy_key(priv_key_id);
|
||||
psa_reset_key_attributes(&priv_attr);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_SOFTWARE_KEY && (CONFIG_MBEDTLS_HARDWARE_ECC || CONFIG_MBEDTLS_HARDWARE_ECDSA_VERIFY) */
|
||||
#endif /* CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN || CONFIG_MBEDTLS_HARDWARE_ECDSA_SIGN_SOFTWARE_KEY */
|
||||
|
||||
@@ -127,6 +127,20 @@ def test_mbedtls_ecdsa_sign(dut: Dut) -> None:
|
||||
dut.run_all_single_board_cases(group='efuse_key')
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
'default',
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', ['esp32s31'], indirect=['target'])
|
||||
def test_mbedtls_ecdsa_sw_key_sign(dut: Dut) -> None:
|
||||
# Software-key ECDSA tests need no eFuse provisioning and are enabled by default
|
||||
dut.run_all_single_board_cases(group='ecdsa_sw_key')
|
||||
|
||||
|
||||
@pytest.mark.nvs_encr_hmac
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
|
||||
@@ -1147,6 +1147,10 @@ config SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ECDSA_SUPPORT_SOFTWARE_KEY
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_DS_SIGNATURE_MAX_BIT_LEN
|
||||
int
|
||||
default 4096
|
||||
|
||||
@@ -423,6 +423,7 @@
|
||||
#define SOC_ECDSA_SUPPORT_HW_DETERMINISTIC_LOOP (1)
|
||||
#define SOC_ECDSA_SUPPORT_CURVE_P384 (1)
|
||||
#define SOC_ECDSA_SUPPORT_CURVE_SPECIFIC_KEY_PURPOSES (1) /*!< Support individual key purposes for different ECDSA curves (P192, P256, P384) */
|
||||
#define SOC_ECDSA_SUPPORT_SOFTWARE_KEY (1) /*!< Support software supplied private key written into the ECDSA key registers */
|
||||
|
||||
/*-------------------------- Digital Signature CAPS ----------------------------------------*/
|
||||
#define SOC_DS_SIGNATURE_MAX_BIT_LEN (4096)
|
||||
|
||||
Reference in New Issue
Block a user