Skip to content

Commit 78737a7

Browse files
committed
feat(esp_tee): Added support for PBKDF2-based (HMAC) ECDSA signing
1 parent d49055e commit 78737a7

File tree

18 files changed

+372
-30
lines changed

18 files changed

+372
-30
lines changed

components/esp_tee/Kconfig.projbuild

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,20 @@ menu "ESP-TEE (Trusted Execution Environment)"
8282
endchoice
8383

8484
config SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID
85-
int "Secure Storage: eFuse HMAC key ID"
85+
int "Secure Storage: eFuse HMAC key ID for storage encryption keys"
8686
depends on SECURE_TEE_SEC_STG_MODE_RELEASE
8787
range -1 5
8888
default -1
8989
help
9090
eFuse block key ID storing the HMAC key for deriving the TEE secure storage encryption keys
9191

92+
config SECURE_TEE_PBKDF2_EFUSE_HMAC_KEY_ID
93+
int "Secure Storage: eFuse HMAC key ID for PBKDF2 key derivation"
94+
range -1 5
95+
default -1
96+
help
97+
eFuse block key ID storing the HMAC key for deriving PBKDF2-based ECDSA keys
98+
9299
config SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
93100
bool "Secure Storage: Support signing with the ECDSA SECP192R1 curve"
94101
default n

components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ secure_services:
314314
type: custom
315315
function: esp_tee_sec_storage_aead_decrypt
316316
args: 4
317+
- id: 181
318+
type: custom
319+
function: esp_tee_sec_storage_ecdsa_sign_pbkdf2
320+
args: 5
317321
# ID: 195-199 (5) - OTA
318322
- family: ota
319323
entries:

components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,10 @@ secure_services:
278278
type: custom
279279
function: esp_tee_sec_storage_aead_decrypt
280280
args: 4
281+
- id: 181
282+
type: custom
283+
function: esp_tee_sec_storage_ecdsa_sign_pbkdf2
284+
args: 5
281285
# ID: 195-199 (5) - OTA
282286
- family: ota
283287
entries:

components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,10 @@ secure_services:
282282
type: custom
283283
function: esp_tee_sec_storage_aead_decrypt
284284
args: 4
285+
- id: 181
286+
type: custom
287+
function: esp_tee_sec_storage_ecdsa_sign_pbkdf2
288+
args: 5
285289
# ID: 195-199 (5) - OTA
286290
- family: ota
287291
entries:

components/esp_tee/subproject/components/tee_sec_storage/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ set(priv_requires esp_tee)
55

66
if(esp_tee_build)
77
list(APPEND srcs "tee_sec_storage.c")
8-
list(APPEND priv_requires efuse esp_partition log mbedtls nvs_flash spi_flash tee_flash_mgr)
8+
list(APPEND priv_requires efuse esp_partition esp_security log mbedtls nvs_flash spi_flash tee_flash_mgr)
99
else()
1010
if(CONFIG_SECURE_ENABLE_TEE)
1111
list(APPEND srcs "tee_sec_storage_wrapper.c")

components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ typedef struct {
5555
size_t input_len; /*!< Length of input data */
5656
} esp_tee_sec_storage_aead_ctx_t;
5757

58+
/**
59+
* @brief Context structure for ECDSA signing with PBKDF2 (HMAC) derived key
60+
*
61+
*/
62+
typedef struct {
63+
const uint8_t *salt; /*!< Salt for PBKDF2 */
64+
size_t salt_len; /*!< Length of the salt */
65+
esp_tee_sec_storage_type_t key_type; /*!< Key type to be generated and used */
66+
} esp_tee_sec_storage_pbkdf2_ctx_t;
67+
5868
/**
5969
* @brief Structure holding the X and Y components of the ECDSA public key
6070
*
@@ -149,6 +159,22 @@ esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t
149159
*/
150160
esp_err_t esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *tag, size_t tag_len, uint8_t *output);
151161

162+
/**
163+
* @brief Generate and return the signature for the specified message digest using
164+
* the key pair derived via PBKDF2-HMAC-SHA256 using the HMAC peripheral
165+
* with the given salt and the configured HMAC eFuse key ID
166+
* (`CONFIG_SECURE_TEE_PBKDF2_EFUSE_HMAC_KEY_ID`).
167+
*
168+
* @param[in] ctx Pointer to the PBKDF2 context
169+
* @param[in] hash Message digest
170+
* @param[in] hlen Digest length
171+
* @param[out] out_sign Output context holding the signature
172+
* @param[out] out_pubkey Output context holding the public key
173+
*
174+
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
175+
*/
176+
esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2_ctx_t *ctx, const uint8_t *hash, size_t hlen, esp_tee_sec_storage_ecdsa_sign_t *out_sign, esp_tee_sec_storage_ecdsa_pubkey_t *out_pubkey);
177+
152178
#ifdef __cplusplus
153179
}
154180
#endif

components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c

Lines changed: 157 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "esp_fault.h"
1212
#include "esp_flash.h"
1313
#include "esp_efuse.h"
14+
#include "esp_efuse_chip.h"
15+
#include "esp_hmac.h"
1416
#include "esp_random.h"
1517
#include "spi_flash_mmap.h"
1618

@@ -19,11 +21,8 @@
1921
#include "mbedtls/sha256.h"
2022
#include "mbedtls/ecdsa.h"
2123
#include "mbedtls/error.h"
24+
#include "esp_hmac_pbkdf2.h"
2225

23-
#include "rom/efuse.h"
24-
#if SOC_HMAC_SUPPORTED
25-
#include "rom/hmac.h"
26-
#endif
2726
#include "esp_rom_sys.h"
2827
#include "nvs.h"
2928
#include "nvs_flash.h"
@@ -40,9 +39,13 @@
4039
#define ECDSA_SECP256R1_KEY_LEN 32
4140
#define ECDSA_SECP192R1_KEY_LEN 24
4241

42+
#define SHA256_DIGEST_SZ 32
43+
4344
#define EKEY_SEED 0xAEBE5A5A
4445
#define TKEY_SEED 0xCEDEA5A5
4546

47+
#define PBKDF2_HMAC_ITER 2048
48+
4649
/* Structure to hold ECDSA SECP256R1 key pair */
4750
typedef struct {
4851
uint8_t priv_key[ECDSA_SECP256R1_KEY_LEN]; /* Private key for ECDSA SECP256R1 */
@@ -84,6 +87,10 @@ static const char *TAG = "secure_storage";
8487
#error "TEE Secure Storage: Configured eFuse block (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID) out of range!"
8588
#endif
8689

90+
#if CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID == CONFIG_SECURE_TEE_PBKDF2_EFUSE_HMAC_KEY_ID
91+
#error "TEE Secure Storage: Configured eFuse block for storage encryption keys (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID) and PBKDF2 key derivation (CONFIG_SECURE_TEE_PBKDF2_EFUSE_HMAC_KEY_ID) cannot be the same!"
92+
#endif
93+
8794
static int buffer_hexdump(const char *label, const void *buffer, size_t length)
8895
{
8996
#if CONFIG_SECURE_TEE_LOG_LEVEL >= 4
@@ -130,24 +137,21 @@ static int rand_func(void *rng_state, unsigned char *output, size_t len)
130137
}
131138

132139
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
133-
static esp_err_t compute_nvs_keys_with_hmac(ets_efuse_block_t hmac_key, nvs_sec_cfg_t *cfg)
140+
static esp_err_t compute_nvs_keys_with_hmac(hmac_key_id_t hmac_key_id, nvs_sec_cfg_t *cfg)
134141
{
135142
uint32_t ekey_seed[8] = {[0 ... 7] = EKEY_SEED};
136143
uint32_t tkey_seed[8] = {[0 ... 7] = TKEY_SEED};
137144

138145
memset(cfg, 0x00, sizeof(nvs_sec_cfg_t));
139146

140-
int ret = -1;
141-
ets_hmac_enable();
142-
ret = ets_hmac_calculate_message(hmac_key, ekey_seed, sizeof(ekey_seed), (uint8_t *)cfg->eky);
143-
ret = ets_hmac_calculate_message(hmac_key, tkey_seed, sizeof(tkey_seed), (uint8_t *)cfg->tky);
144-
ets_hmac_disable();
145-
146-
if (ret != 0) {
147+
esp_err_t err = ESP_FAIL;
148+
err = esp_hmac_calculate(hmac_key_id, ekey_seed, sizeof(ekey_seed), (uint8_t *)cfg->eky);
149+
err |= esp_hmac_calculate(hmac_key_id, tkey_seed, sizeof(tkey_seed), (uint8_t *)cfg->tky);
150+
if (err != ESP_OK) {
147151
ESP_LOGE(TAG, "Failed to calculate seed HMAC");
148152
return ESP_FAIL;
149153
}
150-
ESP_FAULT_ASSERT(ret == 0);
154+
ESP_FAULT_ASSERT(err == ESP_OK);
151155

152156
/* NOTE: If the XTS E-key and T-key are the same, we have a hash collision */
153157
ESP_FAULT_ASSERT(memcmp(cfg->eky, cfg->tky, NVS_KEY_SIZE) != 0);
@@ -163,14 +167,14 @@ static esp_err_t read_security_cfg_hmac(nvs_sec_cfg_t *cfg)
163167
}
164168

165169
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
166-
ets_efuse_block_t hmac_key = (ets_efuse_block_t)(ETS_EFUSE_BLOCK_KEY0 + CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
167-
ets_efuse_purpose_t hmac_efuse_blk_purpose = ets_efuse_get_key_purpose(hmac_key);
168-
if (hmac_efuse_blk_purpose != ETS_EFUSE_KEY_PURPOSE_HMAC_UP) {
170+
esp_efuse_block_t hmac_key_blk = (esp_efuse_block_t)(EFUSE_BLK_KEY0 + (esp_efuse_block_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
171+
esp_efuse_purpose_t hmac_efuse_blk_purpose = esp_efuse_get_key_purpose(hmac_key_blk);
172+
if (hmac_efuse_blk_purpose != ESP_EFUSE_KEY_PURPOSE_HMAC_UP) {
169173
ESP_LOGE(TAG, "HMAC key is not burnt in eFuse block");
170174
return ESP_ERR_NOT_FOUND;
171175
}
172176

173-
esp_err_t err = compute_nvs_keys_with_hmac(hmac_key, cfg);
177+
esp_err_t err = compute_nvs_keys_with_hmac((hmac_key_id_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID, cfg);
174178
if (err != ESP_OK) {
175179
return err;
176180
}
@@ -304,17 +308,17 @@ static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t
304308
NULL;
305309
#endif
306310

307-
ret = mbedtls_mpi_write_binary(&ctxECDSA.MBEDTLS_PRIVATE(d), priv_key, key_len);
311+
ret = mbedtls_mpi_write_binary(&(ctxECDSA.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), pub_key, key_len);
308312
if (ret != 0) {
309313
goto exit;
310314
}
311315

312-
ret = mbedtls_mpi_write_binary(&(ctxECDSA.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), pub_key, key_len);
316+
ret = mbedtls_mpi_write_binary(&(ctxECDSA.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), pub_key + key_len, key_len);
313317
if (ret != 0) {
314318
goto exit;
315319
}
316320

317-
ret = mbedtls_mpi_write_binary(&(ctxECDSA.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), pub_key + key_len, key_len);
321+
ret = mbedtls_mpi_write_binary(&ctxECDSA.MBEDTLS_PRIVATE(d), priv_key, key_len);
318322
if (ret != 0) {
319323
goto exit;
320324
}
@@ -457,18 +461,17 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
457461
}
458462

459463
memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t));
460-
461464
ret = mbedtls_mpi_write_binary(&r, out_sign->sign_r, key_len);
462-
if (ret != 0) {
463-
err = ESP_FAIL;
464-
goto exit;
465+
if (ret == 0) {
466+
ret = mbedtls_mpi_write_binary(&s, out_sign->sign_s, key_len);
465467
}
466468

467-
ret = mbedtls_mpi_write_binary(&s, out_sign->sign_s, key_len);
468469
if (ret != 0) {
470+
memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t));
469471
err = ESP_FAIL;
470472
goto exit;
471473
}
474+
472475
err = ESP_OK;
473476

474477
exit:
@@ -606,3 +609,132 @@ esp_err_t esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t
606609
{
607610
return tee_sec_storage_crypt_common(ctx->key_id, ctx->input, ctx->input_len, ctx->aad, ctx->aad_len, (uint8_t *)tag, tag_len, output, false);
608611
}
612+
613+
esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2_ctx_t *ctx,
614+
const uint8_t *hash, size_t hlen,
615+
esp_tee_sec_storage_ecdsa_sign_t *out_sign,
616+
esp_tee_sec_storage_ecdsa_pubkey_t *out_pubkey)
617+
{
618+
if (!ctx || !hash || !out_sign || !out_pubkey || !ctx->salt || ctx->salt_len == 0) {
619+
return ESP_ERR_INVALID_ARG;
620+
}
621+
622+
if (hlen != SHA256_DIGEST_SZ) {
623+
return ESP_ERR_INVALID_SIZE;
624+
}
625+
626+
esp_err_t err = ESP_FAIL;
627+
size_t key_len;
628+
mbedtls_ecp_group_id curve_id = MBEDTLS_ECP_DP_NONE;
629+
630+
switch (ctx->key_type) {
631+
case ESP_SEC_STG_KEY_ECDSA_SECP256R1:
632+
key_len = ECDSA_SECP256R1_KEY_LEN;
633+
curve_id = MBEDTLS_ECP_DP_SECP256R1;
634+
break;
635+
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN
636+
case ESP_SEC_STG_KEY_ECDSA_SECP192R1:
637+
key_len = ECDSA_SECP192R1_KEY_LEN;
638+
curve_id = MBEDTLS_ECP_DP_SECP192R1;
639+
break;
640+
#endif
641+
default:
642+
ESP_LOGE(TAG, "Unsupported key type");
643+
return ESP_ERR_INVALID_ARG;
644+
}
645+
646+
hmac_key_id_t key_id = (hmac_key_id_t)(CONFIG_SECURE_TEE_PBKDF2_EFUSE_HMAC_KEY_ID);
647+
esp_efuse_block_t blk = EFUSE_BLK_KEY0 + (esp_efuse_block_t)(key_id);
648+
if (esp_efuse_get_key_purpose(blk) != ESP_EFUSE_KEY_PURPOSE_HMAC_UP) {
649+
ESP_LOGE(TAG, "HMAC key is not burnt in the specified eFuse block ID");
650+
return ESP_ERR_NOT_FOUND;
651+
}
652+
653+
uint8_t *derived_key = calloc(1, key_len);
654+
if (!derived_key) {
655+
return ESP_ERR_NO_MEM;
656+
}
657+
658+
err = esp_hmac_derive_pbkdf2_key(key_id, ctx->salt, ctx->salt_len, PBKDF2_HMAC_ITER, key_len, derived_key);
659+
if (err != ESP_OK) {
660+
goto exit;
661+
}
662+
663+
mbedtls_ecp_keypair keypair;
664+
mbedtls_mpi r, s;
665+
666+
mbedtls_ecp_keypair_init(&keypair);
667+
mbedtls_mpi_init(&r);
668+
mbedtls_mpi_init(&s);
669+
670+
int ret = -1;
671+
672+
ret = mbedtls_ecp_group_load(&keypair.MBEDTLS_PRIVATE(grp), curve_id);
673+
if (ret != 0) {
674+
err = ESP_FAIL;
675+
goto exit;
676+
}
677+
678+
ret = mbedtls_mpi_read_binary(&keypair.MBEDTLS_PRIVATE(d), derived_key, key_len);
679+
if (ret != 0) {
680+
err = ESP_FAIL;
681+
goto exit;
682+
}
683+
684+
ret = mbedtls_ecp_check_privkey(&keypair.MBEDTLS_PRIVATE(grp), &keypair.MBEDTLS_PRIVATE(d));
685+
if (ret != 0) {
686+
ESP_LOGE(TAG, "Invalid private key!");
687+
err = ESP_FAIL;
688+
goto exit;
689+
}
690+
691+
ret = mbedtls_ecp_keypair_calc_public(&keypair, rand_func, NULL);
692+
if (ret != 0) {
693+
err = ESP_FAIL;
694+
goto exit;
695+
}
696+
697+
ret = mbedtls_ecdsa_sign(&keypair.MBEDTLS_PRIVATE(grp), &r, &s,
698+
&keypair.MBEDTLS_PRIVATE(d), hash, hlen,
699+
rand_func, NULL);
700+
if (ret != 0) {
701+
err = ESP_FAIL;
702+
goto exit;
703+
}
704+
705+
memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t));
706+
ret = mbedtls_mpi_write_binary(&r, out_sign->sign_r, key_len);
707+
if (ret == 0) {
708+
ret = mbedtls_mpi_write_binary(&s, out_sign->sign_s, key_len);
709+
}
710+
711+
if (ret != 0) {
712+
memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t));
713+
err = ESP_FAIL;
714+
goto exit;
715+
}
716+
717+
memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t));
718+
ret = mbedtls_mpi_write_binary(&keypair.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), out_pubkey->pub_x, key_len);
719+
if (ret == 0) {
720+
ret = mbedtls_mpi_write_binary(&keypair.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), out_pubkey->pub_y, key_len);
721+
}
722+
723+
if (ret != 0) {
724+
memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t));
725+
err = ESP_FAIL;
726+
goto exit;
727+
}
728+
729+
err = ESP_OK;
730+
731+
exit:
732+
if (derived_key) {
733+
memset(derived_key, 0x00, key_len);
734+
free(derived_key);
735+
}
736+
mbedtls_ecp_keypair_free(&keypair);
737+
mbedtls_mpi_free(&r);
738+
mbedtls_mpi_free(&s);
739+
return err;
740+
}

components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage_wrapper.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,8 @@ esp_err_t esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t
3737
{
3838
return esp_tee_service_call_with_noniram_intr_disabled(5, SS_ESP_TEE_SEC_STORAGE_AEAD_DECRYPT, ctx, tag, tag_len, output);
3939
}
40+
41+
esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2_ctx_t *ctx, const uint8_t *hash, size_t hlen, esp_tee_sec_storage_ecdsa_sign_t *out_sign, esp_tee_sec_storage_ecdsa_pubkey_t *out_pubkey)
42+
{
43+
return esp_tee_service_call(6, SS_ESP_TEE_SEC_STORAGE_ECDSA_SIGN_PBKDF2, ctx, hash, hlen, out_sign, out_pubkey);
44+
}

0 commit comments

Comments
 (0)