feat(esp_tee): Use CTR-DRBG for assisting random number generation in TEE

- For ESP-TEE, fault-assert in `esp_random()` if the RNG is held in a
  freeze state
This commit is contained in:
Laukik Hase
2026-09-04 10:23:24 +05:30
parent eb0a81b89a
commit 8e34cc16cc
5 changed files with 112 additions and 9 deletions
+7 -2
View File
@@ -17,15 +17,17 @@
#if !ESP_TEE_BUILD #if !ESP_TEE_BUILD
#include "esp_private/startup_internal.h" #include "esp_private/startup_internal.h"
#else
#include "esp_fault.h"
#endif #endif
#include "hal/rtc_timer_hal.h" #include "hal/rtc_timer_hal.h"
#if SOC_RNG_CLOCK_IS_INDEPENDENT #if SOC_RNG_CLOCK_IS_INDEPENDENT
#include "hal/lp_clkrst_ll.h" #include "hal/lp_clkrst_ll.h"
#if SOC_RNG_BUF_CHAIN_ENTROPY_SOURCE || SOC_RNG_RTC_TIMER_ENTROPY_SOURCE
#include "hal/rng_ll.h"
#endif #endif
#if (SOC_RNG_CLOCK_IS_INDEPENDENT && (SOC_RNG_BUF_CHAIN_ENTROPY_SOURCE || SOC_RNG_RTC_TIMER_ENTROPY_SOURCE)) || ESP_TEE_BUILD
#include "hal/rng_ll.h"
#endif #endif
#if defined CONFIG_IDF_TARGET_ESP32S3 #if defined CONFIG_IDF_TARGET_ESP32S3
@@ -74,6 +76,9 @@ uint32_t IRAM_ATTR esp_random(void)
uint32_t result = 0; uint32_t result = 0;
for (size_t i = 0; i < sizeof(result); i++) { for (size_t i = 0; i < sizeof(result); i++) {
do { do {
#if ESP_TEE_BUILD
ESP_FAULT_ASSERT(rng_ll_is_enabled());
#endif
ccount = esp_cpu_get_cycle_count(); ccount = esp_cpu_get_cycle_count();
result ^= REG_READ(WDEV_RND_REG); result ^= REG_READ(WDEV_RND_REG);
} while (ccount - last_ccount < cpu_to_apb_freq_ratio * APB_CYCLE_WAIT_NUM); } while (ccount - last_ccount < cpu_to_apb_freq_ratio * APB_CYCLE_WAIT_NUM);
@@ -12,7 +12,6 @@
#include "esp_fault.h" #include "esp_fault.h"
#include "esp_efuse.h" #include "esp_efuse.h"
#include "esp_efuse_chip.h" #include "esp_efuse_chip.h"
#include "esp_random.h"
#include "spi_flash_mmap.h" #include "spi_flash_mmap.h"
#if SOC_HMAC_SUPPORTED #if SOC_HMAC_SUPPORTED
#include "psa_crypto_driver_esp_hmac_opaque.h" #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) 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 = {}; nvs_sec_cfg_t cfg = {};
esp_err_t err = read_security_cfg_hmac(&cfg); esp_err_t err = read_security_cfg_hmac(&cfg);
if (err != ESP_OK) { 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_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) esp_err_t esp_tee_sec_storage_gen_key(const esp_tee_sec_storage_key_cfg_t *cfg)
@@ -747,7 +753,11 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
} }
if (is_encrypt) { 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; size_t output_length = 0;
status = psa_aead_encrypt(psa_key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len), status = psa_aead_encrypt(psa_key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len),
@@ -27,6 +27,9 @@
#if SOC_ECDSA_SUPPORTED #if SOC_ECDSA_SUPPORTED
#include "hal/ecdsa_ll.h" #include "hal/ecdsa_ll.h"
#endif #endif
#if SOC_RNG_SUPPORTED
#include "hal/rng_ll.h"
#endif
#include "esp_tee.h" #include "esp_tee.h"
#include "esp_attr.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_reset_register();
ecdsa_ll_enable_bus_clock(false); ecdsa_ll_enable_bus_clock(false);
#endif #endif
#if SOC_RNG_SUPPORTED
rng_ll_enable();
#if RNG_LL_NEEDS_RESET_WHEN_WAKEUP
rng_ll_reset();
#endif
#endif
} }
@@ -43,6 +43,12 @@
#if SOC_AES_SUPPORTED #if SOC_AES_SUPPORTED
#define ESP_AES_DRIVER_ENABLED #define ESP_AES_DRIVER_ENABLED
#define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES #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 #endif
#define MBEDTLS_CIPHER_MODE_XTS #define MBEDTLS_CIPHER_MODE_XTS
@@ -120,13 +126,16 @@
/* Disable unused cipher/algorithm types */ /* Disable unused cipher/algorithm types */
#undef PSA_WANT_KEY_TYPE_ARIA #undef PSA_WANT_KEY_TYPE_ARIA
#undef PSA_WANT_KEY_TYPE_CAMELLIA #undef PSA_WANT_KEY_TYPE_CAMELLIA
#undef PSA_WANT_KEY_TYPE_CHACHA20
#undef PSA_WANT_KEY_TYPE_DES #undef PSA_WANT_KEY_TYPE_DES
#undef PSA_WANT_ALG_RIPEMD160 #undef PSA_WANT_ALG_RIPEMD160
#undef PSA_WANT_ALG_STREAM_CIPHER
#undef PSA_WANT_ALG_CHACHA20 #undef PSA_WANT_ALG_CHACHA20
#undef MBEDTLS_CHACHA20_C #undef MBEDTLS_CHACHA20_C
#undef PSA_WANT_ALG_CHACHA20_POLY1305 #undef PSA_WANT_ALG_CHACHA20_POLY1305
#undef MBEDTLS_CHACHAPOLY_C #undef MBEDTLS_CHACHAPOLY_C
#undef PSA_WANT_ALG_CCM #undef PSA_WANT_ALG_CCM
#undef PSA_WANT_ALG_CCM_STAR_NO_TAG
#undef PSA_WANT_ALG_CMAC #undef PSA_WANT_ALG_CMAC
/* Disable unused hash algorithms */ /* Disable unused hash algorithms */
@@ -168,6 +177,8 @@
#undef MBEDTLS_SSL_SRV_C #undef MBEDTLS_SSL_SRV_C
#undef PSA_WANT_ALG_TLS12_PRF #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_HMAC
#undef PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 #undef PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128
@@ -200,8 +211,8 @@
/* Disable self-test functions to save code size */ /* Disable self-test functions to save code size */
#undef MBEDTLS_SELF_TEST #undef MBEDTLS_SELF_TEST
/* TEE uses EXTERNAL_RNG, no need for CTR-DRBG */ /* CTR-DRBG for strengthening the RNG operations in TEE */
#undef MBEDTLS_CTR_DRBG_C #define MBEDTLS_CTR_DRBG_C
/* Disable PEM/Base64 — TEE uses DER format */ /* Disable PEM/Base64 — TEE uses DER format */
#undef MBEDTLS_PEM_PARSE_C #undef MBEDTLS_PEM_PARSE_C
+68 -1
View File
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -11,6 +11,62 @@
#include <entropy_poll.h> #include <entropy_poll.h>
#include "psa/crypto.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, int mbedtls_hardware_poll( void *data,
unsigned char *output, size_t len, size_t *olen ) 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) { if (context == NULL || output == NULL || output_length == NULL) {
return PSA_ERROR_INVALID_ARGUMENT; 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); esp_fill_random(output, output_size);
#endif
*output_length = output_size; *output_length = output_size;
return PSA_SUCCESS; return PSA_SUCCESS;
} }