mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
Merge branch 'fix/tee_disallow_reentrant_sec_svc_v5.5' into 'release/v5.5'
feat(esp_tee): Backports to v5.5 See merge request espressif/esp-idf!52289
This commit is contained in:
@@ -326,11 +326,12 @@ esp_err_t esp_ds_start_sign(const void *message,
|
|||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(data->rsa_length == ESP_DS_RSA_1024
|
const uint32_t rsa_length = data->rsa_length;
|
||||||
|| data->rsa_length == ESP_DS_RSA_2048
|
if (!(rsa_length == ESP_DS_RSA_1024
|
||||||
|| data->rsa_length == ESP_DS_RSA_3072
|
|| rsa_length == ESP_DS_RSA_2048
|
||||||
|
|| rsa_length == ESP_DS_RSA_3072
|
||||||
#if SOC_RSA_MAX_BIT_LEN == 4096
|
#if SOC_RSA_MAX_BIT_LEN == 4096
|
||||||
|| data->rsa_length == ESP_DS_RSA_4096
|
|| rsa_length == ESP_DS_RSA_4096
|
||||||
#endif
|
#endif
|
||||||
)) {
|
)) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
@@ -384,7 +385,7 @@ esp_err_t esp_ds_start_sign(const void *message,
|
|||||||
return ESP_ERR_NO_MEM;
|
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_write_private_key_params(data->c);
|
||||||
ds_hal_configure_iv((uint32_t *)data->iv);
|
ds_hal_configure_iv((uint32_t *)data->iv);
|
||||||
ds_hal_write_message(message, rsa_len);
|
ds_hal_write_message(message, rsa_len);
|
||||||
@@ -409,20 +410,29 @@ 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;
|
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()) { }
|
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) {
|
if (res == DS_SIGNATURE_MD_FAIL || res == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
|
||||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||||
}
|
} else if (res == DS_SIGNATURE_PADDING_FAIL) {
|
||||||
|
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||||
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
|
} else if (res == DS_SIGNATURE_OK) {
|
||||||
return_value = ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
return_value = ESP_OK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !ESP_TEE_BUILD
|
#if !ESP_TEE_BUILD
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
.equ SAVE_REGS, 32
|
.equ SAVE_REGS, 32
|
||||||
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
|
.equ CONTEXT_SIZE, (SAVE_REGS * 4)
|
||||||
.equ MAGIC, 0x1f
|
.equ MAGIC, 0x1f
|
||||||
|
.equ NS_INT_RTN_MAGIC, (MAGIC << 12)
|
||||||
|
|
||||||
/* Macro which first allocates space on the stack to save general
|
/* Macro which first allocates space on the stack to save general
|
||||||
* purpose registers, and then save them. GP register is excluded.
|
* purpose registers, and then save them. GP register is excluded.
|
||||||
@@ -222,6 +223,24 @@
|
|||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SVC_LOCK_ACQUIRE / SVC_LOCK_RELEASE
|
||||||
|
* Hold _s_svc_lock for the duration of a secure service call, so that a call issued
|
||||||
|
* while another one is active branches to \fail instead of clobbering it.
|
||||||
|
*
|
||||||
|
* Clobbers: \tx
|
||||||
|
*/
|
||||||
|
.macro SVC_LOCK_ACQUIRE tx, fail
|
||||||
|
la \tx, _s_svc_lock
|
||||||
|
amoswap.w.aq \tx, \tx, (\tx)
|
||||||
|
bnez \tx, \fail
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro SVC_LOCK_RELEASE tx
|
||||||
|
la \tx, _s_svc_lock
|
||||||
|
amoswap.w.rl zero, zero, (\tx)
|
||||||
|
.endm
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VALIDATE_REE_SP
|
* VALIDATE_REE_SP
|
||||||
* Validate an REE-supplied sp before the TEE stores through it. The TEE region is
|
* Validate an REE-supplied sp before the TEE stores through it. The TEE region is
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ _ns_sp_max:
|
|||||||
_ns_int_rtn:
|
_ns_int_rtn:
|
||||||
.word 0
|
.word 0
|
||||||
|
|
||||||
|
.global _s_svc_lock
|
||||||
|
_s_svc_lock:
|
||||||
|
.word 0
|
||||||
|
|
||||||
.section .exception_vectors.text, "ax"
|
.section .exception_vectors.text, "ax"
|
||||||
|
|
||||||
/* Exception handler. */
|
/* Exception handler. */
|
||||||
@@ -177,6 +181,9 @@ _1:
|
|||||||
lui t0, ESP_TEE_M2U_SWITCH_MAGIC
|
lui t0, ESP_TEE_M2U_SWITCH_MAGIC
|
||||||
beq a1, t0, _skip_ctx_restore
|
beq a1, t0, _skip_ctx_restore
|
||||||
|
|
||||||
|
/* The secure service has returned - the REE may issue the next one */
|
||||||
|
SVC_LOCK_RELEASE t0
|
||||||
|
|
||||||
/* Check if we need to restore the MINTTHRESH register */
|
/* Check if we need to restore the MINTTHRESH register */
|
||||||
la t0, _s_intr_thresh
|
la t0, _s_intr_thresh
|
||||||
lw t1, 0(t0)
|
lw t1, 0(t0)
|
||||||
@@ -211,10 +218,13 @@ _skip_ctx_restore:
|
|||||||
/* U-mode ecall handler */
|
/* U-mode ecall handler */
|
||||||
_user_ecall:
|
_user_ecall:
|
||||||
/* Check whether we are returning after servicing an U-mode interrupt */
|
/* Check whether we are returning after servicing an U-mode interrupt */
|
||||||
|
li t0, NS_INT_RTN_MAGIC
|
||||||
|
bne a0, t0, _svc_call_enter
|
||||||
la t0, _ns_int_rtn
|
la t0, _ns_int_rtn
|
||||||
lw t0, 0(t0)
|
lw t0, 0(t0)
|
||||||
bnez t0, _rtn_from_ns_int
|
bnez t0, _rtn_from_ns_int
|
||||||
|
|
||||||
|
_svc_call_enter:
|
||||||
/* Reject an sp whose frame would be out-of-bounds */
|
/* Reject an sp whose frame would be out-of-bounds */
|
||||||
VALIDATE_REE_SP CONTEXT_SIZE, t0, 0
|
VALIDATE_REE_SP CONTEXT_SIZE, t0, 0
|
||||||
|
|
||||||
@@ -226,6 +236,9 @@ _user_ecall:
|
|||||||
save_general_regs
|
save_general_regs
|
||||||
save_mepc
|
save_mepc
|
||||||
|
|
||||||
|
/* Claim the TEE before touching any of its state */
|
||||||
|
SVC_LOCK_ACQUIRE t0, _svc_call_reject
|
||||||
|
|
||||||
# Check if REE is in a critical section
|
# Check if REE is in a critical section
|
||||||
csrr t0, CSR_UINTTHRESH # t0 = current UINTTHRESH
|
csrr t0, CSR_UINTTHRESH # t0 = current UINTTHRESH
|
||||||
beqz t0, _process_ecall # if threshold == 0 -> continue
|
beqz t0, _process_ecall # if threshold == 0 -> continue
|
||||||
@@ -295,6 +308,16 @@ _3:
|
|||||||
|
|
||||||
mret
|
mret
|
||||||
|
|
||||||
|
/* Discard a service call that arrived while another one was active */
|
||||||
|
_svc_call_reject:
|
||||||
|
addi sp, sp, CONTEXT_SIZE /* t0 is the only register clobbered past the context save */
|
||||||
|
csrr t0, mepc
|
||||||
|
addi t0, t0, 4 /* resume the REE after its ecall */
|
||||||
|
csrw mepc, t0
|
||||||
|
csrr t0, mscratch
|
||||||
|
li a0, -1
|
||||||
|
mret
|
||||||
|
|
||||||
.size _ecall_handler, .-_ecall_handler
|
.size _ecall_handler, .-_ecall_handler
|
||||||
|
|
||||||
/* This is the interrupt handler for the U-mode interrupts.
|
/* This is the interrupt handler for the U-mode interrupts.
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ _ns_sp_max:
|
|||||||
_ns_int_rtn:
|
_ns_int_rtn:
|
||||||
.word 0
|
.word 0
|
||||||
|
|
||||||
|
.global _s_svc_lock
|
||||||
|
_s_svc_lock:
|
||||||
|
.word 0
|
||||||
|
|
||||||
.section .exception_vectors.text, "ax"
|
.section .exception_vectors.text, "ax"
|
||||||
|
|
||||||
/* Exception handler. */
|
/* Exception handler. */
|
||||||
@@ -162,6 +166,9 @@ _machine_ecall:
|
|||||||
lui t0, ESP_TEE_M2U_SWITCH_MAGIC
|
lui t0, ESP_TEE_M2U_SWITCH_MAGIC
|
||||||
beq a1, t0, _skip_ctx_restore
|
beq a1, t0, _skip_ctx_restore
|
||||||
|
|
||||||
|
/* The secure service has returned - the REE may issue the next one */
|
||||||
|
SVC_LOCK_RELEASE t0
|
||||||
|
|
||||||
/* Check if we need to restore the MXINT threshold register */
|
/* Check if we need to restore the MXINT threshold register */
|
||||||
la t0, _s_intr_thresh
|
la t0, _s_intr_thresh
|
||||||
lw t1, 0(t0)
|
lw t1, 0(t0)
|
||||||
@@ -197,10 +204,13 @@ _skip_ctx_restore:
|
|||||||
/* U-mode ecall handler */
|
/* U-mode ecall handler */
|
||||||
_user_ecall:
|
_user_ecall:
|
||||||
/* Check whether we are returning after servicing an U-mode interrupt */
|
/* Check whether we are returning after servicing an U-mode interrupt */
|
||||||
|
li t0, NS_INT_RTN_MAGIC
|
||||||
|
bne a0, t0, _svc_call_enter
|
||||||
la t0, _ns_int_rtn
|
la t0, _ns_int_rtn
|
||||||
lw t0, 0(t0)
|
lw t0, 0(t0)
|
||||||
bnez t0, _rtn_from_ns_int
|
bnez t0, _rtn_from_ns_int
|
||||||
|
|
||||||
|
_svc_call_enter:
|
||||||
/* Reject an sp whose frame would be out-of-bounds */
|
/* Reject an sp whose frame would be out-of-bounds */
|
||||||
VALIDATE_REE_SP CONTEXT_SIZE, t0, 0
|
VALIDATE_REE_SP CONTEXT_SIZE, t0, 0
|
||||||
|
|
||||||
@@ -212,6 +222,9 @@ _user_ecall:
|
|||||||
save_general_regs
|
save_general_regs
|
||||||
save_mepc
|
save_mepc
|
||||||
|
|
||||||
|
/* Claim the TEE before touching any of its state */
|
||||||
|
SVC_LOCK_ACQUIRE t0, _svc_call_reject
|
||||||
|
|
||||||
# Check if REE is in a critical section
|
# Check if REE is in a critical section
|
||||||
li t0, PLIC_UXINT_THRESH_REG
|
li t0, PLIC_UXINT_THRESH_REG
|
||||||
lw t1, 0(t0) # t1 = current UXINT threshold
|
lw t1, 0(t0) # t1 = current UXINT threshold
|
||||||
@@ -271,6 +284,16 @@ _rtn_from_ns_int:
|
|||||||
|
|
||||||
mret
|
mret
|
||||||
|
|
||||||
|
/* Discard a service call that arrived while another one was active */
|
||||||
|
_svc_call_reject:
|
||||||
|
addi sp, sp, CONTEXT_SIZE /* t0 is the only register clobbered past the context save */
|
||||||
|
csrr t0, mepc
|
||||||
|
addi t0, t0, 4 /* resume the REE after its ecall */
|
||||||
|
csrw mepc, t0
|
||||||
|
csrr t0, mscratch
|
||||||
|
li a0, -1
|
||||||
|
mret
|
||||||
|
|
||||||
.size _ecall_handler, .-_ecall_handler
|
.size _ecall_handler, .-_ecall_handler
|
||||||
|
|
||||||
/* This is the interrupt handler for the U-mode interrupts.
|
/* This is the interrupt handler for the U-mode interrupts.
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#include "esp_crypto_periph_clk.h"
|
#include "esp_crypto_periph_clk.h"
|
||||||
#include "ecc_impl.h"
|
#include "ecc_impl.h"
|
||||||
|
|
||||||
|
#include "nvs.h"
|
||||||
|
|
||||||
#include "esp_tee.h"
|
#include "esp_tee.h"
|
||||||
#include "esp_tee_memory_utils.h"
|
#include "esp_tee_memory_utils.h"
|
||||||
#include "esp_tee_aes_intr.h"
|
#include "esp_tee_aes_intr.h"
|
||||||
@@ -54,7 +56,8 @@ int _ss_esp_aes_crypt_cbc(esp_aes_context *ctx,
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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,
|
int _ss_esp_aes_crypt_cfb128(esp_aes_context *ctx,
|
||||||
@@ -76,7 +79,8 @@ int _ss_esp_aes_crypt_cfb128(esp_aes_context *ctx,
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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,
|
int _ss_esp_aes_crypt_cfb8(esp_aes_context *ctx,
|
||||||
@@ -96,7 +100,8 @@ int _ss_esp_aes_crypt_cfb8(esp_aes_context *ctx,
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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,
|
int _ss_esp_aes_crypt_ctr(esp_aes_context *ctx,
|
||||||
@@ -119,7 +124,8 @@ int _ss_esp_aes_crypt_ctr(esp_aes_context *ctx,
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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,
|
int _ss_esp_aes_crypt_ecb(esp_aes_context *ctx,
|
||||||
@@ -136,7 +142,8 @@ int _ss_esp_aes_crypt_ecb(esp_aes_context *ctx,
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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,
|
int _ss_esp_aes_crypt_ofb(esp_aes_context *ctx,
|
||||||
@@ -157,7 +164,8 @@ int _ss_esp_aes_crypt_ofb(esp_aes_context *ctx,
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------- SHA ------------------------------------------------- */
|
/* ---------------------------------------------- SHA ------------------------------------------------- */
|
||||||
@@ -380,8 +388,10 @@ esp_err_t _ss_esp_ds_sign(const void *message,
|
|||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t n = get_ds_msg_sign_len(data->rsa_length);
|
const size_t n_max = SOC_DS_SIGNATURE_MAX_BIT_LEN / 8;
|
||||||
valid_addr &= (n > 0) && esp_tee_buf_in_ree(message, n) && esp_tee_buf_in_ree(signature, n);
|
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
|
#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);
|
valid_addr &= (key_id != (hmac_key_id_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
|
||||||
@@ -401,15 +411,21 @@ esp_err_t _ss_esp_ds_start_sign(const void *message,
|
|||||||
hmac_key_id_t key_id,
|
hmac_key_id_t key_id,
|
||||||
esp_ds_context_t **esp_ds_ctx)
|
esp_ds_context_t **esp_ds_ctx)
|
||||||
{
|
{
|
||||||
bool valid_addr = (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 *))) {
|
||||||
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)));
|
esp_tee_buf_in_ree(data, sizeof(esp_ds_data_t)));
|
||||||
if (!valid_addr) {
|
if (!valid_addr) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t n = get_ds_msg_sign_len(data->rsa_length);
|
valid_addr &= (get_ds_msg_sign_len(data->rsa_length) > 0) &&
|
||||||
valid_addr &= (n > 0) && esp_tee_buf_in_ree(message, n);
|
esp_tee_buf_in_ree(message, n_max);
|
||||||
|
|
||||||
#if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE
|
#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);
|
valid_addr &= (key_id != (hmac_key_id_t)CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID);
|
||||||
@@ -421,7 +437,12 @@ esp_err_t _ss_esp_ds_start_sign(const void *message,
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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)
|
bool _ss_esp_ds_is_busy(void)
|
||||||
@@ -431,14 +452,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)
|
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;
|
const size_t n_max = SOC_DS_SIGNATURE_MAX_BIT_LEN / 8;
|
||||||
bool valid_addr = (esp_tee_buf_in_ree(signature, max_sign) &&
|
bool valid_addr = (esp_tee_buf_in_ree(signature, n_max) &&
|
||||||
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 (!valid_addr) {
|
if (!valid_addr) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
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)) &&
|
valid_addr &= esp_tee_buf_in_ree(data, sizeof(esp_ds_data_t)) &&
|
||||||
(get_ds_msg_sign_len(data->rsa_length) > 0);
|
(get_ds_msg_sign_len(data->rsa_length) > 0);
|
||||||
|
|
||||||
@@ -447,7 +470,7 @@ esp_err_t _ss_esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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,
|
esp_err_t _ss_esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||||
@@ -536,15 +559,11 @@ int _ss_esp_tee_ota_end(void)
|
|||||||
|
|
||||||
/* ---------------------------------------------- Secure Storage ------------------------------------------------- */
|
/* ---------------------------------------------- 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)
|
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);
|
bool valid_arg = !esp_tee_sec_storage_is_key_tee_owned(key_id);
|
||||||
if (!valid_arg) {
|
if (!valid_arg) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
@@ -556,13 +575,20 @@ 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)
|
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)) &&
|
if (!esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t))) {
|
||||||
!(cfg->flags & SEC_STORAGE_FLAG_TEE_ONLY) &&
|
return ESP_ERR_INVALID_ARG;
|
||||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id);
|
}
|
||||||
|
|
||||||
|
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) {
|
if (!valid_arg) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_arg);
|
ESP_FAULT_ASSERT(valid_arg);
|
||||||
|
|
||||||
return esp_tee_sec_storage_gen_key(cfg);
|
return esp_tee_sec_storage_gen_key(&cfg_local);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
@@ -165,57 +166,70 @@ void _ss_wdt_hal_init(wdt_hal_context_t *hal, wdt_inst_t wdt_inst, uint32_t pres
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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)
|
void _ss_wdt_hal_deinit(wdt_hal_context_t *hal)
|
||||||
{
|
{
|
||||||
bool valid_addr = (esp_tee_buf_in_ree(hal, sizeof(wdt_hal_context_t)) &&
|
if (!esp_tee_buf_in_ree(hal, sizeof(wdt_hal_context_t))) {
|
||||||
is_wdt_dev_valid(hal->mwdt_dev));
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wdt_hal_context_t hal_snap = *hal;
|
||||||
|
|
||||||
|
bool valid_addr = is_wdt_dev_valid(hal_snap.mwdt_dev);
|
||||||
if (!valid_addr) {
|
if (!valid_addr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
ESP_FAULT_ASSERT(valid_addr);
|
||||||
|
|
||||||
wdt_hal_deinit(hal);
|
wdt_hal_deinit(&hal_snap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------- Secure Storage ------------------------------------------------- */
|
/* ---------------------------------------------- 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)
|
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)) &&
|
if (!esp_tee_buf_in_ree(cfg, sizeof(esp_tee_sec_storage_key_cfg_t))) {
|
||||||
esp_tee_buf_in_ree(hash, hlen) &&
|
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_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) {
|
if (!valid_arg) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_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)
|
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)) &&
|
if (!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)) &&
|
return ESP_ERR_INVALID_ARG;
|
||||||
!esp_tee_sec_storage_is_key_tee_owned(cfg->id));
|
}
|
||||||
|
|
||||||
|
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) {
|
if (!valid_arg) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_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(esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output)
|
esp_err_t _ss_esp_tee_sec_storage_aead_encrypt(esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output)
|
||||||
@@ -240,14 +254,21 @@ esp_err_t _ss_esp_tee_sec_storage_aead_encrypt(esp_tee_sec_storage_aead_ctx_t *c
|
|||||||
|
|
||||||
esp_err_t _ss_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)
|
esp_err_t _ss_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)
|
||||||
{
|
{
|
||||||
bool valid_arg = (esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t)) &&
|
if (!esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_aead_ctx_t))) {
|
||||||
esp_tee_buf_in_ree(ctx->input, ctx->input_len) &&
|
return ESP_ERR_INVALID_ARG;
|
||||||
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));
|
|
||||||
|
|
||||||
if (ctx->aad_len != 0) {
|
esp_tee_sec_storage_aead_ctx_t ctx_local = *ctx;
|
||||||
valid_arg &= esp_tee_buf_in_ree(ctx->aad, ctx->aad_len);
|
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(tag, tag_len) &&
|
||||||
|
esp_tee_buf_in_ree(output, ctx_local.input_len) &&
|
||||||
|
!esp_tee_sec_storage_is_key_tee_owned(ctx_local.key_id));
|
||||||
|
|
||||||
|
if (ctx_local.aad_len != 0) {
|
||||||
|
valid_arg &= esp_tee_buf_in_ree(ctx_local.aad, ctx_local.aad_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid_arg) {
|
if (!valid_arg) {
|
||||||
@@ -255,23 +276,28 @@ esp_err_t _ss_esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ct
|
|||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_arg);
|
ESP_FAULT_ASSERT(valid_arg);
|
||||||
|
|
||||||
return esp_tee_sec_storage_aead_decrypt(ctx, tag, tag_len, output);
|
return esp_tee_sec_storage_aead_decrypt(&ctx_local, 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)
|
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)) &&
|
if (!esp_tee_buf_in_ree(ctx, sizeof(esp_tee_sec_storage_pbkdf2_ctx_t))) {
|
||||||
esp_tee_buf_in_ree(hash, hlen) &&
|
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_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(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) {
|
if (!valid_addr) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
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 ------------------------------------------------- */
|
/* ---------------------------------------------- MMU HAL ------------------------------------------------- */
|
||||||
@@ -378,30 +404,6 @@ static bool is_flash_addr_readable(uint32_t paddr, uint32_t len)
|
|||||||
return !esp_tee_flash_check_prange_in_tee_region(paddr, 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)
|
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) {
|
if (addr_bitlen == 0) {
|
||||||
@@ -426,206 +428,246 @@ static const spi_flash_host_driver_t tee_host_driver = {
|
|||||||
.configure_host_io_mode = spi_flash_hal_configure_host_io_mode,
|
.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;
|
if (!esp_tee_buf_in_ree(host, sizeof(spi_flash_hal_context_t))) {
|
||||||
host->driver = &tee_host_driver;
|
return NULL;
|
||||||
return orig;
|
}
|
||||||
|
|
||||||
|
*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)
|
uint32_t _ss_spi_flash_hal_check_status(spi_flash_host_inst_t *host)
|
||||||
{
|
{
|
||||||
bool valid_addr = is_spi_host_in_ree(host);
|
spi_flash_hal_context_t host_snap;
|
||||||
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
if (!valid_addr) {
|
if (tee_host == NULL) {
|
||||||
return 0;
|
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)
|
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) {
|
if (!trans_valid) {
|
||||||
|
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, trans_snap.address);
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(trans_valid);
|
ESP_FAULT_ASSERT(trans_valid);
|
||||||
|
|
||||||
bool addr_ok = is_spi_cmd_addr_ok(trans->address_bitlen, trans->address, trans->mosi_len, trans->miso_len);
|
return spi_flash_hal_common_command(tee_host, &trans_snap);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t _ss_spi_flash_hal_device_config(spi_flash_host_inst_t *host)
|
esp_err_t _ss_spi_flash_hal_device_config(spi_flash_host_inst_t *host)
|
||||||
{
|
{
|
||||||
bool valid_addr = is_spi_host_in_ree(host);
|
spi_flash_hal_context_t host_snap;
|
||||||
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
if (!valid_addr) {
|
if (tee_host == NULL) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
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)
|
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) &&
|
spi_flash_hal_context_t host_snap;
|
||||||
start_address <= FLASH_ADDR_MAX_24BIT &&
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
is_flash_addr_writable(start_address, FLASH_BLOCK_SIZE));
|
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) {
|
if (!valid_addr) {
|
||||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address);
|
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
ESP_FAULT_ASSERT(valid_addr);
|
||||||
|
|
||||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
spi_flash_hal_erase_block(tee_host, start_address);
|
||||||
spi_flash_hal_erase_block(host, start_address);
|
|
||||||
host->driver = orig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ss_spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t 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) &&
|
spi_flash_hal_context_t host_snap;
|
||||||
start_address <= FLASH_ADDR_MAX_24BIT &&
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
is_flash_addr_writable(start_address, FLASH_SECTOR_SIZE));
|
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) {
|
if (!valid_addr) {
|
||||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address);
|
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, start_address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
ESP_FAULT_ASSERT(valid_addr);
|
||||||
|
|
||||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
spi_flash_hal_erase_sector(tee_host, start_address);
|
||||||
spi_flash_hal_erase_sector(host, start_address);
|
|
||||||
host->driver = orig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ss_spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length)
|
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) &&
|
spi_flash_hal_context_t host_snap;
|
||||||
address <= FLASH_ADDR_MAX_24BIT &&
|
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) &&
|
is_flash_addr_writable(address, length) &&
|
||||||
esp_tee_buf_in_ree(buffer, length));
|
esp_tee_buf_in_ree(buffer, length));
|
||||||
|
|
||||||
if (!valid_addr) {
|
if (!valid_addr) {
|
||||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
|
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
ESP_FAULT_ASSERT(valid_addr);
|
||||||
|
|
||||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
spi_flash_hal_program_page(tee_host, buffer, address, length);
|
||||||
spi_flash_hal_program_page(host, buffer, address, length);
|
|
||||||
host->driver = orig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t _ss_spi_flash_hal_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len)
|
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) &&
|
spi_flash_hal_context_t host_snap;
|
||||||
is_flash_addr_readable(address, read_len) &&
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
esp_tee_buf_in_ree(buffer, read_len));
|
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) {
|
if (!valid_addr) {
|
||||||
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
|
ESP_LOGD(TAG, "[%s] Illegal flash access at 0x%08x", __func__, address);
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
ESP_FAULT_ASSERT(valid_addr);
|
ESP_FAULT_ASSERT(valid_addr);
|
||||||
|
|
||||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
return spi_flash_hal_read(tee_host, buffer, address, read_len);
|
||||||
esp_err_t r = spi_flash_hal_read(host, buffer, address, read_len);
|
|
||||||
host->driver = orig;
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ss_spi_flash_hal_resume(spi_flash_host_inst_t *host)
|
void _ss_spi_flash_hal_resume(spi_flash_host_inst_t *host)
|
||||||
{
|
{
|
||||||
bool valid_addr = is_spi_host_in_ree(host);
|
spi_flash_hal_context_t host_snap;
|
||||||
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
if (!valid_addr) {
|
if (tee_host == NULL) {
|
||||||
return;
|
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(tee_host);
|
||||||
spi_flash_hal_resume(host);
|
|
||||||
host->driver = orig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t _ss_spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp)
|
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);
|
spi_flash_hal_context_t host_snap;
|
||||||
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
if (!valid_addr) {
|
if (tee_host == NULL) {
|
||||||
return ESP_ERR_INVALID_ARG;
|
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);
|
return spi_flash_hal_set_write_protect(tee_host, wp);
|
||||||
esp_err_t r = spi_flash_hal_set_write_protect(host, wp);
|
|
||||||
host->driver = orig;
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t _ss_spi_flash_hal_setup_read_suspend(spi_flash_host_inst_t *host, const spi_flash_sus_cmd_conf *sus_conf)
|
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) &&
|
spi_flash_hal_context_t host_snap;
|
||||||
esp_tee_buf_in_ree(sus_conf, sizeof(spi_flash_sus_cmd_conf)));
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
|
if (tee_host == NULL) {
|
||||||
if (!valid_addr) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
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 _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));
|
spi_flash_hal_context_t host_snap;
|
||||||
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
if (!valid_addr) {
|
if (tee_host == NULL) {
|
||||||
return false;
|
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 _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));
|
spi_flash_hal_context_t host_snap;
|
||||||
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
if (!valid_addr) {
|
if (tee_host == NULL) {
|
||||||
return false;
|
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)
|
void _ss_spi_flash_hal_suspend(spi_flash_host_inst_t *host)
|
||||||
{
|
{
|
||||||
bool valid_addr = is_spi_host_in_ree(host);
|
spi_flash_hal_context_t host_snap;
|
||||||
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
if (!valid_addr) {
|
if (tee_host == NULL) {
|
||||||
return;
|
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(tee_host);
|
||||||
spi_flash_hal_suspend(host);
|
|
||||||
host->driver = orig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------- SPI Flash Extras ------------------------------------------------- */
|
/* ---------------------------------------------- SPI Flash Extras ------------------------------------------------- */
|
||||||
@@ -676,38 +718,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)
|
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) &&
|
spi_flash_hal_context_t host_snap;
|
||||||
is_flash_addr_readable(addr, size));
|
spi_flash_host_inst_t *tee_host = tee_own_host(host, &host_snap);
|
||||||
|
if (tee_host == NULL) {
|
||||||
if (!valid_addr) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
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)
|
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;
|
if (!esp_tee_buf_in_ree(chip, sizeof(struct esp_flash_t))) {
|
||||||
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) {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
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 = {
|
esp_flash_t chip_snap = {
|
||||||
.host = host,
|
.host = tee_host,
|
||||||
.read_mode = chip->read_mode,
|
.read_mode = chip->read_mode,
|
||||||
.hpm_dummy_ena = chip->hpm_dummy_ena,
|
.hpm_dummy_ena = chip->hpm_dummy_ena,
|
||||||
};
|
};
|
||||||
|
|
||||||
const spi_flash_host_driver_t *orig = tee_substitute_host_driver(host);
|
return spi_flash_chip_generic_config_host_io_mode(&chip_snap, flags);
|
||||||
esp_err_t r = spi_flash_chip_generic_config_host_io_mode(&chip_snap, flags);
|
|
||||||
host->driver = orig;
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32C5
|
#if CONFIG_IDF_TARGET_ESP32C5
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "soc/ext_mem_defs.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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -34,7 +34,7 @@ static bool IRAM_ATTR test_timer_on_alarm_cb(gptimer_handle_t timer, const gptim
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_timer_init(volatile uint32_t *arg)
|
static void test_timer_init_with_cb(gptimer_alarm_cb_t on_alarm, void *arg)
|
||||||
{
|
{
|
||||||
/* Select and initialize basic parameters of the timer */
|
/* Select and initialize basic parameters of the timer */
|
||||||
gptimer_config_t timer_config = {
|
gptimer_config_t timer_config = {
|
||||||
@@ -45,9 +45,9 @@ static void test_timer_init(volatile uint32_t *arg)
|
|||||||
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
|
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
|
||||||
|
|
||||||
gptimer_event_callbacks_t cbs = {
|
gptimer_event_callbacks_t cbs = {
|
||||||
.on_alarm = test_timer_on_alarm_cb,
|
.on_alarm = on_alarm,
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, (void *)arg));
|
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, arg));
|
||||||
|
|
||||||
ESP_ERROR_CHECK(gptimer_enable(gptimer));
|
ESP_ERROR_CHECK(gptimer_enable(gptimer));
|
||||||
|
|
||||||
@@ -60,6 +60,11 @@ static void test_timer_init(volatile uint32_t *arg)
|
|||||||
ESP_ERROR_CHECK(gptimer_start(gptimer));
|
ESP_ERROR_CHECK(gptimer_start(gptimer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_timer_init(volatile uint32_t *arg)
|
||||||
|
{
|
||||||
|
test_timer_init_with_cb(test_timer_on_alarm_cb, (void *)arg);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_timer_deinit(void)
|
static void test_timer_deinit(void)
|
||||||
{
|
{
|
||||||
ESP_ERROR_CHECK(gptimer_stop(gptimer));
|
ESP_ERROR_CHECK(gptimer_stop(gptimer));
|
||||||
@@ -113,6 +118,53 @@ TEST_CASE("Test REE interrupt in TEE", "[basic]")
|
|||||||
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
|
TEST_ASSERT_MESSAGE((mode == ESP_CPU_NS_MODE), "Incorrect privilege mode!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
volatile uint32_t intr_count;
|
||||||
|
volatile uint32_t accepted_count;
|
||||||
|
} test_nested_svc_call_ctx_t;
|
||||||
|
|
||||||
|
static bool IRAM_ATTR test_nested_svc_call_cb(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
|
||||||
|
{
|
||||||
|
test_nested_svc_call_ctx_t *ctx = (test_nested_svc_call_ctx_t *)user_data;
|
||||||
|
|
||||||
|
/* Issued while the preempted service call sits parked inside the TEE */
|
||||||
|
uint32_t ret = esp_tee_service_call(3, SS_ESP_TEE_TEST_SERVICE_ADD, 200, 100);
|
||||||
|
if (ret != UINT32_MAX) {
|
||||||
|
ctx->accepted_count = ctx->accepted_count + 1;
|
||||||
|
}
|
||||||
|
ctx->intr_count = ctx->intr_count + 1;
|
||||||
|
|
||||||
|
esp_rom_printf("[mode: %d] Nested service call from ISR (%d) returned 0x%x\n",
|
||||||
|
esp_cpu_get_curr_privilege_level(), ctx->intr_count, ret);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test nested secure service call from an REE interrupt", "[basic]")
|
||||||
|
{
|
||||||
|
TEST_ASSERT_EQUAL(ESP_CPU_NS_MODE, esp_cpu_get_curr_privilege_level());
|
||||||
|
|
||||||
|
static test_nested_svc_call_ctx_t ctx;
|
||||||
|
ctx.intr_count = 0;
|
||||||
|
ctx.accepted_count = 0;
|
||||||
|
|
||||||
|
test_timer_init_with_cb(test_nested_svc_call_cb, &ctx);
|
||||||
|
|
||||||
|
/* Runs in the TEE until the ISR above has fired ESP_TEE_TEST_INTR_ITER times */
|
||||||
|
uint32_t val = esp_tee_service_call(2, SS_ESP_TEE_TEST_REE_INTR_IN_TEE, &ctx.intr_count);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(0, val);
|
||||||
|
|
||||||
|
test_timer_deinit();
|
||||||
|
|
||||||
|
/* Every call made from the ISR should have been rejected by the TEE */
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(0, ctx.accepted_count);
|
||||||
|
|
||||||
|
/* The parked call resumed and completed, so the TEE takes calls again */
|
||||||
|
val = esp_tee_service_call(3, SS_ESP_TEE_TEST_SERVICE_ADD, 200, 100);
|
||||||
|
TEST_ASSERT_EQUAL_UINT32(300, val);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_CPU_NS_MODE, esp_cpu_get_curr_privilege_level());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Test TEE interrupt in REE", "[basic]")
|
TEST_CASE("Test TEE interrupt in REE", "[basic]")
|
||||||
{
|
{
|
||||||
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
esp_cpu_priv_mode_t mode = esp_cpu_get_curr_privilege_level();
|
||||||
|
|||||||
@@ -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 esp_ecc_point_verify(const ecc_point_t *point)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
const unsigned len = point->len;
|
||||||
|
|
||||||
/* point->len drives a fixed-stride MMIO write loop in the HAL; an unvalidated oversized
|
if (len != P192_LEN && len != P256_LEN
|
||||||
* 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 SOC_ECC_SUPPORT_CURVE_P384
|
#if SOC_ECC_SUPPORT_CURVE_P384
|
||||||
&& point->len != P384_LEN
|
&& len != P384_LEN
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_ecc_acquire_hardware();
|
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_set_mode(ECC_MODE_VERIFY);
|
||||||
ecc_hal_start_calc();
|
ecc_hal_start_calc();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user