mirror of
https://github.com/espressif/esp-idf.git
synced 2026-09-22 13:01:16 +03:00
change(esp_tee): Limit the TEE secure storage AEAD operation input buffer length
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user