feat(esp_tee): Disable the MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS option for TEE build

This commit is contained in:
Laukik Hase
2026-08-21 17:30:59 +05:30
parent 4057fcda2d
commit f8d0bae631
6 changed files with 139 additions and 73 deletions

View File

@@ -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
*/
@@ -71,6 +71,21 @@ static size_t digest_type_to_len(esp_att_part_digest_type_t digest)
}
#if ESP_TEE_BUILD
#define DIGEST_CHUNK_LEN (1024)
static psa_status_t hash_update_chunked(psa_hash_operation_t *hash_op, const void *data, uint32_t len)
{
psa_status_t status = PSA_SUCCESS;
for (uint32_t offset = 0; offset < len; offset += DIGEST_CHUNK_LEN) {
status = psa_hash_update(hash_op, (const uint8_t *)data + offset, MIN(DIGEST_CHUNK_LEN, len - offset));
if (status != PSA_SUCCESS) {
break;
}
}
return status;
}
static esp_err_t read_partition(uint32_t offset, void *buf, size_t size)
{
@@ -99,12 +114,12 @@ esp_err_t get_flash_contents_sha256(uint32_t flash_offset, uint32_t len, uint8_t
psa_hash_abort(&hash_op);
return ESP_FAIL;
}
status = psa_hash_update(&hash_op, image, mmap_len);
status = hash_update_chunked(&hash_op, image, mmap_len);
esp_tee_flash_munmap(image);
if (status != PSA_SUCCESS) {
psa_hash_abort(&hash_op);
return ESP_FAIL;
}
esp_tee_flash_munmap(image);
flash_offset += mmap_len;
len -= mmap_len;

View File

@@ -6,6 +6,7 @@
#include <string.h>
#include <stdlib.h>
#include <sys/param.h>
#include "soc/soc_caps.h"
#include "esp_log.h"
@@ -36,8 +37,8 @@
#define AES256_KEY_LEN 32
#define AES256_KEY_BITS (AES256_KEY_LEN * 8)
#define AES256_GCM_IV_LEN 12
#define AES256_GCM_TAG_LEN_MIN 12 /* NIST SP800-38D general-use minimum (96-bit tag) */
#define AES256_GCM_TAG_LEN_MAX 16 /* full GCM tag (128-bit) */
#define AES256_GCM_TAG_LEN_MIN 12 /* NIST SP800-38D general-use minimum (96-bit tag) */
#define AES256_GCM_TAG_LEN_MAX 16 /* full GCM tag (128-bit) */
#define ECDSA_SECP384R1_KEY_LEN 48
#define ECDSA_SECP256R1_KEY_LEN 32
@@ -678,6 +679,46 @@ cleanup:
return err;
}
#define AEAD_CHUNK_LEN (1024)
static psa_status_t aead_update_ad_chunked(psa_aead_operation_t *op, const uint8_t *aad, size_t aad_len)
{
psa_status_t status = PSA_SUCCESS;
for (size_t offset = 0; offset < aad_len; offset += AEAD_CHUNK_LEN) {
status = psa_aead_update_ad(op, aad + offset, MIN(AEAD_CHUNK_LEN, aad_len - offset));
if (status != PSA_SUCCESS) {
break;
}
}
return status;
}
static psa_status_t aead_update_chunked(psa_aead_operation_t *op, psa_algorithm_t alg,
const uint8_t *input, size_t len,
uint8_t *out, size_t out_size, size_t *out_len)
{
psa_status_t status = PSA_SUCCESS;
size_t total = 0;
for (size_t offset = 0; offset < len; offset += AEAD_CHUNK_LEN) {
const size_t chunk = MIN(AEAD_CHUNK_LEN, len - offset);
const size_t update_osize = PSA_AEAD_UPDATE_OUTPUT_SIZE(PSA_KEY_TYPE_AES, alg, chunk);
const size_t osize = MIN(out_size - total, update_osize);
size_t olen = 0;
status = psa_aead_update(op, input + offset, chunk, out + total, osize, &olen);
if (status != PSA_SUCCESS) {
break;
}
total += olen;
}
*out_len = total;
return status;
}
static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t *input, size_t len, const uint8_t *aad,
size_t aad_len, uint8_t *iv, size_t iv_len, uint8_t *tag, size_t tag_len,
uint8_t *output, bool is_encrypt)
@@ -700,21 +741,16 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
return ESP_ERR_INVALID_SIZE;
}
esp_err_t err = secure_storage_find_key(key_id);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Key ID not found");
return err;
}
psa_key_id_t psa_key_id = 0;
uint8_t *aead_buf = NULL;
size_t aead_buf_len = 0;
psa_aead_operation_t aead_op = PSA_AEAD_OPERATION_INIT;
uint8_t *plaintext = NULL;
sec_stg_key_t keyctx;
size_t keyctx_len = sizeof(keyctx);
err = secure_storage_read(key_id, (void *)&keyctx, &keyctx_len);
esp_err_t err = secure_storage_read(key_id, (void *)&keyctx, &keyctx_len);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to fetch key from storage");
ESP_LOGE(TAG, "%s", (err == ESP_ERR_NVS_NOT_FOUND) ?
"Key ID not found" : "Failed to fetch key from storage");
goto cleanup;
}
@@ -724,10 +760,12 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
goto cleanup;
}
const psa_algorithm_t alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len);
// Setup PSA key attributes
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len));
psa_set_key_usage_flags(&attributes, is_encrypt ? PSA_KEY_USAGE_ENCRYPT : PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, AES256_KEY_BITS);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
@@ -741,56 +779,75 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
goto cleanup;
}
/* PSA AEAD wants ciphertext+tag concatenated in a single buffer for both
* encrypt (output) and decrypt (input). */
aead_buf_len = len + tag_len;
aead_buf = malloc(aead_buf_len);
if (!aead_buf) {
err = ESP_ERR_NO_MEM;
uint8_t iv_local[AES256_GCM_IV_LEN];
uint8_t tag_local[AES256_GCM_TAG_LEN_MAX];
size_t out_len = 0, fin_len = 0, tag_out_len = tag_len;
uint8_t *out_buf = output;
if (is_encrypt) {
status = psa_aead_encrypt_setup(&aead_op, psa_key_id, alg);
if (status == PSA_SUCCESS) {
status = psa_generate_random(iv_local, iv_len);
}
} else {
memcpy(iv_local, iv, iv_len);
memcpy(tag_local, tag, tag_len);
/* NOTE: Only the AEAD-written prefix is ever copied out; zeroized at cleanup */
plaintext = malloc(len);
if (!plaintext) {
err = ESP_ERR_NO_MEM;
goto cleanup;
}
out_buf = plaintext;
status = psa_aead_decrypt_setup(&aead_op, psa_key_id, alg);
}
/* Shared spine: nonce, then AAD, then the payload in bounded chunks. */
if (status == PSA_SUCCESS) {
status = psa_aead_set_nonce(&aead_op, iv_local, iv_len);
}
if (status == PSA_SUCCESS) {
status = aead_update_ad_chunked(&aead_op, aad, aad_len);
}
if (status == PSA_SUCCESS) {
status = aead_update_chunked(&aead_op, alg, input, len, out_buf, len, &out_len);
}
if (status == PSA_SUCCESS) {
const size_t osize_fv = PSA_AEAD_FINISH_OUTPUT_SIZE(PSA_KEY_TYPE_AES, alg);
const size_t osize = MIN(len - out_len, osize_fv);
if (is_encrypt) {
status = psa_aead_finish(&aead_op, out_buf + out_len, osize, &fin_len,
tag_local, tag_len, &tag_out_len);
} else {
status = psa_aead_verify(&aead_op, out_buf + out_len, osize, &fin_len,
tag_local, tag_len);
}
}
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in %scrypting data: %d", is_encrypt ? "en" : "de", status);
err = ESP_FAIL;
goto cleanup;
}
if (is_encrypt) {
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),
iv, iv_len, aad, aad_len, input, len,
aead_buf, aead_buf_len, &output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in encrypting data: %d", status);
err = ESP_FAIL;
goto cleanup;
}
// Separate ciphertext and tag
memcpy(output, aead_buf, len);
memcpy(tag, aead_buf + len, tag_len);
memcpy(iv, iv_local, iv_len);
memcpy(tag, tag_local, tag_out_len);
} else {
memcpy(aead_buf, input, len);
memcpy(aead_buf + len, tag, tag_len);
size_t output_length = 0;
status = psa_aead_decrypt(psa_key_id, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len),
iv, iv_len, aad, aad_len, aead_buf, aead_buf_len,
output, len, &output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in decrypting data: %d", status);
err = ESP_FAIL;
goto cleanup;
}
memcpy(output, plaintext, out_len + fin_len);
}
err = ESP_OK;
cleanup:
if (aead_buf) {
mbedtls_platform_zeroize(aead_buf, aead_buf_len);
free(aead_buf);
psa_aead_abort(&aead_op);
if (plaintext) {
mbedtls_platform_zeroize(plaintext, len);
free(plaintext);
}
if (psa_key_id != 0) {
psa_destroy_key(psa_key_id);

View File

@@ -31,8 +31,7 @@ endif()
# SHA
if(CONFIG_SOC_SHA_SUPPORTED)
list(APPEND srcs "${mbedtls_test_srcs_dir}/test_sha.c"
"${mbedtls_test_srcs_dir}/test_sha_perf.c")
list(APPEND srcs "${mbedtls_test_srcs_dir}/test_sha_perf.c")
endif()
# Mixed

View File

@@ -27,7 +27,6 @@
#pragma once
#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS
#ifndef CONFIG_IDF_TARGET_LINUX
#undef MBEDTLS_PSA_BUILTIN_GET_ENTROPY
#define MBEDTLS_PSA_DRIVER_GET_ENTROPY

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,6 +9,7 @@
#include <assert.h>
#include "psa/crypto.h"
#include "mbedtls/platform_util.h"
#include "hal/sha_hal.h"
#include "hal/sha_types.h"
@@ -64,18 +65,20 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
if (alg == PSA_ALG_NONE) {
ESP_LOGE(TAG, "SHA type %d not supported", (int)sha_type);
abort();
return;
}
size_t olen;
size_t output_len = PSA_HASH_LENGTH(alg);
status = psa_hash_compute(alg, input, ilen, output, output_len, &olen);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "SHA computation failed, status %d", status);
abort();
ESP_LOGE(TAG, "SHA computation failed (status %d), output zeroed", (int)status);
mbedtls_platform_zeroize(output, output_len);
return;
}
if (olen != output_len) {
ESP_LOGE(TAG, "SHA output length mismatch, expected %u, got %u", output_len, olen);
abort();
ESP_LOGE(TAG, "SHA output length mismatch (expected %u, got %u), output zeroed", output_len, olen);
mbedtls_platform_zeroize(output, output_len);
return;
}
}

View File

@@ -112,12 +112,6 @@ TEST_CASE("Test esp_sha()", "[hw_crypto]")
#endif
}
/* NOTE: This test attempts to mmap 1MB of flash starting from address 0x00, which overlaps
* the entire TEE protected region, causing the mmap operation to fail and triggering an
* exception in the subsequent steps.
*/
#if !CONFIG_SECURE_ENABLE_TEE
TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]")
{
int r = -1;
@@ -176,4 +170,3 @@ TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]")
}
#endif
#endif // SOC_SHA_SUPPORTED && CONFIG_MBEDTLS_HARDWARE_SHA