mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
feat(esp_tee): Disable the MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS option for TEE build
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -32,8 +32,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user