Merge branch 'feat/support_ecdsa_p384_tee_sec_stg' into 'master'

feat(esp_tee): Support ECDSA `secp384r1` keys in TEE secure storage

See merge request espressif/esp-idf!41298
This commit is contained in:
Mahavir Jain
2025-12-08 13:33:29 +05:30
13 changed files with 332 additions and 125 deletions
+14 -5
View File
@@ -96,11 +96,20 @@ menu "ESP-TEE (Trusted Execution Environment)"
help
eFuse block key ID storing the HMAC key for deriving PBKDF2-based ECDSA keys
config SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
bool "Secure Storage: Support signing with the ECDSA SECP192R1 curve"
default n
help
Enable ECDSA signing with the SECP192R1 curve using the TEE secure storage.
menu "Secure Storage: Additional supported curves for ECDSA signing"
config SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
bool "SECP192R1"
help
Enable ECDSA signing with the SECP192R1 curve using TEE secure storage
config SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
bool "SECP384R1"
depends on SOC_ECDSA_SUPPORT_CURVE_P384
help
Enable ECDSA signing with the SECP384R1 curve using TEE secure storage
endmenu
config SECURE_TEE_ATTESTATION
bool "Enable Attestation"
@@ -7,13 +7,13 @@
```
$ python esp_tee_sec_stg_keygen.py --help
usage: esp_tee_sec_stg_keygen.py [-h] -k {aes256,ecdsa_p256,ecdsa_p192} -o OUTPUT [-i INPUT] [--write-once]
usage: esp_tee_sec_stg_keygen.py [-h] -k {aes256,ecdsa_p256,ecdsa_p192,ecdsa_p384} -o OUTPUT [-i INPUT] [--write-once]
Generate or import a cryptographic key structure for secure storage
options:
-h, --help show this help message and exit
-k, --key-type {aes256,ecdsa_p256,ecdsa_p192}
-k, --key-type {aes256,ecdsa_p256,ecdsa_p192,ecdsa_p384}
key type to be processed
-o, --output OUTPUT output binary file name
-i, --input INPUT input key file (.pem for ecdsa, .bin for aes)
@@ -25,6 +25,7 @@ options:
```bash
python esp_tee_sec_stg_keygen.py -k ecdsa_p256 -o ecdsa_p256_k0.bin
python esp_tee_sec_stg_keygen.py -k ecdsa_p192 -o ecdsa_p192_k0.bin
python esp_tee_sec_stg_keygen.py -k ecdsa_p384 -o ecdsa_p384_k0.bin
```
#### With custom PEM:
@@ -65,6 +66,7 @@ tee_sec_stg_ns,namespace,,
aes256_key0,file,binary,aes256_gcm_k0.bin
p256_key0,file,binary,ecdsa_p256_k0.bin
p192_key0,file,binary,ecdsa_p192_k0.bin
p384_key0,file,binary,ecdsa_p384_k0.bin
attest_key0,file,binary,ecdsa_p256_k1.bin
```
> [!IMPORTANT]
@@ -8,7 +8,6 @@ import struct
from enum import Enum
from enum import IntFlag
from typing import Any
from typing import Optional
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
@@ -21,6 +20,7 @@ AES_DEFAULT_IV_LEN = 16
AES_GCM_IV_LEN = 12
ECDSA_P256_LEN = 32
ECDSA_P192_LEN = 24
ECDSA_P384_LEN = 48
# === Key Type Enum ===
@@ -28,6 +28,7 @@ class KeyType(Enum):
AES256 = 0
ECDSA_P256 = 1
ECDSA_P192 = 2
ECDSA_P384 = 3
# === Bitwise Flags Enum ===
@@ -39,7 +40,7 @@ class Flags(IntFlag):
# === Key Generators ===
def generate_aes256_key(flags: Flags, key_file: Optional[str] = None) -> bytes:
def generate_aes256_key(flags: Flags, key_file: str | None = None) -> bytes:
if key_file:
with open(key_file, 'rb') as f:
key_data = f.read()
@@ -68,7 +69,7 @@ def generate_aes256_key(flags: Flags, key_file: Optional[str] = None) -> bytes:
def generate_ecdsa_key(
curve: ec.EllipticCurve, key_type_enum: KeyType, key_len: int, flags: Flags, pem_file: Optional[str] = None
curve: ec.EllipticCurve, key_type_enum: KeyType, key_len: int, flags: Flags, pem_file: str | None = None
) -> bytes:
if pem_file:
with open(pem_file, 'rb') as f:
@@ -87,13 +88,15 @@ def generate_ecdsa_key(
return packed + b'\x00' * (SEC_STG_KEY_DATA_SZ - len(packed))
def generate_key_data(key_type: KeyType, flags: Flags, input_file: Optional[str]) -> bytes:
def generate_key_data(key_type: KeyType, flags: Flags, input_file: str | None) -> bytes:
if key_type == KeyType.AES256:
return generate_aes256_key(flags, input_file)
elif key_type == KeyType.ECDSA_P256:
return generate_ecdsa_key(ec.SECP256R1(), key_type, ECDSA_P256_LEN, flags, input_file)
elif key_type == KeyType.ECDSA_P192:
return generate_ecdsa_key(ec.SECP192R1(), key_type, ECDSA_P192_LEN, flags, input_file)
elif key_type == KeyType.ECDSA_P384:
return generate_ecdsa_key(ec.SECP384R1(), key_type, ECDSA_P384_LEN, flags, input_file)
else:
raise ValueError(f'Unsupported key type: {key_type}')
@@ -16,7 +16,11 @@ extern "C" {
#include "esp_err.h"
#include "esp_bit_defs.h"
#define MAX_ECDSA_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the ECDSA key */
#if SOC_ECDSA_SUPPORT_CURVE_P384
#define MAX_ECDSA_SUPPORTED_KEY_LEN 48 /*!< Maximum supported size for the ECDSA key (SECP384R1) */
#else
#define MAX_ECDSA_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the ECDSA key (SECP256R1) */
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
#define MAX_AES_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the AES key */
#define SEC_STORAGE_FLAG_NONE 0 /*!< No flags */
@@ -30,6 +34,9 @@ typedef enum {
ESP_SEC_STG_KEY_AES256 = 0,
ESP_SEC_STG_KEY_ECDSA_SECP256R1 = 1,
ESP_SEC_STG_KEY_ECDSA_SECP192R1 = 2,
#if SOC_ECDSA_SUPPORT_CURVE_P384
ESP_SEC_STG_KEY_ECDSA_SECP384R1 = 3,
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
ESP_SEC_STG_TYPE_MAX,
} esp_tee_sec_storage_type_t;
@@ -38,6 +38,7 @@
#define AES256_KEY_BITS (AES256_KEY_LEN * 8)
#define AES256_DEFAULT_IV_LEN 16
#define AES256_GCM_IV_LEN 12
#define ECDSA_SECP384R1_KEY_LEN 48
#define ECDSA_SECP256R1_KEY_LEN 32
#define ECDSA_SECP192R1_KEY_LEN 24
@@ -48,6 +49,12 @@
#define PBKDF2_HMAC_ITER 2048
/* Structure to hold ECDSA SECP384R1 key pair */
typedef struct {
uint8_t priv_key[ECDSA_SECP384R1_KEY_LEN]; /* Private key for ECDSA SECP384R1 */
uint8_t pub_key[2 * ECDSA_SECP384R1_KEY_LEN]; /* Public key for ECDSA SECP384R1 (X and Y coordinates) */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_ecdsa_secp384r1_t;
/* Structure to hold ECDSA SECP256R1 key pair */
typedef struct {
uint8_t priv_key[ECDSA_SECP256R1_KEY_LEN]; /* Private key for ECDSA SECP256R1 */
@@ -71,11 +78,12 @@ typedef struct {
const esp_tee_sec_storage_type_t type; /* Type of the key */
uint32_t flags; /* Flags associated with the key */
union {
sec_stg_ecdsa_secp384r1_t ecdsa_secp384r1; /* ECDSA SECP384R1 key pair */
sec_stg_ecdsa_secp256r1_t ecdsa_secp256r1; /* ECDSA SECP256R1 key pair */
sec_stg_ecdsa_secp192r1_t ecdsa_secp192r1; /* ECDSA SECP192R1 key pair */
sec_stg_aes256_t aes256; /* AES-256 key and IV */
};
uint32_t reserved[38]; /* Reserved space for future use */
uint32_t reserved[26]; /* Reserved space for future use */
} __attribute__((aligned(4))) __attribute__((__packed__)) sec_stg_key_t;
_Static_assert(sizeof(sec_stg_key_t) == 256, "Incorrect sec_stg_key_t size");
@@ -306,23 +314,63 @@ esp_err_t esp_tee_sec_storage_clear_key(const char *key_id)
return err;
}
static esp_err_t get_ecdsa_curve_info(esp_tee_sec_storage_type_t type, sec_stg_key_t *ctx, mbedtls_ecp_group_id *curve,
size_t *key_len, uint8_t **priv_key, uint8_t **pub_key)
{
if (!ctx || !curve || !key_len || !priv_key || !pub_key) {
return ESP_ERR_INVALID_ARG;
}
esp_err_t err = ESP_FAIL;
switch (type) {
case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
*curve = MBEDTLS_ECP_DP_SECP256R1;
*key_len = ECDSA_SECP256R1_KEY_LEN;
*priv_key = ctx->ecdsa_secp256r1.priv_key;
*pub_key = ctx->ecdsa_secp256r1.pub_key;
err = ESP_OK;
break;
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP192R1:
*curve = MBEDTLS_ECP_DP_SECP192R1;
*key_len = ECDSA_SECP192R1_KEY_LEN;
*priv_key = ctx->ecdsa_secp192r1.priv_key;
*pub_key = ctx->ecdsa_secp192r1.pub_key;
err = ESP_OK;
break;
#endif
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP384R1:
*curve = MBEDTLS_ECP_DP_SECP384R1;
*key_len = ECDSA_SECP384R1_KEY_LEN;
*priv_key = ctx->ecdsa_secp384r1.priv_key;
*pub_key = ctx->ecdsa_secp384r1.pub_key;
err = ESP_OK;
break;
#endif
default:
ESP_LOGE(TAG, "Unsupported ECDSA curve type");
err = ESP_ERR_INVALID_ARG;
break;
}
return err;
}
static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t key_type)
{
if (keyctx == NULL) {
return -1;
}
mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_SECP256R1;
size_t key_len = ECDSA_SECP256R1_KEY_LEN;
mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_NONE;
size_t key_len = 0;
uint8_t *priv_key = NULL;
uint8_t *pub_key = NULL;
if (key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
curve_id = MBEDTLS_ECP_DP_SECP192R1;
key_len = ECDSA_SECP192R1_KEY_LEN;
#else
ESP_LOGE(TAG, "Unsupported key-type!");
if (get_ecdsa_curve_info(key_type, keyctx, &curve_id, &key_len, &priv_key, &pub_key) != ESP_OK) {
return -1;
#endif
}
ESP_LOGD(TAG, "Generating ECDSA key for curve %d...", curve_id);
@@ -335,22 +383,6 @@ static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t
goto exit;
}
uint8_t *priv_key = (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) ?
keyctx->ecdsa_secp256r1.priv_key :
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
keyctx->ecdsa_secp192r1.priv_key;
#else
NULL;
#endif
uint8_t *pub_key = (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) ?
keyctx->ecdsa_secp256r1.pub_key :
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
keyctx->ecdsa_secp192r1.pub_key;
#else
NULL;
#endif
ret = mbedtls_mpi_write_binary(&(ctxECDSA.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), pub_key, key_len);
if (ret != 0) {
goto exit;
@@ -408,6 +440,9 @@ esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP192R1:
#endif
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP384R1:
#endif
if (generate_ecdsa_key(&keyctx, cfg->type) != 0) {
ESP_LOGE(TAG, "Failed to generate ECDSA keypair");
@@ -436,7 +471,12 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
#if !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
if (cfg->type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
ESP_LOGE(TAG, "Unsupported key-type!");
return ESP_ERR_NOT_SUPPORTED;
}
#endif
#if SOC_ECC_SUPPORT_CURVE_P384 && !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
if (cfg->type == ESP_SEC_STG_KEY_ECDSA_SECP384R1) {
return ESP_ERR_NOT_SUPPORTED;
}
#endif
@@ -461,33 +501,31 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
}
mbedtls_mpi r, s;
mbedtls_ecp_keypair priv_key;
mbedtls_ecp_keypair keypair_ctx;
mbedtls_ecdsa_context sign_ctx;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
mbedtls_ecp_keypair_init(&priv_key);
mbedtls_ecp_keypair_init(&keypair_ctx);
mbedtls_ecdsa_init(&sign_ctx);
mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_NONE;
size_t key_len = 0;
int ret = -1;
uint8_t *priv_key = NULL;
uint8_t *pub_key = NULL;
if (cfg->type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) {
ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256R1, &priv_key, keyctx.ecdsa_secp256r1.priv_key, sizeof(keyctx.ecdsa_secp256r1.priv_key));
key_len = ECDSA_SECP256R1_KEY_LEN;
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
} else if (cfg->type == ESP_SEC_STG_KEY_ECDSA_SECP192R1) {
ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP192R1, &priv_key, keyctx.ecdsa_secp192r1.priv_key, sizeof(keyctx.ecdsa_secp192r1.priv_key));
key_len = ECDSA_SECP192R1_KEY_LEN;
#endif
err = get_ecdsa_curve_info(keyctx.type, &keyctx, &curve_id, &key_len, &priv_key, &pub_key);
if (err != ESP_OK) {
return ESP_ERR_INVALID_ARG;
}
int ret = mbedtls_ecp_read_key(curve_id, &keypair_ctx, priv_key, key_len);
if (ret != 0) {
err = ESP_FAIL;
goto exit;
}
ret = mbedtls_ecdsa_from_keypair(&sign_ctx, &priv_key);
ret = mbedtls_ecdsa_from_keypair(&sign_ctx, &keypair_ctx);
if (ret != 0) {
err = ESP_FAIL;
goto exit;
@@ -519,7 +557,7 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
exit:
mbedtls_ecdsa_free(&sign_ctx);
mbedtls_ecp_keypair_free(&priv_key);
mbedtls_ecp_keypair_free(&keypair_ctx);
mbedtls_mpi_free(&s);
mbedtls_mpi_free(&r);
@@ -540,24 +578,6 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg
sec_stg_key_t keyctx;
size_t keyctx_len = sizeof(keyctx);
uint8_t *pub_key_src = NULL;
size_t pub_key_len = 0;
switch (cfg->type) {
case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
pub_key_src = keyctx.ecdsa_secp256r1.pub_key;
pub_key_len = ECDSA_SECP256R1_KEY_LEN;
break;
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP192R1:
pub_key_src = keyctx.ecdsa_secp192r1.pub_key;
pub_key_len = ECDSA_SECP192R1_KEY_LEN;
break;
#endif
default:
ESP_LOGE(TAG, "Unsupported key-type");
return ESP_ERR_INVALID_ARG;
}
err = secure_storage_read(cfg->id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
@@ -570,8 +590,18 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg
return ESP_ERR_INVALID_STATE;
}
memcpy(out_pubkey->pub_x, pub_key_src, pub_key_len);
memcpy(out_pubkey->pub_y, pub_key_src + pub_key_len, pub_key_len);
mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_NONE;
size_t key_len = 0;
uint8_t *priv_key = NULL;
uint8_t *pub_key = NULL;
err = get_ecdsa_curve_info(keyctx.type, &keyctx, &curve_id, &key_len, &priv_key, &pub_key);
if (err != ESP_OK) {
return err;
}
memcpy(out_pubkey->pub_x, pub_key, key_len);
memcpy(out_pubkey->pub_y, pub_key + key_len, key_len);
return ESP_OK;
}
@@ -5,6 +5,7 @@
*/
#include <string.h>
#include "soc/soc_caps.h"
#include "esp_event.h"
#include "esp_log.h"
@@ -22,7 +23,11 @@
#include "example_tee_srv.h"
#define SHA256_DIGEST_SZ (32)
#define ECDSA_SECP256R1_KEY_LEN (32)
#if SOC_ECDSA_SUPPORT_CURVE_P384
#define MAX_ECDSA_KEY_LEN (48)
#else
#define MAX_ECDSA_KEY_LEN (32)
#endif
#define AES256_GCM_TAG_LEN (16)
#define MAX_AES_PLAINTEXT_LEN (256)
@@ -290,7 +295,7 @@ static int tee_sec_stg_sign(int argc, char **argv)
goto exit;
}
size_t sign_hexstr_len = (ECDSA_SECP256R1_KEY_LEN * 2) * 2 + 1;
size_t sign_hexstr_len = (MAX_ECDSA_KEY_LEN * 2) * 2 + 1;
char *sign_hexstr = calloc(sign_hexstr_len, sizeof(char));
if (sign_hexstr == NULL) {
err = ESP_ERR_NO_MEM;
@@ -308,7 +313,7 @@ static int tee_sec_stg_sign(int argc, char **argv)
goto exit;
}
size_t pubkey_hexstr_len = (ECDSA_SECP256R1_KEY_LEN * 2) * 2 + 1;
size_t pubkey_hexstr_len = (MAX_ECDSA_KEY_LEN * 2) * 2 + 1;
char *pubkey_hexstr = calloc(pubkey_hexstr_len, sizeof(char));
if (pubkey_hexstr == NULL) {
err = ESP_ERR_NO_MEM;
@@ -339,6 +339,20 @@ class TEESerial(IdfSerial):
'LS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo='
),
},
{'key': 'p192_key0', 'type': 'ecdsa_p192', 'input': None, 'write_once': False},
{
'key': 'p384_key0',
'type': 'ecdsa_p384',
'input': 'ecdsa_p384_key.pem',
'write_once': True,
'b64': (
'LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1JR2tBZ0VCQkRDQUIreENyckkrOWJObWlzVlVsSG1R'
'T3dZMHIyNWVIL09DalVMUVY4NHZtZU0wWDVLMnYrRE4KZkdSUkRZd0NheGlnQndZRks0RUVBQ0toWkFOaUFB'
'UVFWcHFObVY0Qm1aemw5VWZBcm0veVpiak9QZTJoUEtDRQp0RERZLy9FS0lOZExvY1dvMUgwWWhzYTBuU2xj'
'cGk2SDM3eXlSVHNxUnFueFBOeXFYZDdqbXo1WkIySWZHWHhBCmptZnZLVmJIcVNJV0JDRUx0WUxwS2t3UHNCO'
'XV4WW89Ci0tLS0tRU5EIEVDIFBSSVZBVEUgS0VZLS0tLS0='
),
},
]
NVS_KEYS_B64 = 'MzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzPMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzA=='
@@ -36,7 +36,7 @@
static const char *TAG = "test_esp_tee_att";
extern int verify_ecdsa_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, bool is_crv_p192);
extern int verify_ecdsa_sign(const esp_tee_sec_storage_type_t key_type, 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 uint8_t hexchar_to_byte(char hex)
{
@@ -275,7 +275,7 @@ TEST_CASE("Test TEE Attestation - Generate and verify the EAT", "[attestation]")
fetch_signature((const char *)token_buf, &sign_ctx);
// Verifying the generated token
TEST_ASSERT_EQUAL(0, verify_ecdsa_sign(digest, sizeof(digest), &pubkey_ctx, &sign_ctx, false));
TEST_ASSERT_EQUAL(0, verify_ecdsa_sign(ESP_SEC_STG_KEY_ECDSA_SECP256R1, digest, sizeof(digest), &pubkey_ctx, &sign_ctx));
free(token_buf);
}
@@ -12,6 +12,7 @@
#include "mbedtls/ecp.h"
#include "mbedtls/ecdsa.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#include "ecdsa/ecdsa_alt.h"
#include "esp_tee.h"
@@ -30,7 +31,9 @@
error hex value (mbedTLS uses -N for error codes) */
#define TEST_ASSERT_MBEDTLS_OK(X) TEST_ASSERT_EQUAL_HEX32(0, -(X))
#define SHA384_DIGEST_SZ (48)
#define SHA256_DIGEST_SZ (32)
#define ECDSA_SECP384R1_KEY_LEN (48)
#define ECDSA_SECP256R1_KEY_LEN (32)
#define ECDSA_SECP192R1_KEY_LEN (24)
@@ -41,10 +44,13 @@
static const char *TAG = "test_esp_tee_sec_storage";
int verify_ecdsa_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, bool is_crv_p192)
int verify_ecdsa_sign(const esp_tee_sec_storage_type_t key_type, 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)
{
#if !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
TEST_ASSERT_FALSE(is_crv_p192);
TEST_ASSERT_FALSE(key_type == ESP_SEC_STG_KEY_ECDSA_SECP192R1);
#endif
#if SOC_ECDSA_SUPPORT_CURVE_P384 && !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
TEST_ASSERT_FALSE(key_type == ESP_SEC_STG_KEY_ECDSA_SECP384R1);
#endif
TEST_ASSERT_NOT_NULL(pubkey);
@@ -59,9 +65,25 @@ int verify_ecdsa_sign(const uint8_t *digest, size_t len, const esp_tee_sec_stora
mbedtls_ecdsa_context ecdsa_context;
mbedtls_ecdsa_init(&ecdsa_context);
mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_SECP256R1;
if (is_crv_p192) {
mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_NONE;
switch (key_type) {
case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
curve_id = MBEDTLS_ECP_DP_SECP256R1;
break;
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP192R1:
curve_id = MBEDTLS_ECP_DP_SECP192R1;
break;
#endif
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
case ESP_SEC_STG_KEY_ECDSA_SECP384R1:
curve_id = MBEDTLS_ECP_DP_SECP384R1;
break;
#endif
default:
ESP_LOGE(TAG, "Unsupported key type: %d", key_type);
return -1;
}
TEST_ASSERT_MBEDTLS_OK(mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), curve_id));
@@ -113,7 +135,7 @@ TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp256r1)", "[sec_stora
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {};
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey));
TEST_ESP_OK(verify_ecdsa_sign(msg_digest, sizeof(msg_digest), &pubkey, &sign, false));
TEST_ESP_OK(verify_ecdsa_sign(key_cfg.type, msg_digest, sizeof(msg_digest), &pubkey, &sign));
TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id));
}
@@ -152,7 +174,47 @@ TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp192r1)", "[sec_stora
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {};
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey));
TEST_ESP_OK(verify_ecdsa_sign(msg_digest, sizeof(msg_digest), &pubkey, &sign, true));
TEST_ESP_OK(verify_ecdsa_sign(key_cfg.type, msg_digest, sizeof(msg_digest), &pubkey, &sign));
TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id));
}
}
#endif
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp384r1)", "[sec_storage]")
{
const size_t buf_sz = 16 * 1024 + 6; // NOTE: Not an exact multiple of SHA block size
unsigned char *message = heap_caps_malloc(buf_sz, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(message);
esp_fill_random(message, buf_sz);
uint8_t msg_digest[SHA384_DIGEST_SZ];
TEST_ASSERT_MBEDTLS_OK(mbedtls_sha512(message, buf_sz, msg_digest, false));
free(message);
esp_tee_sec_storage_key_cfg_t key_cfg = {
.type = ESP_SEC_STG_KEY_ECDSA_SECP384R1
};
for (unsigned int i = 0; i < MAX_SEC_STG_ITER; i++) {
char key_id[32];
int ret = snprintf(key_id, sizeof(key_id), "ecdsa_key_%u", i);
TEST_ASSERT_TRUE(ret > 0 && ret < sizeof(key_id));
key_cfg.id = key_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_ESP_OK(esp_tee_sec_storage_gen_key(&key_cfg));
esp_tee_sec_storage_ecdsa_sign_t sign = {};
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_sign(&key_cfg, msg_digest, sizeof(msg_digest), &sign));
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {};
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey));
TEST_ESP_OK(verify_ecdsa_sign(key_cfg.type, msg_digest, sizeof(msg_digest), &pubkey, &sign));
TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id));
}
@@ -265,7 +327,7 @@ TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys",
TEST_ESP_OK(esp_tee_sec_storage_gen_key(&key_cfg));
esp_tee_sec_storage_ecdsa_sign_t sign = {};
TEST_ESP_ERR(ESP_FAIL, esp_tee_sec_storage_ecdsa_sign(&key_cfg, msg_digest, sizeof(msg_digest), &sign));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_ecdsa_sign(&key_cfg, msg_digest, sizeof(msg_digest), &sign));
TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id));
// Test with non-existent data
@@ -377,46 +439,64 @@ static void test_aead_encrypt_decrypt(const char *key_id, const uint8_t *input,
free(decrypted);
}
static void do_ecdsa_sign_and_verify(const esp_tee_sec_storage_key_cfg_t *cfg, const uint8_t *digest, size_t digest_len)
{
esp_tee_sec_storage_ecdsa_sign_t sign = {0};
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {0};
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_sign(cfg, digest, digest_len, &sign));
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(cfg, &pubkey));
TEST_ESP_OK(verify_ecdsa_sign(cfg->type, digest, digest_len, &pubkey, &sign));
}
TEST_CASE("Test TEE Secure Storage - Host-generated keys", "[sec_storage_host_keygen]")
{
const char *aes_key_id0 = "aes256_key0";
const char *aes_key_id1 = "aes256_key1";
const char *aes_key_ids[] = { "aes256_key0", "aes256_key1" };
const char *ecdsa_key_id0 = "p256_key0";
const char *attest_key_id = "attest_key";
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(aes_key_id0));
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(aes_key_ids[0]));
const size_t SZ = 100;
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(plaintext);
esp_fill_random(plaintext, SZ);
test_aead_encrypt_decrypt(aes_key_id0, plaintext, SZ);
test_aead_encrypt_decrypt(aes_key_id1, plaintext, SZ);
for (size_t i = 0; i < sizeof(aes_key_ids) / sizeof(aes_key_ids[0]); ++i) {
test_aead_encrypt_decrypt(aes_key_ids[i], plaintext, SZ);
}
free(plaintext);
heap_caps_free(plaintext);
TEST_ESP_OK(esp_tee_sec_storage_clear_key(aes_key_id1));
TEST_ESP_OK(esp_tee_sec_storage_clear_key(aes_key_ids[1]));
uint8_t msg_digest[SHA256_DIGEST_SZ];
esp_fill_random(msg_digest, sizeof(msg_digest));
uint8_t digest_buf[SHA384_DIGEST_SZ];
esp_fill_random(digest_buf, sizeof(digest_buf));
esp_tee_sec_storage_key_cfg_t key_cfg = {
.id = ecdsa_key_id0,
.id = ecdsa_key_id0,
.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1,
};
esp_tee_sec_storage_ecdsa_sign_t sign = {};
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_sign(&key_cfg, msg_digest, sizeof(msg_digest), &sign));
esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {};
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey));
TEST_ESP_OK(verify_ecdsa_sign(msg_digest, sizeof(msg_digest), &pubkey, &sign, false));
do_ecdsa_sign_and_verify(&key_cfg, digest_buf, SHA256_DIGEST_SZ);
TEST_ESP_OK(esp_tee_sec_storage_clear_key(ecdsa_key_id0));
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(attest_key_id));
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
const char *ecdsa_key_id1 = "p192_key0";
key_cfg.id = ecdsa_key_id1;
key_cfg.type = ESP_SEC_STG_KEY_ECDSA_SECP192R1;
do_ecdsa_sign_and_verify(&key_cfg, digest_buf, SHA256_DIGEST_SZ);
TEST_ESP_OK(esp_tee_sec_storage_clear_key(ecdsa_key_id1));
#endif /* CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN */
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
const char *ecdsa_key_id2 = "p384_key0";
key_cfg.id = ecdsa_key_id2;
key_cfg.type = ESP_SEC_STG_KEY_ECDSA_SECP384R1;
do_ecdsa_sign_and_verify(&key_cfg, digest_buf, SHA384_DIGEST_SZ);
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(ecdsa_key_id2));
#endif /* CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN */
#if CONFIG_SECURE_TEE_ATTESTATION
uint8_t *token_buf = heap_caps_calloc(ESP_ATT_TK_BUF_SIZE, sizeof(uint8_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
@@ -427,29 +507,52 @@ TEST_CASE("Test TEE Secure Storage - Host-generated keys", "[sec_storage_host_ke
token_buf, ESP_ATT_TK_BUF_SIZE, &token_len));
free(token_buf);
#endif
const char *attest_key_id = "attest_key";
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(attest_key_id));
#endif /* CONFIG_SECURE_TEE_ATTESTATION */
}
#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
static const uint8_t sha[] = {
0x0c, 0xaa, 0x08, 0xb4, 0xf0, 0x89, 0xd3, 0x45,
0xbb, 0x55, 0x98, 0xd9, 0xc2, 0xe9, 0x65, 0x5d,
0x7e, 0xa3, 0xa9, 0xc3, 0xcd, 0x69, 0xb1, 0xcf,
0x91, 0xbe, 0x58, 0x10, 0xfe, 0x80, 0x65, 0x6e
0xda, 0x99, 0x5d, 0x66, 0xcb, 0xa5, 0xcb, 0xc7,
0xc5, 0x3d, 0x8d, 0x08, 0x4d, 0x6a, 0x5e, 0x8e,
0xf0, 0x84, 0x4b, 0x7b, 0xdd, 0xd0, 0x20, 0x47,
0xa3, 0x6c, 0x61, 0xf3, 0xbc, 0xcf, 0xf4, 0xe2,
0xf7, 0x70, 0xcd, 0x19, 0xf7, 0x31, 0x52, 0x48,
0x1f, 0x29, 0x0e, 0x13, 0x24, 0x55, 0x9d, 0xb9,
0x1a, 0x48, 0xa4, 0x0e, 0x75, 0xc2, 0xa8, 0x35,
0xa9, 0x53, 0x97, 0xec, 0xcc, 0x66, 0x5b, 0xa6
};
static void test_ecdsa_sign(mbedtls_ecp_group_id gid)
{
bool is_crv_p192 = false;
esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1;
size_t key_len = ECDSA_SECP256R1_KEY_LEN;
esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_TYPE_MAX;
size_t key_len = 0;
size_t sha_len = SHA256_DIGEST_SZ;
if (gid == MBEDTLS_ECP_DP_SECP192R1) {
is_crv_p192 = true;
switch (gid) {
case MBEDTLS_ECP_DP_SECP256R1:
key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1;
key_len = ECDSA_SECP256R1_KEY_LEN;
break;
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
case MBEDTLS_ECP_DP_SECP192R1:
key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1;
key_len = ECDSA_SECP192R1_KEY_LEN;
key_len = ECDSA_SECP192R1_KEY_LEN;
break;
#endif
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
case MBEDTLS_ECP_DP_SECP384R1:
key_type = ESP_SEC_STG_KEY_ECDSA_SECP384R1;
key_len = ECDSA_SECP384R1_KEY_LEN;
sha_len = SHA384_DIGEST_SZ;
break;
#endif
default:
ESP_LOGE(TAG, "Unsupported curve ID: %d", gid);
return;
}
const char *key_id = "ecdsa_k0";
esp_tee_sec_storage_key_cfg_t key_cfg = {
@@ -486,13 +589,13 @@ static void test_ecdsa_sign(mbedtls_ecp_group_id gid)
mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(key_ctx);
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, SHA256_DIGEST_SZ, NULL, NULL));
TEST_ASSERT_MBEDTLS_OK(mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, sha_len, NULL, NULL));
esp_tee_sec_storage_ecdsa_sign_t sign = {};
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&r, sign.sign_r, key_len));
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&s, sign.sign_s, key_len));
TEST_ESP_OK(verify_ecdsa_sign(sha, sizeof(sha), &pubkey, &sign, is_crv_p192));
TEST_ESP_OK(verify_ecdsa_sign(key_type, sha, sha_len, &pubkey, &sign));
mbedtls_pk_free(&key_ctx);
mbedtls_ecdsa_free(&ecdsa_context);
@@ -508,5 +611,8 @@ TEST_CASE("Test TEE Secure Storage - mbedtls ECDSA signing", "[mbedtls]")
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN && !TEMPORARY_DISABLED_FOR_TARGETS(ESP32H2)
test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1);
#endif
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
test_ecdsa_sign(MBEDTLS_ECP_DP_SECP384R1);
#endif
}
#endif
@@ -9,6 +9,8 @@ CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG=y
CONFIG_SECURE_TEE_LOG_LEVEL_DEBUG=y
CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN=y
# Takes effect only for supported targets
CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN=y
# secure storage key slot for attestation
CONFIG_SECURE_TEE_ATT_KEY_STR_ID="tee_att_keyN"
@@ -48,6 +48,9 @@
#define MBEDTLS_ASN1_WRITE_C
#define MBEDTLS_ASN1_PARSE_C
#define MBEDTLS_BIGNUM_C
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
#endif
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
+17 -3
View File
@@ -560,7 +560,14 @@ int esp_ecdsa_tee_load_pubkey(mbedtls_ecp_keypair *keypair, const char *tee_key_
} else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP192R1) {
len = ECDSA_KEY_LEN_P192;
key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1;
} else {
}
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (keypair->MBEDTLS_PRIVATE(grp).id == MBEDTLS_ECP_DP_SECP384R1) {
len = ECDSA_KEY_LEN_P384;
key_type = ESP_SEC_STG_KEY_ECDSA_SECP384R1;
}
#endif
else {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
@@ -670,7 +677,14 @@ static int esp_ecdsa_tee_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mp
} else if (grp->id == MBEDTLS_ECP_DP_SECP192R1) {
len = ECDSA_KEY_LEN_P192;
key_type = ESP_SEC_STG_KEY_ECDSA_SECP192R1;
} else {
}
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (grp->id == MBEDTLS_ECP_DP_SECP384R1) {
len = ECDSA_KEY_LEN_P384;
key_type = ESP_SEC_STG_KEY_ECDSA_SECP384R1;
}
#endif
else {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
@@ -689,7 +703,7 @@ static int esp_ecdsa_tee_sign(mbedtls_ecp_group *grp, mbedtls_mpi* r, mbedtls_mp
esp_tee_sec_storage_ecdsa_sign_t sign = {};
esp_err_t err = esp_tee_sec_storage_ecdsa_sign(&cfg, (uint8_t *)msg, msg_len, &sign);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to get signature");
ESP_LOGE(TAG, "Failed to get signature: 0x%08lx", err);
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
+16 -4
View File
@@ -20,8 +20,14 @@ The TEE Secure Storage service provides persistent storage for securely storing
Additionally, the secure storage provides interfaces for performing the following cryptographic services from the TEE using securely stored key material:
#. Message signing and public key retrieval using the ``ecdsa_secp256r1`` and ``ecdsa_secp192r1`` algorithms
#. Authenticated encryption and decryption using the ``aes256_gcm`` algorithm
#. Authenticated encryption and decryption using the ``aes256_gcm`` algorithm
#. Message signing and public key retrieval using ECDSA with the following curves
.. list::
- ``ecdsa_secp256r1``
- ``ecdsa_secp192r1``
:SOC_ECDSA_SUPPORT_CURVE_P384: - ``ecdsa_secp384r1``
.. note::
@@ -47,8 +53,14 @@ Each data object consisting of the type, associated metadata flags (e.g., ``WRIT
Currently, TEE secure storage supports storing the following cryptographic keys:
#. ``ecdsa_secp256r1`` and ``ecdsa_secp192r1`` curve key-pairs, including private and public key components
#. ``aes256`` keys, including the key and initialization vector (IV)
#. ``aes256`` keys, including the key and initialization vector (IV)
#. ECDSA key-pairs for the following curves, including both public and private components
.. list::
- ``ecdsa_secp256r1``
- ``ecdsa_secp192r1``
:SOC_ECDSA_SUPPORT_CURVE_P384: - ``ecdsa_secp384r1``
All assets related to TEE secure storage are protected by the APM peripheral and are inaccessible to the REE application. Any direct access attempts will result in a system fault. Future updates are planned to add support for additional key types and general-purpose data storage.