mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-27 16:56:43 +03:00
Merge branch 'feat/tee_sec_stg_non_det_sign' into 'master'
change(esp_tee): Force non-deterministic ECDSA signing for TEE secure storage keys Closes IDF-15937 and IDF-15939 See merge request espressif/esp-idf!50355
This commit is contained in:
@@ -18,6 +18,8 @@
|
||||
|
||||
#if !ESP_TEE_BUILD
|
||||
#include "esp_private/startup_internal.h"
|
||||
#else
|
||||
#include "esp_fault.h"
|
||||
#endif
|
||||
|
||||
#include "hal/rtc_timer_hal.h"
|
||||
@@ -80,6 +82,9 @@ uint32_t IRAM_ATTR esp_random(void)
|
||||
uint32_t result = 0;
|
||||
for (size_t i = 0; i < sizeof(result); i++) {
|
||||
do {
|
||||
#if ESP_TEE_BUILD
|
||||
ESP_FAULT_ASSERT(rng_ll_is_enabled());
|
||||
#endif
|
||||
ccount = esp_cpu_get_cycle_count();
|
||||
result ^= rng_ll_read_data();
|
||||
} while (ccount - last_ccount < cpu_to_apb_freq_ratio * APB_CYCLE_WAIT_NUM);
|
||||
|
||||
@@ -334,11 +334,12 @@ esp_err_t esp_ds_start_sign(const void *message,
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (!(data->rsa_length == ESP_DS_RSA_1024
|
||||
|| data->rsa_length == ESP_DS_RSA_2048
|
||||
|| data->rsa_length == ESP_DS_RSA_3072
|
||||
const uint32_t rsa_length = data->rsa_length;
|
||||
if (!(rsa_length == ESP_DS_RSA_1024
|
||||
|| rsa_length == ESP_DS_RSA_2048
|
||||
|| rsa_length == ESP_DS_RSA_3072
|
||||
#if SOC_RSA_MAX_BIT_LEN == 4096
|
||||
|| data->rsa_length == ESP_DS_RSA_4096
|
||||
|| rsa_length == ESP_DS_RSA_4096
|
||||
#endif
|
||||
)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -393,7 +394,7 @@ esp_err_t esp_ds_start_sign(const void *message,
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
size_t rsa_len = (data->rsa_length + 1) * 4;
|
||||
size_t rsa_len = (rsa_length + 1) * 4;
|
||||
ds_hal_write_private_key_params(data->c);
|
||||
ds_hal_configure_iv((uint32_t *)data->iv);
|
||||
ds_hal_write_message(message, rsa_len);
|
||||
@@ -426,22 +427,31 @@ esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
}
|
||||
|
||||
const esp_ds_data_t *data = (const esp_ds_data_t *)esp_ds_ctx->data;
|
||||
unsigned rsa_len = (data->rsa_length + 1) * 4;
|
||||
esp_err_t return_value = ESP_ERR_INVALID_ARG;
|
||||
|
||||
while (ds_hal_busy()) { }
|
||||
|
||||
ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t *) signature, (size_t) rsa_len);
|
||||
uint32_t rsa_length = data->rsa_length;
|
||||
if (rsa_length == ESP_DS_RSA_1024
|
||||
|| rsa_length == ESP_DS_RSA_2048
|
||||
|| rsa_length == ESP_DS_RSA_3072
|
||||
#if SOC_DS_SIGNATURE_MAX_BIT_LEN == 4096
|
||||
|| rsa_length == ESP_DS_RSA_4096
|
||||
#endif
|
||||
) {
|
||||
unsigned rsa_len = (rsa_length + 1) * 4;
|
||||
|
||||
esp_err_t return_value = ESP_OK;
|
||||
ds_signature_check_t res = ds_hal_read_result((uint8_t *) signature, (size_t) rsa_len);
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
|
||||
esp_ds_zeroize(signature, rsa_len);
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||
}
|
||||
|
||||
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
|
||||
esp_ds_zeroize(signature, rsa_len);
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||
if (res == DS_SIGNATURE_MD_FAIL || res == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
|
||||
esp_ds_zeroize(signature, rsa_len);
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||
} else if (res == DS_SIGNATURE_PADDING_FAIL) {
|
||||
esp_ds_zeroize(signature, rsa_len);
|
||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||
} else if (res == DS_SIGNATURE_OK) {
|
||||
return_value = ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
#if !ESP_TEE_BUILD
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "esp_fault.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_chip.h"
|
||||
#include "esp_random.h"
|
||||
#include "spi_flash_mmap.h"
|
||||
#if SOC_HMAC_SUPPORTED
|
||||
#include "psa_crypto_driver_esp_hmac_opaque.h"
|
||||
@@ -314,6 +313,13 @@ bool esp_tee_sec_storage_is_key_tee_owned(const char *key_id)
|
||||
|
||||
esp_err_t esp_tee_sec_storage_init(void)
|
||||
{
|
||||
/* Explicitly seeds the CTR-DRBG before any PSA operations */
|
||||
uint8_t random;
|
||||
psa_status_t ret = psa_generate_random(&random, sizeof(random));
|
||||
if (ret != PSA_SUCCESS) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
nvs_sec_cfg_t cfg = {};
|
||||
esp_err_t err = read_security_cfg_hmac(&cfg);
|
||||
if (err != ESP_OK) {
|
||||
@@ -479,9 +485,9 @@ static int generate_aes256_key(sec_stg_key_t *keyctx)
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Generating AES-256 key...");
|
||||
esp_fill_random(&keyctx->aes256.key, AES256_KEY_LEN);
|
||||
psa_status_t status = psa_generate_random(keyctx->aes256.key, AES256_KEY_LEN);
|
||||
|
||||
return 0;
|
||||
return (status == PSA_SUCCESS) ? 0 : -1;
|
||||
}
|
||||
|
||||
esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
|
||||
@@ -569,11 +575,9 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
|
||||
|
||||
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
|
||||
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_VERIFY_HASH);
|
||||
psa_algorithm_t ecdsa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
|
||||
|
||||
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC
|
||||
ecdsa_alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256);
|
||||
#endif
|
||||
/* ECDSA signatures over TEE secure-storage keys are compulsorily non-deterministic */
|
||||
psa_algorithm_t ecdsa_alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
|
||||
|
||||
psa_set_key_algorithm(&key_attributes, ecdsa_alg);
|
||||
|
||||
@@ -747,7 +751,11 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
|
||||
}
|
||||
|
||||
if (is_encrypt) {
|
||||
esp_fill_random(iv, iv_len);
|
||||
status = psa_generate_random(iv, iv_len);
|
||||
if (status != PSA_SUCCESS) {
|
||||
err = ESP_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
size_t output_length = 0;
|
||||
status = psa_aead_encrypt(psa_key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len),
|
||||
|
||||
@@ -71,7 +71,8 @@ int _ss_esp_aes_crypt_cbc(esp_aes_context *ctx,
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
return esp_aes_crypt_cbc(ctx, mode, length, iv, input, output);
|
||||
esp_aes_context ctx_local = *ctx;
|
||||
return esp_aes_crypt_cbc(&ctx_local, mode, length, iv, input, output);
|
||||
}
|
||||
|
||||
int _ss_esp_aes_crypt_cfb128(esp_aes_context *ctx,
|
||||
@@ -93,7 +94,8 @@ int _ss_esp_aes_crypt_cfb128(esp_aes_context *ctx,
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
return esp_aes_crypt_cfb128(ctx, mode, length, iv_off, iv, input, output);
|
||||
esp_aes_context ctx_local = *ctx;
|
||||
return esp_aes_crypt_cfb128(&ctx_local, mode, length, iv_off, iv, input, output);
|
||||
}
|
||||
|
||||
int _ss_esp_aes_crypt_cfb8(esp_aes_context *ctx,
|
||||
@@ -113,7 +115,8 @@ int _ss_esp_aes_crypt_cfb8(esp_aes_context *ctx,
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
return esp_aes_crypt_cfb8(ctx, mode, length, iv, input, output);
|
||||
esp_aes_context ctx_local = *ctx;
|
||||
return esp_aes_crypt_cfb8(&ctx_local, mode, length, iv, input, output);
|
||||
}
|
||||
|
||||
int _ss_esp_aes_crypt_ctr(esp_aes_context *ctx,
|
||||
@@ -136,7 +139,8 @@ int _ss_esp_aes_crypt_ctr(esp_aes_context *ctx,
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
return esp_aes_crypt_ctr(ctx, length, nc_off, nonce_counter, stream_block, input, output);
|
||||
esp_aes_context ctx_local = *ctx;
|
||||
return esp_aes_crypt_ctr(&ctx_local, length, nc_off, nonce_counter, stream_block, input, output);
|
||||
}
|
||||
|
||||
int _ss_esp_aes_crypt_ecb(esp_aes_context *ctx,
|
||||
@@ -153,7 +157,8 @@ int _ss_esp_aes_crypt_ecb(esp_aes_context *ctx,
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
return esp_aes_crypt_ecb(ctx, mode, input, output);
|
||||
esp_aes_context ctx_local = *ctx;
|
||||
return esp_aes_crypt_ecb(&ctx_local, mode, input, output);
|
||||
}
|
||||
|
||||
int _ss_esp_aes_crypt_ofb(esp_aes_context *ctx,
|
||||
@@ -174,7 +179,8 @@ int _ss_esp_aes_crypt_ofb(esp_aes_context *ctx,
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
return esp_aes_crypt_ofb(ctx, length, iv_off, iv, input, output);
|
||||
esp_aes_context ctx_local = *ctx;
|
||||
return esp_aes_crypt_ofb(&ctx_local, length, iv_off, iv, input, output);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -401,8 +407,10 @@ esp_err_t _ss_esp_ds_sign(const void *message,
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
size_t n = get_ds_msg_sign_len(data->rsa_length);
|
||||
valid_addr &= (n > 0) && esp_tee_buf_in_ree(message, n) && esp_tee_buf_in_ree(signature, n);
|
||||
const size_t n_max = SOC_DS_SIGNATURE_MAX_BIT_LEN / 8;
|
||||
valid_addr &= (get_ds_msg_sign_len(data->rsa_length) > 0) &&
|
||||
esp_tee_buf_in_ree(message, n_max) &&
|
||||
esp_tee_buf_in_ree(signature, n_max);
|
||||
|
||||
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
|
||||
valid_addr &= (key_id != (hmac_key_id_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
|
||||
@@ -422,15 +430,21 @@ esp_err_t _ss_esp_ds_start_sign(const void *message,
|
||||
hmac_key_id_t key_id,
|
||||
esp_ds_context_t **esp_ds_ctx)
|
||||
{
|
||||
bool valid_addr = (esp_tee_buf_in_ree(esp_ds_ctx, sizeof(esp_ds_context_t *)) &&
|
||||
esp_tee_buf_in_ree(*esp_ds_ctx, sizeof(esp_ds_context_t)) &&
|
||||
if (!esp_tee_buf_in_ree(esp_ds_ctx, sizeof(esp_ds_context_t *))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_ds_context_t *ds_ctx = *esp_ds_ctx;
|
||||
const size_t n_max = SOC_DS_SIGNATURE_MAX_BIT_LEN / 8;
|
||||
|
||||
bool valid_addr = (esp_tee_buf_in_ree(ds_ctx, sizeof(esp_ds_context_t)) &&
|
||||
esp_tee_buf_in_ree(data, sizeof(esp_ds_data_t)));
|
||||
if (!valid_addr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
size_t n = get_ds_msg_sign_len(data->rsa_length);
|
||||
valid_addr &= (n > 0) && esp_tee_buf_in_ree(message, n);
|
||||
valid_addr &= (get_ds_msg_sign_len(data->rsa_length) > 0) &&
|
||||
esp_tee_buf_in_ree(message, n_max);
|
||||
|
||||
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
|
||||
valid_addr &= (key_id != (hmac_key_id_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
|
||||
@@ -442,7 +456,12 @@ esp_err_t _ss_esp_ds_start_sign(const void *message,
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
return esp_ds_start_sign(message, data, key_id, esp_ds_ctx);
|
||||
esp_err_t err = esp_ds_start_sign(message, data, key_id, &ds_ctx);
|
||||
if (err == ESP_OK) {
|
||||
*esp_ds_ctx = ds_ctx;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool _ss_esp_ds_is_busy(void)
|
||||
@@ -452,14 +471,16 @@ bool _ss_esp_ds_is_busy(void)
|
||||
|
||||
esp_err_t _ss_esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
{
|
||||
const size_t max_sign = SOC_DS_SIGNATURE_MAX_BIT_LEN / 8;
|
||||
bool valid_addr = (esp_tee_buf_in_ree(signature, max_sign) &&
|
||||
const size_t n_max = SOC_DS_SIGNATURE_MAX_BIT_LEN / 8;
|
||||
bool valid_addr = (esp_tee_buf_in_ree(signature, n_max) &&
|
||||
esp_tee_buf_in_ree(esp_ds_ctx, sizeof(esp_ds_context_t)));
|
||||
if (!valid_addr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_ds_data_t *data = (const esp_ds_data_t *)esp_ds_ctx->data;
|
||||
const esp_ds_context_t ctx_local = *esp_ds_ctx;
|
||||
|
||||
const esp_ds_data_t *data = (const esp_ds_data_t *)ctx_local.data;
|
||||
valid_addr &= esp_tee_buf_in_ree(data, sizeof(esp_ds_data_t)) &&
|
||||
(get_ds_msg_sign_len(data->rsa_length) > 0);
|
||||
|
||||
@@ -468,7 +489,7 @@ esp_err_t _ss_esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
return esp_ds_finish_sign(signature, esp_ds_ctx);
|
||||
return esp_ds_finish_sign(signature, (esp_ds_context_t *)&ctx_local);
|
||||
}
|
||||
|
||||
esp_err_t _ss_esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||
@@ -583,15 +604,11 @@ int _ss_esp_tee_ota_end(void)
|
||||
|
||||
/* ---------------------------------------------- Secure Storage ------------------------------------------------- */
|
||||
|
||||
/* NOTE: The key-name pointers here (cfg->id/ctx->key_id) are REE-supplied, NULL-terminated
|
||||
* NVS key names used read-only for key lookup (NVS compares them with strncmp bounded to
|
||||
* NVS_KEY_NAME_MAX_SIZE-1) — never written through, never used as a register base.
|
||||
* Pointing one at TEE memory yields at most a load-fault DoS or a useless presence oracle,
|
||||
* so they are left unchecked. Argument checks cost code size and add latency to every
|
||||
* service call, so we keep only the ones that close a real REE->TEE read/write/control-flow gap.
|
||||
*/
|
||||
esp_err_t _ss_esp_tee_sec_storage_clear_key(const char *key_id)
|
||||
{
|
||||
char id_buf[NVS_KEY_NAME_MAX_SIZE];
|
||||
tee_snapshot_ree_str(&key_id, id_buf, sizeof(id_buf));
|
||||
|
||||
bool valid_arg = !esp_tee_sec_storage_is_key_tee_owned(key_id);
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -603,15 +620,22 @@ esp_err_t _ss_esp_tee_sec_storage_clear_key(const char *key_id)
|
||||
|
||||
esp_err_t _ss_esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
|
||||
{
|
||||
bool valid_arg = esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
!(cfg->flags & SEC_STORAGE_FLAG_TEE_ONLY) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id);
|
||||
if (!esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_tee_sec_storage_key_cfg_t cfg_local = *cfg;
|
||||
char id_buf[NVS_KEY_NAME_MAX_SIZE];
|
||||
tee_snapshot_ree_str(&cfg_local.id, id_buf, sizeof(id_buf));
|
||||
|
||||
bool valid_arg = !(cfg_local.flags & SEC_STORAGE_FLAG_TEE_ONLY) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg_local.id);
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_gen_key(cfg);
|
||||
return esp_tee_sec_storage_gen_key(&cfg_local);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------- PSA Attestation ------------------------------------------------- */
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
@@ -164,70 +165,90 @@ void _ss_wdt_hal_init(wdt_hal_context_t *hal, wdt_inst_t wdt_inst, uint32_t pres
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
wdt_hal_init(hal, wdt_inst, prescaler, enable_intr);
|
||||
wdt_hal_context_t hal_local;
|
||||
wdt_hal_init(&hal_local, wdt_inst, prescaler, enable_intr);
|
||||
|
||||
*hal = hal_local;
|
||||
}
|
||||
|
||||
void _ss_wdt_hal_deinit(wdt_hal_context_t *hal)
|
||||
{
|
||||
bool valid_addr = (esp_tee_buf_in_ree(hal, sizeof(wdt_hal_context_t)) &&
|
||||
is_wdt_dev_valid(hal->mwdt_dev));
|
||||
if (!esp_tee_buf_in_ree(hal, sizeof(wdt_hal_context_t))) {
|
||||
return;
|
||||
}
|
||||
|
||||
wdt_hal_context_t hal_snap = *hal;
|
||||
|
||||
bool valid_addr = is_wdt_dev_valid(hal_snap.mwdt_dev);
|
||||
if (!valid_addr) {
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
wdt_hal_deinit(hal);
|
||||
wdt_hal_deinit(&hal_snap);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------- Secure Storage ------------------------------------------------- */
|
||||
|
||||
/* NOTE: The key-name pointers here (cfg->id/ctx->key_id) are REE-supplied, NULL-terminated
|
||||
* NVS key names used read-only for key lookup (NVS compares them with strncmp bounded to
|
||||
* NVS_KEY_NAME_MAX_SIZE-1) — never written through, never used as a register base.
|
||||
* Pointing one at TEE memory yields at most a load-fault DoS or a useless presence oracle,
|
||||
* so they are left unchecked. Argument checks cost code size and add latency to every
|
||||
* service call, so we keep only the ones that close a real REE->TEE read/write/control-flow gap.
|
||||
* The buffers alongside these ARE validated, since the TEE reads/writes them.
|
||||
*/
|
||||
esp_err_t _ss_esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cfg, const uint8_t *hash, size_t hlen, esp_tee_sec_storage_ecdsa_sign_t *out_sign)
|
||||
{
|
||||
bool valid_arg = (esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(hash, hlen) &&
|
||||
if (!esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_tee_sec_storage_key_cfg_t cfg_local = *cfg;
|
||||
char id_buf[NVS_KEY_NAME_MAX_SIZE];
|
||||
tee_snapshot_ree_str(&cfg_local.id, id_buf, sizeof(id_buf));
|
||||
|
||||
bool valid_arg = (esp_tee_buf_in_ree(hash, hlen) &&
|
||||
esp_tee_buf_in_ree(out_sign, sizeof(esp_tee_sec_storage_ecdsa_sign_t)) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id));
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg_local.id));
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_ecdsa_sign(cfg, hash, hlen, out_sign);
|
||||
return esp_tee_sec_storage_ecdsa_sign(&cfg_local, hash, hlen, out_sign);
|
||||
}
|
||||
|
||||
esp_err_t _ss_esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg_t *cfg, esp_tee_sec_storage_ecdsa_pubkey_t *out_pubkey)
|
||||
{
|
||||
bool valid_arg = (esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t)) &&
|
||||
esp_tee_buf_in_ree(out_pubkey, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id));
|
||||
if (!esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_tee_sec_storage_key_cfg_t cfg_local = *cfg;
|
||||
char id_buf[NVS_KEY_NAME_MAX_SIZE];
|
||||
tee_snapshot_ree_str(&cfg_local.id, id_buf, sizeof(id_buf));
|
||||
|
||||
bool valid_arg = (esp_tee_buf_in_ree(out_pubkey, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(cfg_local.id));
|
||||
if (!valid_arg) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_ecdsa_get_pubkey(cfg, out_pubkey);
|
||||
return esp_tee_sec_storage_ecdsa_get_pubkey(&cfg_local, out_pubkey);
|
||||
}
|
||||
|
||||
esp_err_t _ss_esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *iv, size_t iv_len, uint8_t *tag, size_t tag_len, uint8_t *output)
|
||||
{
|
||||
bool valid_arg = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
if (!esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_tee_sec_storage_aead_ctx_t ctx_local = *ctx;
|
||||
char id_buf[NVS_KEY_NAME_MAX_SIZE];
|
||||
tee_snapshot_ree_str(&ctx_local.key_id, id_buf, sizeof(id_buf));
|
||||
|
||||
bool valid_arg = (esp_tee_buf_in_ree(ctx_local.input, ctx_local.input_len) &&
|
||||
esp_tee_buf_in_ree(iv, iv_len) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(ctx->key_id));
|
||||
esp_tee_buf_in_ree(output, ctx_local.input_len) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(ctx_local.key_id));
|
||||
|
||||
if (ctx->aad_len != 0) {
|
||||
valid_arg &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
if (ctx_local.aad_len != 0) {
|
||||
valid_arg &= esp_tee_buf_in_ree(ctx_local.aad, ctx_local.aad_len);
|
||||
}
|
||||
|
||||
if (!valid_arg) {
|
||||
@@ -235,20 +256,27 @@ esp_err_t _ss_esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ct
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_aead_encrypt(ctx, iv, iv_len, tag, tag_len, output);
|
||||
return esp_tee_sec_storage_aead_encrypt(&ctx_local, iv, iv_len, tag, tag_len, output);
|
||||
}
|
||||
|
||||
esp_err_t _ss_esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *iv, size_t iv_len, const uint8_t *tag, size_t tag_len, uint8_t *output)
|
||||
{
|
||||
bool valid_arg = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
||||
if (!esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
esp_tee_sec_storage_aead_ctx_t ctx_local = *ctx;
|
||||
char id_buf[NVS_KEY_NAME_MAX_SIZE];
|
||||
tee_snapshot_ree_str(&ctx_local.key_id, id_buf, sizeof(id_buf));
|
||||
|
||||
bool valid_arg = (esp_tee_buf_in_ree(ctx_local.input, ctx_local.input_len) &&
|
||||
esp_tee_buf_in_ree(iv, iv_len) &&
|
||||
esp_tee_buf_in_ree(tag, tag_len) &&
|
||||
esp_tee_buf_in_ree(output, ctx->input_len) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(ctx->key_id));
|
||||
esp_tee_buf_in_ree(output, ctx_local.input_len) &&
|
||||
!esp_tee_sec_storage_is_key_tee_owned(ctx_local.key_id));
|
||||
|
||||
if (ctx->aad_len != 0) {
|
||||
valid_arg &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
||||
if (ctx_local.aad_len != 0) {
|
||||
valid_arg &= esp_tee_buf_in_ree(ctx_local.aad, ctx_local.aad_len);
|
||||
}
|
||||
|
||||
if (!valid_arg) {
|
||||
@@ -256,23 +284,28 @@ esp_err_t _ss_esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ct
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_arg);
|
||||
|
||||
return esp_tee_sec_storage_aead_decrypt(ctx, iv, iv_len, tag, tag_len, output);
|
||||
return esp_tee_sec_storage_aead_decrypt(&ctx_local, iv, iv_len, tag, tag_len, output);
|
||||
}
|
||||
|
||||
esp_err_t _ss_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)
|
||||
{
|
||||
bool valid_addr = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_pbkdf2_ctx_t)) &&
|
||||
esp_tee_buf_in_ree(hash, hlen) &&
|
||||
if (!esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_pbkdf2_ctx_t))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const esp_tee_sec_storage_pbkdf2_ctx_t ctx_local = *ctx;
|
||||
|
||||
bool valid_addr = (esp_tee_buf_in_ree(hash, hlen) &&
|
||||
esp_tee_buf_in_ree(out_sign, sizeof(esp_tee_sec_storage_ecdsa_sign_t)) &&
|
||||
esp_tee_buf_in_ree(out_pubkey, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t)) &&
|
||||
esp_tee_buf_in_ree(ctx->salt, ctx->salt_len));
|
||||
esp_tee_buf_in_ree(ctx_local.salt, ctx_local.salt_len));
|
||||
|
||||
if (!valid_addr) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
return esp_tee_sec_storage_ecdsa_sign_pbkdf2(ctx, hash, hlen, out_sign, out_pubkey);
|
||||
return esp_tee_sec_storage_ecdsa_sign_pbkdf2(&ctx_local, hash, hlen, out_sign, out_pubkey);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------- MMU HAL ------------------------------------------------- */
|
||||
@@ -379,30 +412,6 @@ static bool is_flash_addr_readable(uint32_t paddr, uint32_t len)
|
||||
return !esp_tee_flash_check_prange_in_tee_region(paddr, len);
|
||||
}
|
||||
|
||||
static bool is_spi_host_in_ree(spi_flash_host_inst_t *host)
|
||||
{
|
||||
const spi_flash_hal_context_t *ctx = (const spi_flash_hal_context_t *)host;
|
||||
|
||||
return (esp_tee_buf_in_ree(host, sizeof(spi_flash_hal_context_t)) &&
|
||||
ctx->spi == spi_flash_ll_get_hw(SPI1_HOST));
|
||||
}
|
||||
|
||||
static bool is_spi_trans_valid(spi_flash_host_inst_t *host, spi_flash_trans_t *trans)
|
||||
{
|
||||
if (!is_spi_host_in_ree(host) || !esp_tee_buf_in_ree(trans, sizeof(spi_flash_trans_t))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid_addr = true;
|
||||
if (trans->mosi_len != 0) {
|
||||
valid_addr &= esp_tee_buf_in_ree(trans->mosi_data, trans->mosi_len);
|
||||
}
|
||||
if (trans->miso_len != 0) {
|
||||
valid_addr &= esp_tee_buf_in_ree(trans->miso_data, trans->miso_len);
|
||||
}
|
||||
return valid_addr;
|
||||
}
|
||||
|
||||
static bool is_spi_cmd_addr_ok(uint32_t addr_bitlen, uint32_t address, uint32_t mosi_len, uint32_t miso_len)
|
||||
{
|
||||
if (addr_bitlen == 0) {
|
||||
@@ -427,206 +436,246 @@ static const spi_flash_host_driver_t tee_host_driver = {
|
||||
.configure_host_io_mode = spi_flash_hal_configure_host_io_mode,
|
||||
};
|
||||
|
||||
static inline const spi_flash_host_driver_t *tee_substitute_host_driver(spi_flash_host_inst_t *host)
|
||||
static spi_flash_host_inst_t *tee_own_host(const spi_flash_host_inst_t *host, spi_flash_hal_context_t *snap)
|
||||
{
|
||||
const spi_flash_host_driver_t *orig = host->driver;
|
||||
host->driver = &tee_host_driver;
|
||||
return orig;
|
||||
if (!esp_tee_buf_in_ree(host, sizeof(spi_flash_hal_context_t))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*snap = *(const spi_flash_hal_context_t *)host;
|
||||
|
||||
/* Reject a host aimed at another peripheral rather than silently retargeting it */
|
||||
if (snap->spi != spi_flash_ll_get_hw(SPI1_HOST)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snap->inst.driver = &tee_host_driver;
|
||||
snap->spi = spi_flash_ll_get_hw(SPI1_HOST);
|
||||
|
||||
return &snap->inst;
|
||||
}
|
||||
|
||||
uint32_t _ss_spi_flash_hal_check_status(spi_flash_host_inst_t *host)
|
||||
{
|
||||
bool valid_addr = is_spi_host_in_ree(host);
|
||||
|
||||
if (!valid_addr) {
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return 0;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
return spi_flash_hal_check_status(host);
|
||||
return spi_flash_hal_check_status(tee_host);
|
||||
}
|
||||
|
||||
esp_err_t _ss_spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans)
|
||||
{
|
||||
bool trans_valid = is_spi_trans_valid(host, trans);
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
if (!esp_tee_buf_in_ree(trans, sizeof(spi_flash_trans_t))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
spi_flash_trans_t trans_snap = *trans;
|
||||
|
||||
bool trans_valid = true;
|
||||
if (trans_snap.mosi_len != 0) {
|
||||
trans_valid &= esp_tee_buf_in_ree(trans_snap.mosi_data, trans_snap.mosi_len);
|
||||
}
|
||||
if (trans_snap.miso_len != 0) {
|
||||
trans_valid &= esp_tee_buf_in_ree(trans_snap.miso_data, trans_snap.miso_len);
|
||||
}
|
||||
trans_valid &= is_spi_cmd_addr_ok(trans_snap.address_bitlen, trans_snap.address,
|
||||
trans_snap.mosi_len, trans_snap.miso_len);
|
||||
if (!trans_valid) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, trans_snap.address);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(trans_valid);
|
||||
|
||||
bool addr_ok = is_spi_cmd_addr_ok(trans->address_bitlen, trans->address, trans->mosi_len, trans->miso_len);
|
||||
if (!addr_ok) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, trans->address);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(addr_ok);
|
||||
|
||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
||||
esp_err_t r = spi_flash_hal_common_command(host, trans);
|
||||
host->driver = orig;
|
||||
return r;
|
||||
return spi_flash_hal_common_command(tee_host, &trans_snap);
|
||||
}
|
||||
|
||||
esp_err_t _ss_spi_flash_hal_device_config(spi_flash_host_inst_t *host)
|
||||
{
|
||||
bool valid_addr = is_spi_host_in_ree(host);
|
||||
|
||||
if (!valid_addr) {
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
return spi_flash_hal_device_config(host);
|
||||
return spi_flash_hal_device_config(tee_host);
|
||||
}
|
||||
|
||||
void _ss_spi_flash_hal_erase_block(spi_flash_host_inst_t *host, uint32_t start_address)
|
||||
{
|
||||
bool valid_addr = (is_spi_host_in_ree(host) &&
|
||||
start_address <= FLASH_ADDR_MAX_24BIT &&
|
||||
is_flash_addr_writable(start_address, FLASH_BLOCK_SIZE));
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
bool valid_addr = (start_address <= FLASH_ADDR_MAX_24BIT &&
|
||||
is_flash_addr_writable(start_address, FLASH_BLOCK_SIZE));
|
||||
if (!valid_addr) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address);
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
||||
spi_flash_hal_erase_block(host, start_address);
|
||||
host->driver = orig;
|
||||
spi_flash_hal_erase_block(tee_host, start_address);
|
||||
}
|
||||
|
||||
void _ss_spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address)
|
||||
{
|
||||
bool valid_addr = (is_spi_host_in_ree(host) &&
|
||||
start_address <= FLASH_ADDR_MAX_24BIT &&
|
||||
is_flash_addr_writable(start_address, FLASH_SECTOR_SIZE));
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
bool valid_addr = (start_address <= FLASH_ADDR_MAX_24BIT &&
|
||||
is_flash_addr_writable(start_address, FLASH_SECTOR_SIZE));
|
||||
if (!valid_addr) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address);
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
||||
spi_flash_hal_erase_sector(host, start_address);
|
||||
host->driver = orig;
|
||||
spi_flash_hal_erase_sector(tee_host, start_address);
|
||||
}
|
||||
|
||||
void _ss_spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length)
|
||||
{
|
||||
bool valid_addr = (is_spi_host_in_ree(host) &&
|
||||
address <= FLASH_ADDR_MAX_24BIT &&
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
bool valid_addr = (address <= FLASH_ADDR_MAX_24BIT &&
|
||||
is_flash_addr_writable(address, length) &&
|
||||
esp_tee_buf_in_ree(buffer, length));
|
||||
|
||||
if (!valid_addr) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
||||
spi_flash_hal_program_page(host, buffer, address, length);
|
||||
host->driver = orig;
|
||||
spi_flash_hal_program_page(tee_host, buffer, address, length);
|
||||
}
|
||||
|
||||
esp_err_t _ss_spi_flash_hal_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len)
|
||||
{
|
||||
bool valid_addr = (is_spi_host_in_ree(host) &&
|
||||
is_flash_addr_readable(address, read_len) &&
|
||||
esp_tee_buf_in_ree(buffer, read_len));
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
bool valid_addr = (is_flash_addr_readable(address, read_len) &&
|
||||
esp_tee_buf_in_ree(buffer, read_len));
|
||||
if (!valid_addr) {
|
||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
||||
esp_err_t r = spi_flash_hal_read(host, buffer, address, read_len);
|
||||
host->driver = orig;
|
||||
return r;
|
||||
return spi_flash_hal_read(tee_host, buffer, address, read_len);
|
||||
}
|
||||
|
||||
void _ss_spi_flash_hal_resume(spi_flash_host_inst_t *host)
|
||||
{
|
||||
bool valid_addr = is_spi_host_in_ree(host);
|
||||
|
||||
if (!valid_addr) {
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
||||
spi_flash_hal_resume(host);
|
||||
host->driver = orig;
|
||||
spi_flash_hal_resume(tee_host);
|
||||
}
|
||||
|
||||
esp_err_t _ss_spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp)
|
||||
{
|
||||
bool valid_addr = is_spi_host_in_ree(host);
|
||||
|
||||
if (!valid_addr) {
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
||||
esp_err_t r = spi_flash_hal_set_write_protect(host, wp);
|
||||
host->driver = orig;
|
||||
return r;
|
||||
return spi_flash_hal_set_write_protect(tee_host, wp);
|
||||
}
|
||||
|
||||
esp_err_t _ss_spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf)
|
||||
{
|
||||
bool valid_addr = (is_spi_host_in_ree(host) &&
|
||||
esp_tee_buf_in_ree(sus_conf, sizeof(spi_flash_sus_cmd_conf)));
|
||||
|
||||
if (!valid_addr) {
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
return spi_flash_hal_setup_read_suspend(host, sus_conf);
|
||||
if (!esp_tee_buf_in_ree(sus_conf, sizeof(spi_flash_sus_cmd_conf))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const spi_flash_sus_cmd_conf sus_snap = *sus_conf;
|
||||
return spi_flash_hal_setup_read_suspend(tee_host, &sus_snap);
|
||||
}
|
||||
|
||||
bool _ss_spi_flash_hal_supports_direct_read(spi_flash_host_inst_t *host, const void *p)
|
||||
{
|
||||
bool valid_addr = (is_spi_host_in_ree(host) && esp_tee_ptr_in_ree(p));
|
||||
|
||||
if (!valid_addr) {
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return false;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
return spi_flash_hal_supports_direct_read(host, p);
|
||||
if (!esp_tee_ptr_in_ree(p)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return spi_flash_hal_supports_direct_read(tee_host, p);
|
||||
}
|
||||
|
||||
bool _ss_spi_flash_hal_supports_direct_write(spi_flash_host_inst_t *host, const void *p)
|
||||
{
|
||||
bool valid_addr = (is_spi_host_in_ree(host) && esp_tee_ptr_in_ree(p));
|
||||
|
||||
if (!valid_addr) {
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return false;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
return spi_flash_hal_supports_direct_write(host, p);
|
||||
if (!esp_tee_ptr_in_ree(p)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return spi_flash_hal_supports_direct_write(tee_host, p);
|
||||
}
|
||||
|
||||
void _ss_spi_flash_hal_suspend(spi_flash_host_inst_t *host)
|
||||
{
|
||||
bool valid_addr = is_spi_host_in_ree(host);
|
||||
|
||||
if (!valid_addr) {
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
||||
spi_flash_hal_suspend(host);
|
||||
host->driver = orig;
|
||||
spi_flash_hal_suspend(tee_host);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------- SPI Flash Extras ------------------------------------------------- */
|
||||
@@ -677,38 +726,41 @@ uint32_t _ss_bootloader_flash_execute_command_common(
|
||||
|
||||
esp_err_t _ss_memspi_host_flush_cache(spi_flash_host_inst_t *host, uint32_t addr, uint32_t size)
|
||||
{
|
||||
bool valid_addr = (is_spi_host_in_ree(host) &&
|
||||
is_flash_addr_readable(addr, size));
|
||||
|
||||
if (!valid_addr) {
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
return memspi_host_flush_cache(host, addr, size);
|
||||
if (!is_flash_addr_readable(addr, size)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return memspi_host_flush_cache(tee_host, addr, size);
|
||||
}
|
||||
|
||||
esp_err_t _ss_spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip, uint32_t flags)
|
||||
{
|
||||
spi_flash_host_inst_t *host = NULL;
|
||||
bool valid_addr = (esp_tee_buf_in_ree(chip, sizeof(struct esp_flash_t)) &&
|
||||
is_spi_host_in_ree((host = chip->host)));
|
||||
|
||||
if (!valid_addr) {
|
||||
if (!esp_tee_buf_in_ree(chip, sizeof(struct esp_flash_t))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(valid_addr);
|
||||
|
||||
spi_flash_host_inst_t *const host = chip->host;
|
||||
spi_flash_hal_context_t host_snap;
|
||||
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||
if (tee_host == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
ESP_FAULT_ASSERT(tee_host != NULL);
|
||||
|
||||
esp_flash_t chip_snap = {
|
||||
.host = host,
|
||||
.host = tee_host,
|
||||
.read_mode = chip->read_mode,
|
||||
.hpm_dummy_ena = chip->hpm_dummy_ena,
|
||||
};
|
||||
|
||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
||||
esp_err_t r = spi_flash_chip_generic_config_host_io_mode(&chip_snap, flags);
|
||||
host->driver = orig;
|
||||
return r;
|
||||
return spi_flash_chip_generic_config_host_io_mode(&chip_snap, flags);
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C5
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "esp_attr.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/ext_mem_defs.h"
|
||||
@@ -42,6 +43,20 @@ FORCE_INLINE_ATTR bool esp_tee_ptr_in_ree(const void *p)
|
||||
return esp_tee_buf_in_ree(p, 4);
|
||||
}
|
||||
|
||||
/* NOTE: re-points a REE string argument at a TEE-resident copy */
|
||||
FORCE_INLINE_ATTR void tee_snapshot_ree_str(const char **name, char *buf, size_t buf_len)
|
||||
{
|
||||
const char *src = *name;
|
||||
if (src == NULL || buf_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(buf, src, buf_len);
|
||||
buf[buf_len - 1] = '\0';
|
||||
|
||||
*name = buf;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
#if SOC_ECDSA_SUPPORTED
|
||||
#include "hal/ecdsa_ll.h"
|
||||
#endif
|
||||
#if SOC_RNG_SUPPORTED
|
||||
#include "hal/rng_ll.h"
|
||||
#endif
|
||||
|
||||
#include "esp_tee.h"
|
||||
#include "esp_attr.h"
|
||||
@@ -77,4 +80,11 @@ void IRAM_ATTR esp_tee_soc_reset_crypto_peripherals(void)
|
||||
ecdsa_ll_reset_register();
|
||||
ecdsa_ll_enable_bus_clock(false);
|
||||
#endif
|
||||
|
||||
#if SOC_RNG_SUPPORTED
|
||||
rng_ll_enable();
|
||||
#if RNG_LL_NEEDS_RESET_WHEN_WAKEUP
|
||||
rng_ll_reset();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -145,6 +145,43 @@ TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp256r1)", "[sec_stora
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Test TEE Secure Storage - Signatures are non-deterministic (ecdsa_secp256r1)", "[sec_storage]")
|
||||
{
|
||||
const size_t sig_len = 2 * ECDSA_SECP256R1_KEY_LEN;
|
||||
|
||||
uint8_t msg_digest[SHA256_DIGEST_SZ];
|
||||
esp_fill_random(msg_digest, sizeof(msg_digest));
|
||||
|
||||
esp_tee_sec_storage_key_cfg_t key_cfg = {
|
||||
.id = "ecdsa_nondet",
|
||||
.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1
|
||||
};
|
||||
|
||||
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_pubkey_t pubkey = {};
|
||||
TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey));
|
||||
|
||||
uint8_t signatures[MAX_SEC_STG_ITER][2 * ECDSA_SECP256R1_KEY_LEN];
|
||||
|
||||
for (unsigned int i = 0; i < MAX_SEC_STG_ITER; i++) {
|
||||
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));
|
||||
|
||||
TEST_ESP_OK(verify_ecdsa_sign(key_cfg.type, msg_digest, sizeof(msg_digest), &pubkey, &sign));
|
||||
|
||||
for (unsigned int j = 0; j < i; j++) {
|
||||
TEST_ASSERT_TRUE_MESSAGE(memcmp(sign.signature, signatures[j], sig_len) != 0,
|
||||
"ECDSA signature repeated - deterministic signing detected");
|
||||
}
|
||||
memcpy(signatures[i], sign.signature, sig_len);
|
||||
}
|
||||
|
||||
TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id));
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN
|
||||
TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp384r1)", "[sec_storage]")
|
||||
{
|
||||
@@ -686,21 +723,6 @@ static void test_ecdsa_sign(esp_ecdsa_curve_t curve)
|
||||
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||
TEST_ASSERT_EQUAL(signature_len, 2 * key_len);
|
||||
|
||||
#if CONFIG_MBEDTLS_ECDSA_DETERMINISTIC
|
||||
uint8_t signature_det_verify[2 * ECDSA_SECP384R1_KEY_LEN];
|
||||
size_t signature_det_verify_len = 0;
|
||||
|
||||
status = psa_sign_hash(priv_key_id,
|
||||
alg,
|
||||
sha, sha_len,
|
||||
signature_det_verify, 2 * key_len,
|
||||
&signature_det_verify_len);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX32(PSA_SUCCESS, status);
|
||||
TEST_ASSERT_EQUAL(signature_det_verify_len, signature_len);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(signature, signature_det_verify, signature_len);
|
||||
#endif
|
||||
|
||||
psa_set_key_type(&pub_key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
|
||||
psa_set_key_bits(&pub_key_attr, key_len * 8);
|
||||
psa_set_key_usage_flags(&pub_key_attr, PSA_KEY_USAGE_VERIFY_HASH);
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
//For ESP32C5, RNG needs to be reset and enabled again when wakeup from sleep
|
||||
#define RNG_LL_NEEDS_RESET_WHEN_WAKEUP 1
|
||||
//Default value for the RNG timer clock divider
|
||||
#define RNG_LL_CFG_PSCALE 255
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -40,6 +42,16 @@ static inline void rng_ll_enable_sample(bool enable)
|
||||
LPPERI.rng_cfg.rng_sample_enable = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set RNG timer prescaler
|
||||
*
|
||||
* @param prescaler Timer prescaler value (0-255)
|
||||
*/
|
||||
static inline void rng_ll_set_timer_prescaler(uint8_t prescaler)
|
||||
{
|
||||
LPPERI.rng_cfg.rng_timer_pscale = prescaler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable rng xor rtc timer.
|
||||
*
|
||||
@@ -77,6 +89,7 @@ static inline void rng_ll_reset(void)
|
||||
static inline void rng_ll_enable(void)
|
||||
{
|
||||
_lp_clkrst_ll_enable_rng_clock(true);
|
||||
rng_ll_set_timer_prescaler(RNG_LL_CFG_PSCALE);
|
||||
rng_ll_enable_sample(true);
|
||||
rng_ll_enable_rtc_timer(true);
|
||||
rng_ll_enable_rng_timer(true);
|
||||
@@ -95,6 +108,16 @@ static inline void rng_ll_disable(void)
|
||||
_lp_clkrst_ll_enable_rng_clock(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check that the RNG is live: clocked and out of reset.
|
||||
*
|
||||
* @return True if the RNG is enabled and operational, false otherwise.
|
||||
*/
|
||||
static inline bool rng_ll_is_enabled(void)
|
||||
{
|
||||
return LPPERI.clk_en.rng_ck_en && !LPPERI.reset_en.lp_rng_reset_en;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/lpperi_reg.h"
|
||||
#include "soc/lpperi_struct.h"
|
||||
#include "hal/lp_clkrst_ll.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -30,6 +32,11 @@ static inline void rng_ll_disable(void)
|
||||
_lp_clkrst_ll_enable_rng_clock(false);
|
||||
}
|
||||
|
||||
static inline bool rng_ll_is_enabled(void)
|
||||
{
|
||||
return LPPERI.clk_en.rng_ck_en;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,26 +6,115 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/lpperi_reg.h"
|
||||
#include "soc/lpperi_struct.h"
|
||||
|
||||
//For ESP32C61, RNG needs to be reset and enabled again when wakeup from sleep
|
||||
#define RNG_LL_NEEDS_RESET_WHEN_WAKEUP 1
|
||||
//Default value for the RNG timer clock divider
|
||||
#define RNG_LL_CFG_PSCALE 255
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Read random data from RNG
|
||||
*
|
||||
* @return 32-bit random data
|
||||
*/
|
||||
static inline uint32_t rng_ll_read_data(void)
|
||||
{
|
||||
return REG_READ(LPPERI_RNG_DATA_SYNC_REG);
|
||||
}
|
||||
|
||||
/* For compatibility. */
|
||||
static inline void rng_ll_enable(void)
|
||||
/**
|
||||
* @brief Enable or disable RNG sampling.
|
||||
*
|
||||
* @param enable True to enable, False to disable
|
||||
*/
|
||||
static inline void rng_ll_enable_sample(bool enable)
|
||||
{
|
||||
LPPERI.rng_cfg.rng_sample_enable = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set RNG timer prescaler
|
||||
*
|
||||
* @param prescaler Timer prescaler value (0-255)
|
||||
*/
|
||||
static inline void rng_ll_set_timer_prescaler(uint8_t prescaler)
|
||||
{
|
||||
LPPERI.rng_cfg.rng_timer_pscale = prescaler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable rng xor rtc timer.
|
||||
*
|
||||
* @param enable True to enable, False to disable
|
||||
*/
|
||||
static inline void rng_ll_enable_rtc_timer(bool enable)
|
||||
{
|
||||
LPPERI.rng_cfg.rtc_timer_en = enable ? 0x3 : 0x0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable rng xor async rng timer.
|
||||
*
|
||||
* @param enable True to enable, False to disable
|
||||
*/
|
||||
static inline void rng_ll_enable_rng_timer(bool enable)
|
||||
{
|
||||
LPPERI.rng_cfg.rng_timer_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset RNG.
|
||||
*/
|
||||
static inline void rng_ll_reset(void)
|
||||
{
|
||||
LPPERI.reset_en.lp_rng_reset_en = 1;
|
||||
LPPERI.reset_en.lp_rng_reset_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable RNG module
|
||||
*
|
||||
* TODO: unify in rng_hal.c
|
||||
*/
|
||||
static inline void rng_ll_enable(void)
|
||||
{
|
||||
LPPERI.clk_en.rng_ck_en = 1;
|
||||
rng_ll_set_timer_prescaler(RNG_LL_CFG_PSCALE);
|
||||
rng_ll_enable_sample(true);
|
||||
rng_ll_enable_rtc_timer(true);
|
||||
rng_ll_enable_rng_timer(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable RNG module
|
||||
*
|
||||
* TODO: unify in rng_hal.c
|
||||
*/
|
||||
static inline void rng_ll_disable(void)
|
||||
{
|
||||
rng_ll_enable_sample(false);
|
||||
rng_ll_enable_rtc_timer(false);
|
||||
rng_ll_enable_rng_timer(false);
|
||||
LPPERI.clk_en.rng_ck_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check that the RNG is live: clocked and out of reset.
|
||||
*
|
||||
* @return True if the RNG is enabled and operational, false otherwise.
|
||||
*/
|
||||
static inline bool rng_ll_is_enabled(void)
|
||||
{
|
||||
return LPPERI.clk_en.rng_ck_en && !LPPERI.reset_en.lp_rng_reset_en;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/lpperi_reg.h"
|
||||
#include "soc/lpperi_struct.h"
|
||||
#include "hal/lp_clkrst_ll.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -30,6 +32,11 @@ static inline void rng_ll_disable(void)
|
||||
_lp_clkrst_ll_enable_rng_clock(false);
|
||||
}
|
||||
|
||||
static inline bool rng_ll_is_enabled(void)
|
||||
{
|
||||
return LPPERI_REG_GET(clk_en.rng_ck_en);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include "soc/lpperi_struct.h"
|
||||
#include "hal/lp_clkrst_ll.h"
|
||||
|
||||
//Default value for the RNG timer clock divider
|
||||
#define RNG_LL_CFG_PSCALE 255
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -38,6 +41,16 @@ static inline void rng_ll_enable_sample(bool enable)
|
||||
REG_SET_FIELD(RNG_CFG_REG, RNG_SAMPLE_ENABLE, enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set RNG timer prescaler
|
||||
*
|
||||
* @param prescaler Timer prescaler value (0-255)
|
||||
*/
|
||||
static inline void rng_ll_set_timer_prescaler(uint8_t prescaler)
|
||||
{
|
||||
REG_SET_FIELD(RNG_CFG_REG, RNG_TIMER_PSCALE, prescaler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable rng xor rtc timer.
|
||||
*
|
||||
@@ -75,6 +88,7 @@ static inline void rng_ll_reset(void)
|
||||
static inline void rng_ll_enable(void)
|
||||
{
|
||||
_lp_clkrst_ll_enable_rng_clock(true);
|
||||
rng_ll_set_timer_prescaler(RNG_LL_CFG_PSCALE);
|
||||
rng_ll_enable_sample(true);
|
||||
rng_ll_enable_rtc_timer(true);
|
||||
rng_ll_enable_rng_timer(true);
|
||||
@@ -93,6 +107,16 @@ static inline void rng_ll_disable(void)
|
||||
_lp_clkrst_ll_enable_rng_clock(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check that the RNG is live: clocked and out of reset.
|
||||
*
|
||||
* @return True if the RNG is enabled and operational, false otherwise.
|
||||
*/
|
||||
static inline bool rng_ll_is_enabled(void)
|
||||
{
|
||||
return LPPERI.clk_en.rng_ck_en && LPPERI.clk_en.rng_apb_ck_en && !LPPERI.reset_en.lp_rng_apb_reset_en;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||
#include "soc/trng_reg.h"
|
||||
#include "soc/trng_struct.h"
|
||||
|
||||
//Default value for the RNG timer clock divider
|
||||
#define RNG_LL_CFG_PSCALE 255
|
||||
|
||||
#else
|
||||
#include "soc/lp_system_reg.h"
|
||||
#endif
|
||||
@@ -121,6 +125,7 @@ static inline void rng_ll_enable(void)
|
||||
#if HAL_CONFIG(CHIP_SUPPORT_MIN_REV) >= 300
|
||||
rng_ll_enable_clock(true);
|
||||
rng_ll_reset();
|
||||
rng_ll_set_timer_prescaler(RNG_LL_CFG_PSCALE);
|
||||
rng_ll_enable_timer(true);
|
||||
rng_ll_enable_sample(true);
|
||||
#endif
|
||||
|
||||
@@ -96,6 +96,16 @@ static inline void rng_ll_disable(void)
|
||||
rng_ll_enable_bus_clock(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check that the RNG is live: clocked and out of reset.
|
||||
*
|
||||
* @return True if the RNG is enabled and operational, false otherwise.
|
||||
*/
|
||||
static inline bool rng_ll_is_enabled(void)
|
||||
{
|
||||
return LP_PERI_CLKRST.rng_ctrl.lp_rng_clk_en && !LP_PERI_CLKRST.rng_ctrl.lp_rng_rst_en;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -43,6 +43,12 @@
|
||||
#if SOC_AES_SUPPORTED
|
||||
#define ESP_AES_DRIVER_ENABLED
|
||||
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES
|
||||
#define MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING
|
||||
#define MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING
|
||||
#define MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
|
||||
#define MBEDTLS_PSA_ACCEL_ALG_CFB
|
||||
#define MBEDTLS_PSA_ACCEL_ALG_CTR
|
||||
#define MBEDTLS_PSA_ACCEL_ALG_OFB
|
||||
#endif
|
||||
#define MBEDTLS_CIPHER_MODE_XTS
|
||||
|
||||
@@ -55,12 +61,10 @@
|
||||
#endif
|
||||
#define PSA_WANT_ECC_SECP_R1_256 1
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_ECDSA_DETERMINISTIC
|
||||
#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1
|
||||
#else
|
||||
/* ECDSA signatures over TEE secure-storage keys are compulsorily
|
||||
* non-deterministic (randomized nonce) */
|
||||
#undef PSA_WANT_ALG_DETERMINISTIC_ECDSA
|
||||
#undef MBEDTLS_HMAC_DRBG_C
|
||||
#endif
|
||||
|
||||
#if SOC_SHA_SUPPORTED
|
||||
#define ESP_SHA_DRIVER_ENABLED
|
||||
@@ -119,11 +123,14 @@
|
||||
/* Disable unused cipher/algorithm types */
|
||||
#undef PSA_WANT_KEY_TYPE_ARIA
|
||||
#undef PSA_WANT_KEY_TYPE_CAMELLIA
|
||||
#undef PSA_WANT_KEY_TYPE_CHACHA20
|
||||
#undef PSA_WANT_KEY_TYPE_DES
|
||||
#undef PSA_WANT_ALG_RIPEMD160
|
||||
#undef PSA_WANT_ALG_STREAM_CIPHER
|
||||
#undef PSA_WANT_ALG_CHACHA20
|
||||
#undef PSA_WANT_ALG_CHACHA20_POLY1305
|
||||
#undef PSA_WANT_ALG_CCM
|
||||
#undef PSA_WANT_ALG_CCM_STAR_NO_TAG
|
||||
#undef PSA_WANT_ALG_CMAC
|
||||
|
||||
#define MBEDTLS_AES_ROM_TABLES
|
||||
@@ -165,6 +172,8 @@
|
||||
#undef MBEDTLS_SSL_SRV_C
|
||||
|
||||
#undef PSA_WANT_ALG_TLS12_PRF
|
||||
#undef PSA_WANT_ALG_TLS12_PSK_TO_MS
|
||||
#undef PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
|
||||
#undef PSA_WANT_ALG_PBKDF2_HMAC
|
||||
#undef PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128
|
||||
|
||||
@@ -191,8 +200,8 @@
|
||||
/* Disable self-test functions to save code size */
|
||||
#undef MBEDTLS_SELF_TEST
|
||||
|
||||
/* TEE uses EXTERNAL_RNG, no need for CTR-DRBG */
|
||||
#undef MBEDTLS_CTR_DRBG_C
|
||||
/* CTR-DRBG for strengthening the RNG operations in TEE */
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
|
||||
/* Disable PEM/Base64 — TEE uses DER format */
|
||||
#undef MBEDTLS_PEM_PARSE_C
|
||||
|
||||
@@ -75,21 +75,18 @@ int esp_ecc_point_multiply(const ecc_point_t *point, const uint8_t *scalar, ecc_
|
||||
int esp_ecc_point_verify(const ecc_point_t *point)
|
||||
{
|
||||
int result;
|
||||
const unsigned len = point->len;
|
||||
|
||||
/* point->len drives a fixed-stride MMIO write loop in the HAL; an unvalidated oversized
|
||||
* value (attacker-controlled via the TEE secure service) walks past the ECC register block
|
||||
* and can reach other peripheral registers (CWE-787). Reject non-curve lengths up front and
|
||||
* return 0 (point not verified) -- the fail-safe value for this routine. */
|
||||
if (point->len != P192_LEN && point->len != P256_LEN
|
||||
if (len != P192_LEN && len != P256_LEN
|
||||
#if SOC_ECC_SUPPORT_CURVE_P384
|
||||
&& point->len != P384_LEN
|
||||
&& len != P384_LEN
|
||||
#endif
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_ecc_acquire_hardware();
|
||||
ecc_hal_write_verify_param(point->x, point->y, point->len);
|
||||
ecc_hal_write_verify_param(point->x, point->y, len);
|
||||
ecc_hal_set_mode(ECC_MODE_VERIFY);
|
||||
ecc_hal_start_calc();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -11,6 +11,62 @@
|
||||
#include <entropy_poll.h>
|
||||
#include "psa/crypto.h"
|
||||
|
||||
#if ESP_TEE_BUILD
|
||||
#include "mbedtls/private/ctr_drbg.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_fault.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "hal/rng_ll.h"
|
||||
|
||||
#define CTR_DRBG_RESEED_INTERVAL 1024
|
||||
|
||||
static mbedtls_ctr_drbg_context s_ctr_drbg;
|
||||
|
||||
static int esp_tee_entropy_func(void *data, unsigned char *output, unsigned int len)
|
||||
{
|
||||
(void)data;
|
||||
/* Explicitly enable the RNG */
|
||||
rng_ll_enable();
|
||||
esp_fill_random(output, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void esp_tee_ctr_drbg_init(void)
|
||||
{
|
||||
static bool s_ctr_drbg_initialized = false;
|
||||
|
||||
if (!s_ctr_drbg_initialized) {
|
||||
/* Personalization data for CTR-DRBG seeding */
|
||||
struct {
|
||||
uint8_t mac[6];
|
||||
uint32_t random;
|
||||
uint32_t cycle_cnt;
|
||||
} data = {};
|
||||
|
||||
rng_ll_enable();
|
||||
data.random = esp_random();
|
||||
efuse_hal_get_mac(data.mac);
|
||||
data.cycle_cnt = esp_cpu_get_cycle_count();
|
||||
|
||||
mbedtls_ctr_drbg_init(&s_ctr_drbg);
|
||||
mbedtls_ctr_drbg_set_reseed_interval(&s_ctr_drbg, CTR_DRBG_RESEED_INTERVAL);
|
||||
|
||||
int ret = mbedtls_ctr_drbg_seed(&s_ctr_drbg, esp_tee_entropy_func, NULL,
|
||||
(const unsigned char *)&data, sizeof(data));
|
||||
mbedtls_platform_zeroize(&data, sizeof(data));
|
||||
if (ret != 0) {
|
||||
abort();
|
||||
}
|
||||
ESP_FAULT_ASSERT(ret == 0);
|
||||
|
||||
s_ctr_drbg_initialized = true;
|
||||
}
|
||||
|
||||
ESP_FAULT_ASSERT(s_ctr_drbg_initialized);
|
||||
}
|
||||
#endif // ESP_TEE_BUILD
|
||||
|
||||
int mbedtls_hardware_poll( void *data,
|
||||
unsigned char *output, size_t len, size_t *olen )
|
||||
{
|
||||
@@ -27,7 +83,18 @@ psa_status_t mbedtls_psa_external_get_random(
|
||||
if (context == NULL || output == NULL || output_length == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
#if ESP_TEE_BUILD
|
||||
esp_tee_ctr_drbg_init();
|
||||
int ret = mbedtls_ctr_drbg_random(&s_ctr_drbg, output, output_size);
|
||||
if (ret != 0) {
|
||||
return PSA_ERROR_HARDWARE_FAILURE;
|
||||
}
|
||||
ESP_FAULT_ASSERT(ret == 0);
|
||||
#else
|
||||
esp_fill_random(output, output_size);
|
||||
#endif
|
||||
|
||||
*output_length = output_size;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1003,6 +1003,10 @@ psa_status_t esp_ecdsa_opaque_sign_hash_complete(
|
||||
#if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN
|
||||
if (key_source == ESP_ECDSA_KEY_SOURCE_TEE) {
|
||||
/* TEE key path */
|
||||
if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) {
|
||||
ESP_LOGW(TAG, "Deterministic ECDSA unsupported for TEE keys; using randomized nonce");
|
||||
}
|
||||
|
||||
const char *tee_key_id = NULL;
|
||||
uint8_t stored_curve;
|
||||
|
||||
|
||||
@@ -1099,6 +1099,10 @@ config SOC_MODEM_CLOCK_IS_INDEPENDENT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_RNG_CLOCK_IS_INDEPENDENT
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_CLK_XTAL32K_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -451,6 +451,7 @@
|
||||
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
|
||||
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
|
||||
#define SOC_MODEM_CLOCK_IS_INDEPENDENT (1)
|
||||
#define SOC_RNG_CLOCK_IS_INDEPENDENT (1)
|
||||
|
||||
#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */
|
||||
#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */
|
||||
|
||||
Reference in New Issue
Block a user