From c7f74fd7512ff4d02c95eed7ac62979ba07c712e Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Fri, 28 Aug 2026 13:51:47 +0530 Subject: [PATCH] change(esp_tee): Limit the TEE secure storage AEAD operation input buffer length --- .../tee_sec_storage/include/esp_tee_sec_storage.h | 12 +++++++++--- .../components/tee_sec_storage/tee_sec_storage.c | 13 +++++++------ .../tee_test_fw/main/test_esp_tee_sec_stg.c | 4 ++++ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h b/components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h index 61d6ea9a3f3..bb76be87462 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h +++ b/components/esp_tee/subproject/components/tee_sec_storage/include/esp_tee_sec_storage.h @@ -19,11 +19,13 @@ extern "C" { #include "sdkconfig.h" #if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN -#define MAX_ECDSA_SUPPORTED_KEY_LEN 48 /*!< Maximum supported size for the ECDSA key (SECP384R1) */ +#define MAX_ECDSA_SUPPORTED_KEY_LEN 48 /*!< Maximum supported size for the ECDSA key (SECP384R1) */ #else -#define MAX_ECDSA_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the ECDSA key (SECP256R1) */ +#define MAX_ECDSA_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the ECDSA key (SECP256R1) */ #endif /* CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN */ -#define MAX_AES_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the AES key */ +#define MAX_AES_SUPPORTED_KEY_LEN 32 /*!< Maximum supported size for the AES key */ + +#define MAX_AEAD_INPUT_LEN 4096 /*!< Maximum input length per AEAD operation */ #define SEC_STORAGE_FLAG_NONE 0 /*!< No flags */ #define SEC_STORAGE_FLAG_WRITE_ONCE BIT(0) /*!< Data can only be written once */ @@ -169,6 +171,8 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg * @param[out] output Pointer to the output data buffer * * @note Non-standard @p iv_len / @p tag_len values are rejected with ESP_ERR_INVALID_SIZE. + * @note The input length must not exceed ::MAX_AEAD_INPUT_LEN bytes; + * larger inputs are rejected with ESP_ERR_INVALID_SIZE. * * @return esp_err_t ESP_OK on success, appropriate error code otherwise. */ @@ -185,6 +189,8 @@ esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t * @param[out] output Pointer to the output data buffer * * @note Non-standard @p iv_len / @p tag_len values are rejected with ESP_ERR_INVALID_SIZE. + * @note The input length must not exceed ::MAX_AEAD_INPUT_LEN bytes; + * larger inputs are rejected with ESP_ERR_INVALID_SIZE. * * @return esp_err_t ESP_OK on success, appropriate error code otherwise. */ diff --git a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c index ed06175f282..dfdc04f4159 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c +++ b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage.c @@ -704,6 +704,7 @@ static psa_status_t aead_update_chunked(psa_aead_operation_t *op, psa_algorithm_ for (size_t offset = 0; offset < len; offset += AEAD_CHUNK_LEN) { const size_t chunk = MIN(AEAD_CHUNK_LEN, len - offset); + /* NOTE: tight osize keeps PSA's internal output copy chunk-sized (it allocates the declared size) */ 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; @@ -724,20 +725,19 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t uint8_t *output, bool is_encrypt) { if (key_id == NULL || input == NULL || output == NULL || tag == NULL || iv == NULL) { - ESP_LOGE(TAG, "Invalid arguments"); return ESP_ERR_INVALID_ARG; } - if (len == 0) { - ESP_LOGE(TAG, "Invalid input length"); + /* NOTE: Cap applies to both directions so encryption never produces a blob decryption cannot stage */ + if (len == 0 || len > MAX_AEAD_INPUT_LEN) { + ESP_LOGE(TAG, "Invalid input length (max %u)", (unsigned)MAX_AEAD_INPUT_LEN); return ESP_ERR_INVALID_SIZE; } /* Enforce standard AES-GCM parameters */ if (iv_len != AES256_GCM_IV_LEN || tag_len < AES256_GCM_TAG_LEN_MIN || tag_len > AES256_GCM_TAG_LEN_MAX) { - ESP_LOGE(TAG, "Non-standard GCM iv_len(%u)/tag_len(%u) rejected", - (unsigned)iv_len, (unsigned)tag_len); + ESP_LOGE(TAG, "Non-standard GCM iv_len/tag_len rejected"); return ESP_ERR_INVALID_SIZE; } @@ -795,7 +795,7 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t 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 */ + /* NOTE: TEE-resident staging - no plaintext reaches the REE until the tag verifies */ plaintext = malloc(len); if (!plaintext) { err = ESP_ERR_NO_MEM; @@ -833,6 +833,7 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t err = ESP_FAIL; goto cleanup; } + ESP_FAULT_ASSERT(status == PSA_SUCCESS); if (is_encrypt) { memcpy(iv, iv_local, iv_len); diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c index b4a0820e635..247c4c3bcec 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_sec_stg.c @@ -385,6 +385,10 @@ TEST_CASE("Test TEE Secure Storage - Null Pointer and Zero Length", "[sec_storag TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_encrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), data)); TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_decrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), data)); + aead_ctx.input_len = MAX_AEAD_INPUT_LEN + 1; + TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_encrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), data)); + TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_decrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), data)); + TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_id)); key_cfg.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1;