fix(esp_tee): Prevent IV reuse in the TEE secure storage AES-GCM service

This commit is contained in:
Laukik Hase
2026-02-02 18:47:36 +05:30
parent 4362612554
commit 85e66d726d
15 changed files with 103 additions and 81 deletions
@@ -334,11 +334,11 @@ secure_services:
- id: 179
type: custom
function: esp_tee_sec_storage_aead_encrypt
args: 4
args: 6
- id: 180
type: custom
function: esp_tee_sec_storage_aead_decrypt
args: 4
args: 6
- id: 181
type: custom
function: esp_tee_sec_storage_ecdsa_sign_pbkdf2
@@ -274,11 +274,11 @@ secure_services:
- id: 179
type: custom
function: esp_tee_sec_storage_aead_encrypt
args: 4
args: 6
- id: 180
type: custom
function: esp_tee_sec_storage_aead_decrypt
args: 4
args: 6
- id: 181
type: custom
function: esp_tee_sec_storage_ecdsa_sign_pbkdf2
@@ -239,11 +239,11 @@ secure_services:
- id: 179
type: custom
function: esp_tee_sec_storage_aead_encrypt
args: 4
args: 6
- id: 180
type: custom
function: esp_tee_sec_storage_aead_decrypt
args: 4
args: 6
# ID: 195-199 (5) - OTA
- family: ota
entries:
@@ -278,11 +278,11 @@ secure_services:
- id: 179
type: custom
function: esp_tee_sec_storage_aead_encrypt
args: 4
args: 6
- id: 180
type: custom
function: esp_tee_sec_storage_aead_decrypt
args: 4
args: 6
- id: 181
type: custom
function: esp_tee_sec_storage_ecdsa_sign_pbkdf2
@@ -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
*/
@@ -144,25 +144,29 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg
* @brief Perform encryption using AES256-GCM with the key from secure storage
*
* @param[in] ctx Pointer to the AEAD operation context
* @param[out] iv Pointer to the output buffer for the generated initialization vector
* @param[in] iv_len Length of the initialization vector buffer
* @param[out] tag Pointer to the authentication tag buffer
* @param[in] tag_len Length of the authentication tag
* @param[out] output Pointer to the output data buffer
*
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/
esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output);
esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *iv, size_t iv_len, uint8_t *tag, size_t tag_len, uint8_t *output);
/**
* @brief Perform decryption using AES256-GCM with the key from secure storage
*
* @param[in] ctx Pointer to the AEAD operation context
* @param[in] iv Pointer to the initialization vector used during encryption
* @param[in] iv_len Length of the initialization vector
* @param[in] tag Pointer to the authentication tag buffer
* @param[in] tag_len Length of the authentication tag
* @param[out] output Pointer to the output data buffer
*
* @return esp_err_t ESP_OK on success, appropriate error code otherwise.
*/
esp_err_t 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 esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *iv, size_t iv_len, const uint8_t *tag, size_t tag_len, uint8_t *output);
/**
* @brief Generate and return the signature for the specified message digest using
@@ -388,7 +388,6 @@ static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t
size_t pub_key_buf_size = 0;
esp_err_t err = get_ecdsa_curve_info(key_type, keyctx, &priv_key_buf, &priv_key_buf_size, &pub_key_buf, &pub_key_buf_size);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to get ECDSA curve info: %d", err);
return -1;
}
psa_set_key_bits(&key_attributes, priv_key_buf_size * 8);
@@ -398,7 +397,6 @@ static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t
psa_status_t status = psa_generate_key(&key_attributes, &key_id);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to generate ECDSA key: %ld", status);
goto exit;
}
@@ -407,7 +405,6 @@ static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t
status = psa_export_key(key_id, priv_key_buf, priv_key_buf_size, &priv_key_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to export ECDSA private key: %ld", status);
goto exit;
}
@@ -421,7 +418,6 @@ static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t
status = psa_export_public_key(key_id, pub_key_with_prefix, sizeof(pub_key_with_prefix), &pub_key_len_with_prefix);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to export ECDSA public key: %ld", status);
goto exit;
}
@@ -431,7 +427,7 @@ static int generate_ecdsa_key(sec_stg_key_t *keyctx, esp_tee_sec_storage_type_t
pub_key_len = pub_key_buf_size;
} else {
/* Fallback: copy directly if format is unexpected (should not happen with PSA) */
ESP_LOGW(TAG, "Unexpected public key format, copying directly");
ESP_LOGD(TAG, "Unexpected public key format, copying directly");
size_t copy_len = (pub_key_len_with_prefix < pub_key_buf_size) ? pub_key_len_with_prefix : pub_key_buf_size;
memcpy(pub_key_buf, pub_key_with_prefix, copy_len);
pub_key_len = copy_len;
@@ -560,7 +556,6 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign(const esp_tee_sec_storage_key_cfg_t *cf
psa_status_t status = psa_import_key(&key_attributes, priv_key, priv_key_len, &key_id);
if (status != PSA_SUCCESS) {
err = ESP_ERR_INVALID_ARG;
ESP_LOGE(TAG, "Failed to import ECDSA private key: %ld", status);
goto exit;
}
@@ -636,16 +631,16 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg
}
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 *tag, size_t tag_len, uint8_t *output,
bool is_encrypt)
size_t aad_len, uint8_t *iv, size_t iv_len, uint8_t *tag, size_t tag_len,
uint8_t *output, bool is_encrypt)
{
if (key_id == NULL || input == NULL || output == NULL || tag == NULL) {
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 || tag_len == 0) {
ESP_LOGE(TAG, "Invalid input/tag length");
if (len == 0 || tag_len == 0 || iv_len == 0) {
ESP_LOGE(TAG, "Invalid input/tag/iv length");
return ESP_ERR_INVALID_SIZE;
}
@@ -682,7 +677,6 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to import AES key: %d", status);
return ESP_FAIL;
}
@@ -690,16 +684,15 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
// PSA AEAD encrypt outputs ciphertext+tag concatenated
uint8_t *output_with_tag = malloc(len + tag_len);
if (!output_with_tag) {
ESP_LOGE(TAG, "Failed to allocate memory");
psa_destroy_key(key_id_psa);
return ESP_ERR_NO_MEM;
}
esp_fill_random(iv, iv_len);
size_t output_length = 0;
status = psa_aead_encrypt(key_id_psa, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len),
keyctx.aes256.iv, AES256_GCM_IV_LEN,
aad, aad_len,
input, len,
iv, iv_len, aad, aad_len, input, len,
output_with_tag, len + tag_len, &output_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in encrypting data: %d", status);
@@ -719,7 +712,6 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
// For decryption, PSA expects ciphertext + tag concatenated
uint8_t *input_with_tag = malloc(len + tag_len);
if (!input_with_tag) {
ESP_LOGE(TAG, "Failed to allocate memory");
psa_destroy_key(key_id_psa);
return ESP_ERR_NO_MEM;
}
@@ -729,9 +721,7 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
size_t output_length = 0;
status = psa_aead_decrypt(key_id_psa, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, tag_len),
keyctx.aes256.iv, AES256_GCM_IV_LEN,
aad, aad_len,
input_with_tag, len + tag_len,
iv, iv_len, aad, aad_len, input_with_tag, len + tag_len,
output, len, &output_length);
memset(input_with_tag, 0x00, len + tag_len);
@@ -748,14 +738,14 @@ static esp_err_t tee_sec_storage_crypt_common(const char *key_id, const uint8_t
return ESP_OK;
}
esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output)
esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *iv, size_t iv_len, uint8_t *tag, size_t tag_len, uint8_t *output)
{
return tee_sec_storage_crypt_common(ctx->key_id, ctx->input, ctx->input_len, ctx->aad, ctx->aad_len, tag, tag_len, output, true);
return tee_sec_storage_crypt_common(ctx->key_id, ctx->input, ctx->input_len, ctx->aad, ctx->aad_len, iv, iv_len, tag, tag_len, output, true);
}
esp_err_t 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 esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *iv, size_t iv_len, const uint8_t *tag, size_t tag_len, uint8_t *output)
{
return tee_sec_storage_crypt_common(ctx->key_id, ctx->input, ctx->input_len, ctx->aad, ctx->aad_len, (uint8_t *)tag, tag_len, output, false);
return tee_sec_storage_crypt_common(ctx->key_id, ctx->input, ctx->input_len, ctx->aad, ctx->aad_len, (uint8_t *)iv, iv_len, (uint8_t *)tag, tag_len, output, false);
}
#if SOC_HMAC_SUPPORTED
@@ -826,7 +816,6 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2
psa_reset_key_attributes(&attributes);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to import ECC private key: %d", status);
err = ESP_FAIL;
goto exit;
}
@@ -838,7 +827,6 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2
hash, hlen,
out_sign->signature, sizeof(out_sign->signature), &signature_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to sign hash: %d", status);
memset(out_sign, 0x00, sizeof(esp_tee_sec_storage_ecdsa_sign_t));
err = ESP_FAIL;
goto exit;
@@ -850,7 +838,6 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2
size_t public_key_length = 0;
status = psa_export_public_key(psa_key_id, public_key, sizeof(public_key), &public_key_length);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Failed to export public key: %d", status);
memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t));
err = ESP_FAIL;
goto exit;
@@ -859,7 +846,6 @@ esp_err_t esp_tee_sec_storage_ecdsa_sign_pbkdf2(const esp_tee_sec_storage_pbkdf2
// PSA exports public key in uncompressed format: 0x04 || X || Y
// Skip the first byte (0x04) and copy X and Y coordinates
if (public_key_length != (1 + 2 * key_len) || public_key[0] != 0x04) {
ESP_LOGE(TAG, "Unexpected public key format");
memset(out_pubkey, 0x00, sizeof(esp_tee_sec_storage_ecdsa_pubkey_t));
err = ESP_FAIL;
goto exit;
@@ -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
*/
@@ -31,14 +31,14 @@ esp_err_t esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key_cfg
return esp_tee_service_call_with_noniram_intr_disabled(3, SS_ESP_TEE_SEC_STORAGE_ECDSA_GET_PUBKEY, cfg, out_pubkey);
}
esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output)
esp_err_t esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *iv, size_t iv_len, uint8_t *tag, size_t tag_len, uint8_t *output)
{
return esp_tee_service_call_with_noniram_intr_disabled(5, SS_ESP_TEE_SEC_STORAGE_AEAD_ENCRYPT, ctx, tag, tag_len, output);
return esp_tee_service_call_with_noniram_intr_disabled(7, SS_ESP_TEE_SEC_STORAGE_AEAD_ENCRYPT, ctx, iv, iv_len, tag, tag_len, output);
}
esp_err_t 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 esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *iv, size_t iv_len, const uint8_t *tag, size_t tag_len, uint8_t *output)
{
return esp_tee_service_call_with_noniram_intr_disabled(5, SS_ESP_TEE_SEC_STORAGE_AEAD_DECRYPT, ctx, tag, tag_len, output);
return esp_tee_service_call_with_noniram_intr_disabled(7, SS_ESP_TEE_SEC_STORAGE_AEAD_DECRYPT, ctx, iv, iv_len, tag, tag_len, output);
}
#if SOC_HMAC_SUPPORTED
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -151,13 +151,15 @@ esp_err_t _ss_esp_tee_sec_storage_ecdsa_get_pubkey(const esp_tee_sec_storage_key
return esp_tee_sec_storage_ecdsa_get_pubkey(cfg, out_pubkey);
}
esp_err_t _ss_esp_tee_sec_storage_aead_encrypt(const 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(const esp_tee_sec_storage_aead_ctx_t *ctx, uint8_t *iv, size_t iv_len, uint8_t *tag, size_t tag_len, uint8_t *output)
{
bool valid_addr = (esp_tee_ptr_in_ree((void *)ctx->input) &&
esp_tee_ptr_in_ree((void *)iv) &&
esp_tee_ptr_in_ree((void *)tag) &&
esp_tee_ptr_in_ree((void *)output));
valid_addr &= (esp_tee_ptr_in_ree((void *)(ctx->input + ctx->input_len)) &&
esp_tee_ptr_in_ree((void *)(iv + iv_len)) &&
esp_tee_ptr_in_ree((void *)(tag + tag_len)) &&
esp_tee_ptr_in_ree((void *)(output + ctx->input_len)));
@@ -170,16 +172,18 @@ esp_err_t _ss_esp_tee_sec_storage_aead_encrypt(const esp_tee_sec_storage_aead_ct
}
ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_aead_encrypt(ctx, tag, tag_len, output);
return esp_tee_sec_storage_aead_encrypt(ctx, iv, iv_len, tag, tag_len, 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)
esp_err_t _ss_esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ctx_t *ctx, const uint8_t *iv, size_t iv_len, const uint8_t *tag, size_t tag_len, uint8_t *output)
{
bool valid_addr = (esp_tee_ptr_in_ree((void *)ctx->input) &&
esp_tee_ptr_in_ree((void *)iv) &&
esp_tee_ptr_in_ree((void *)tag) &&
esp_tee_ptr_in_ree((void *)output));
valid_addr &= (esp_tee_ptr_in_ree((void *)(ctx->input + ctx->input_len)) &&
esp_tee_ptr_in_ree((void *)(iv + iv_len)) &&
esp_tee_ptr_in_ree((void *)(tag + tag_len)) &&
esp_tee_ptr_in_ree((void *)(output + ctx->input_len)));
@@ -192,7 +196,7 @@ esp_err_t _ss_esp_tee_sec_storage_aead_decrypt(const esp_tee_sec_storage_aead_ct
}
ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_aead_decrypt(ctx, tag, tag_len, output);
return esp_tee_sec_storage_aead_decrypt(ctx, iv, iv_len, 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)
@@ -112,10 +112,11 @@ tee_sec_stg_encrypt <key_id> <plaintext>
<key_id> TEE Secure storage key ID
<plaintext> Plaintext to be encrypted
tee_sec_stg_decrypt <key_id> <ciphertext> <tag>
tee_sec_stg_decrypt <key_id> <ciphertext> <iv> <tag>
Decrypt data using AES-GCM key with the given ID from secure storage
<key_id> TEE Secure storage key ID
<ciphertext> Ciphertext to be decrypted
<iv> AES-GCM initialization vector
<tag> AES-GCM authentication tag
help [<string>] [-v <0|1>]
@@ -180,10 +181,12 @@ esp32c6> tee_sec_stg_gen_key aes256_k0 0
I (2784) tee_sec_stg: Generated AES256 key with ID key0
esp32c6> tee_sec_stg_encrypt aes256_k0 b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
I (3084) tee_sec_stg: Ciphertext -
58054310a96d48c2dccdf2e34005aa63b40817723d3ec3d597ab362efea084c1
f72e44dda3b2d0a44ffc8cafd2f28b7933776dce78684c5514f9398daf3dc344
I (3294) tee_sec_stg: IV -
ef5c08c05828cf933440f121
I (3594) tee_sec_stg: Tag -
caeedb43e08dc3b4e35a58b2412908cc
esp32c6> tee_sec_stg_decrypt aes256_k0 58054310a96d48c2dccdf2e34005aa63b40817723d3ec3d597ab362efea084c1 caeedb43e08dc3b4e35a58b2412908cc
826a2e65f0e1d8aede1fb12e78957f0d
esp32c6> tee_sec_stg_decrypt aes256_k0 f72e44dda3b2d0a44ffc8cafd2f28b7933776dce78684c5514f9398daf3dc344 ef5c08c05828cf933440f121 826a2e65f0e1d8aede1fb12e78957f0d
I (4314) tee_sec_stg: Decrypted plaintext -
b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
```
@@ -33,7 +33,7 @@ static void setup_console(void)
* This can be customized, made dynamic, etc.
*/
repl_config.prompt = PROMPT_STR ">";
repl_config.max_cmdline_length = 128;
repl_config.max_cmdline_length = 256;
/* Register help command */
ESP_ERROR_CHECK(esp_console_register_help_command());
@@ -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
*/
@@ -28,6 +28,7 @@
#endif /* CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP384R1_SIGN */
#define AES256_GCM_TAG_LEN (16)
#define AES256_GCM_IV_LEN (12)
#define MAX_AES_PLAINTEXT_LEN (256)
#define ECDSA_SECP256R1_KEY_LEN (32)
@@ -348,6 +349,7 @@ static int tee_sec_stg_encrypt(int argc, char **argv)
esp_err_t err = ESP_FAIL;
uint8_t tag[AES256_GCM_TAG_LEN];
uint8_t iv[AES256_GCM_IV_LEN];
const char *key_id = (const char *)tee_sec_stg_encrypt_args.key_str_id->sval[0];
const char *plaintext = tee_sec_stg_encrypt_args.plaintext->sval[0];
@@ -384,7 +386,7 @@ static int tee_sec_stg_encrypt(int argc, char **argv)
.input_len = plaintext_buf_len
};
err = esp_tee_sec_storage_aead_encrypt(&ctx, tag, sizeof(tag), ciphertext_buf);
err = esp_tee_sec_storage_aead_encrypt(&ctx, iv, sizeof(iv), tag, sizeof(tag), ciphertext_buf);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to encrypt data: %s", esp_err_to_name(err));
goto exit;
@@ -400,7 +402,11 @@ static int tee_sec_stg_encrypt(int argc, char **argv)
char tag_hexstr[AES256_GCM_TAG_LEN * 2 + 1];
hexbuf_to_hexstr(tag, sizeof(tag), tag_hexstr, sizeof(tag_hexstr));
char iv_hexstr[AES256_GCM_IV_LEN * 2 + 1];
hexbuf_to_hexstr(iv, sizeof(iv), iv_hexstr, sizeof(iv_hexstr));
ESP_LOGI(TAG, "Ciphertext -\n%s", ciphertext);
ESP_LOGI(TAG, "IV -\n%s", iv_hexstr);
ESP_LOGI(TAG, "Tag -\n%s", tag_hexstr);
free(plaintext_buf);
@@ -431,6 +437,7 @@ void register_srv_sec_stg_encrypt(void)
static struct {
struct arg_str *key_str_id;
struct arg_str *ciphertext;
struct arg_str *iv;
struct arg_str *tag;
struct arg_end *end;
} tee_sec_stg_decrypt_args;
@@ -446,6 +453,10 @@ static int tee_sec_stg_decrypt(int argc, char **argv)
esp_err_t err = ESP_FAIL;
const char *key_id = (const char *)tee_sec_stg_decrypt_args.key_str_id->sval[0];
const char *iv_hexstr = tee_sec_stg_decrypt_args.iv->sval[0];
uint8_t iv[AES256_GCM_IV_LEN];
hexstr_to_hexbuf(iv_hexstr, strlen(iv_hexstr), iv, sizeof(iv));
const char *tag_hexstr = tee_sec_stg_decrypt_args.tag->sval[0];
uint8_t tag[AES256_GCM_TAG_LEN];
hexstr_to_hexbuf(tag_hexstr, strlen(tag_hexstr), tag, sizeof(tag));
@@ -484,7 +495,7 @@ static int tee_sec_stg_decrypt(int argc, char **argv)
.input_len = ciphertext_buf_len
};
err = esp_tee_sec_storage_aead_decrypt(&ctx, tag, sizeof(tag), plaintext_buf);
err = esp_tee_sec_storage_aead_decrypt(&ctx, iv, sizeof(iv), tag, sizeof(tag), plaintext_buf);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to decrypt data: %s", esp_err_to_name(err));
goto exit;
@@ -511,8 +522,9 @@ void register_srv_sec_stg_decrypt(void)
{
tee_sec_stg_decrypt_args.key_str_id = arg_str1(NULL, NULL, "<key_id>", "TEE Secure storage key ID");
tee_sec_stg_decrypt_args.ciphertext = arg_str1(NULL, NULL, "<ciphertext>", "Ciphertext to be decrypted");
tee_sec_stg_decrypt_args.iv = arg_str1(NULL, NULL, "<iv>", "AES-GCM initialization vector");
tee_sec_stg_decrypt_args.tag = arg_str1(NULL, NULL, "<tag>", "AES-GCM authentication tag");
tee_sec_stg_decrypt_args.end = arg_end(3);
tee_sec_stg_decrypt_args.end = arg_end(4);
const esp_console_cmd_t tee_sec_stg = {
.command = "tee_sec_stg_decrypt",
@@ -77,9 +77,10 @@ def test_tee_cli_secure_storage(dut: Dut) -> None:
dut.write(f'tee_sec_stg_encrypt {sec_stg_key_ids.get(i)} {test_msg_hash}')
test_msg_cipher = dut.expect(r'Ciphertext -\s*([0-9a-fA-F]{64})', timeout=30)[1].decode()
test_msg_iv = dut.expect(r'IV -\s*([0-9a-fA-F]{24})', timeout=30)[1].decode()
test_msg_tag = dut.expect(r'Tag -\s*([0-9a-fA-F]{32})', timeout=30)[1].decode()
dut.write(f'tee_sec_stg_decrypt {sec_stg_key_ids.get(i)} {test_msg_cipher} {test_msg_tag}')
dut.write(f'tee_sec_stg_decrypt {sec_stg_key_ids.get(i)} {test_msg_cipher} {test_msg_iv} {test_msg_tag}')
test_msg_decipher = dut.expect(r'Decrypted plaintext -\s*([0-9a-fA-F]{64})', timeout=30)[1].decode()
assert test_msg_decipher == test_msg_hash
@@ -202,6 +202,7 @@ TEST_CASE("Test TEE Secure Storage - Encrypt-decrypt (aes256_gcm)", "[sec_storag
TEST_ASSERT_NOT_NULL(decryptedtext);
uint8_t tag[12];
uint8_t iv[12];
uint8_t aad[16];
memset(aad, 0xA5, sizeof(aad));
@@ -227,11 +228,11 @@ TEST_CASE("Test TEE Secure Storage - Encrypt-decrypt (aes256_gcm)", "[sec_storag
aead_ctx.input = plaintext;
aead_ctx.input_len = SZ;
TEST_ESP_OK(esp_tee_sec_storage_aead_encrypt(&aead_ctx, tag, sizeof(tag), ciphertext));
TEST_ESP_OK(esp_tee_sec_storage_aead_encrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), ciphertext));
aead_ctx.input = ciphertext;
aead_ctx.input_len = SZ;
TEST_ESP_OK(esp_tee_sec_storage_aead_decrypt(&aead_ctx, tag, sizeof(tag), decryptedtext));
TEST_ESP_OK(esp_tee_sec_storage_aead_decrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), decryptedtext));
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
@@ -269,6 +270,7 @@ TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys",
uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(ciphertext);
uint8_t tag[12];
uint8_t iv[12];
uint8_t aad[16];
memset(aad, 0xA5, sizeof(aad));
@@ -285,7 +287,7 @@ TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys",
esp_err_t err = esp_tee_sec_storage_clear_key(key_cfg.id);
TEST_ASSERT_TRUE(err == ESP_OK || err == ESP_ERR_NOT_FOUND);
TEST_ESP_OK(esp_tee_sec_storage_gen_key(&key_cfg));
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_aead_encrypt(&aead_ctx, tag, sizeof(tag), ciphertext));
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_aead_encrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), ciphertext));
TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id));
@@ -300,7 +302,7 @@ TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys",
TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id));
// Test with non-existent data
TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, esp_tee_sec_storage_aead_encrypt(&aead_ctx, tag, sizeof(tag), ciphertext));
TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, esp_tee_sec_storage_aead_encrypt(&aead_ctx, iv, sizeof(iv), tag, sizeof(tag), ciphertext));
free(plaintext);
free(ciphertext);
@@ -309,7 +311,7 @@ TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys",
TEST_CASE("Test TEE Secure Storage - Null Pointer and Zero Length", "[sec_storage]")
{
const char *key_id = "key_id_misc";
uint8_t data[31], tag[12];
uint8_t data[31], tag[12], iv[12];
esp_tee_sec_storage_key_cfg_t key_cfg = {
.id = key_id,
@@ -326,20 +328,24 @@ TEST_CASE("Test TEE Secure Storage - Null Pointer and Zero Length", "[sec_storag
.input_len = sizeof(data),
};
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_encrypt(&aead_ctx, NULL, sizeof(tag), data));
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_encrypt(&aead_ctx, tag, 0, data));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_decrypt(&aead_ctx, NULL, sizeof(tag), data));
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_decrypt(&aead_ctx, tag, 0, data));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_encrypt(&aead_ctx, iv, sizeof(iv), NULL, sizeof(tag), data));
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_encrypt(&aead_ctx, iv, sizeof(iv), tag, 0, data));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_encrypt(&aead_ctx, NULL, sizeof(iv), tag, sizeof(tag), data));
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_encrypt(&aead_ctx, iv, 0, tag, sizeof(tag), data));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_decrypt(&aead_ctx, iv, sizeof(iv), NULL, sizeof(tag), data));
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_decrypt(&aead_ctx, iv, sizeof(iv), tag, 0, data));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_decrypt(&aead_ctx, NULL, sizeof(iv), tag, sizeof(tag), data));
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_decrypt(&aead_ctx, iv, 0, tag, sizeof(tag), data));
aead_ctx.input = NULL;
aead_ctx.input_len = sizeof(data);
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_encrypt(&aead_ctx, tag, sizeof(tag), data));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_aead_decrypt(&aead_ctx, tag, sizeof(tag), data));
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 = data;
aead_ctx.input_len = 0;
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_encrypt(&aead_ctx, tag, sizeof(tag), data));
TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_aead_decrypt(&aead_ctx, tag, sizeof(tag), data));
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));
@@ -385,6 +391,7 @@ static void test_aead_encrypt_decrypt(const char *key_id, const uint8_t *input,
TEST_ASSERT_NOT_NULL(decrypted);
uint8_t tag[12];
uint8_t iv[12];
uint8_t aad[16];
esp_fill_random(aad, sizeof(aad));
@@ -396,11 +403,11 @@ static void test_aead_encrypt_decrypt(const char *key_id, const uint8_t *input,
ctx.input = input;
ctx.input_len = len;
TEST_ESP_OK(esp_tee_sec_storage_aead_encrypt(&ctx, tag, sizeof(tag), ciphertext));
TEST_ESP_OK(esp_tee_sec_storage_aead_encrypt(&ctx, iv, sizeof(iv), tag, sizeof(tag), ciphertext));
ctx.input = ciphertext;
ctx.input_len = len;
TEST_ESP_OK(esp_tee_sec_storage_aead_decrypt(&ctx, tag, sizeof(tag), decrypted));
TEST_ESP_OK(esp_tee_sec_storage_aead_decrypt(&ctx, iv, sizeof(iv), tag, sizeof(tag), decrypted));
TEST_ASSERT_EQUAL_HEX8_ARRAY(input, decrypted, len);
@@ -95,11 +95,13 @@ I (1001) Plaintext: 4c 6f 72 65 6d 20 69 70 73 75 6d 20 64 6f 6c 6f
I (1001) Plaintext: 72 20 73 69 74 20 61 6d 65 74 2c 20 63 6f 6e 73
I (1011) Plaintext: 65 63 74 65 74 75 72 20 61 64 69 70 69 73 63 69
I (1021) Plaintext: 6e 67 20 65 6c 69 74 2e
I (1111) Encrypted data: 18 85 a2 97 7d 20 be 53 47 b7 3f 6f 52 06 8a 44
I (1111) Encrypted data: 3b 7e 2e 25 7b 33 5d 4f 2a e5 17 5e bc d7 4e 23
I (1111) Encrypted data: 2a 8f 89 a1 80 9c 6c 6b 00 e6 c6 39 7b 3f 75 65
I (1121) Encrypted data: cd d5 f6 f6 3c 9a fb bb
I (1131) Tag: 6d 7f 1f 8e 1e a9 2c d9 d2 7f 9b db 16 cc 9b 68
I (1111) Encrypted data: 5e b0 43 e9 38 a6 9c 04 85 00 be b2 d9 c7 40 08
I (1111) Encrypted data: b1 ae 64 80 2b 91 72 8a 77 d6 3c b1 d5 7f ef 00
I (1111) Encrypted data: 8d bc e0 c9 a9 9c d1 1f 33 76 34 2a da 02 a9 2f
I (1121) Encrypted data: d6 75 c1 3a 54 1b 84 ad
I (1131) IV: e8 f3 82 d8 bf 6d e5 4f 12 e0 51 57
I (1131) Tag: 30 d4 c5 a1 73 9f 6d d2 3c de 83 cb 93 01 af b9
I (1131) example_tee_sec_stg: Done with encryption/decryption!
I (1141) main_task: Returned from app_main()
```
@@ -25,6 +25,7 @@
#define SHA256_DIGEST_SZ (32)
#define ECDSA_SECP256R1_KEY_LEN (32)
#define AES256_GCM_TAG_LEN (16)
#define AES256_GCM_IV_LEN (12)
#define AES256_GCM_AAD_LEN (16)
#define SIGN_KEY_STR_ID (CONFIG_EXAMPLE_TEE_SEC_STG_SIGN_KEY_STR_ID)
@@ -165,6 +166,7 @@ static void example_tee_sec_stg_encrypt_decrypt(void *pvParameter)
}
uint8_t tag[AES256_GCM_TAG_LEN];
uint8_t iv[AES256_GCM_IV_LEN];
uint8_t aad_buf[AES256_GCM_AAD_LEN];
memset(aad_buf, 0xA5, sizeof(aad_buf));
@@ -202,7 +204,7 @@ static void example_tee_sec_stg_encrypt_decrypt(void *pvParameter)
ctx.input = (const uint8_t *)plaintext;
ctx.input_len = plaintext_len;
err = esp_tee_sec_storage_aead_encrypt(&ctx, tag, sizeof(tag), ciphertext);
err = esp_tee_sec_storage_aead_encrypt(&ctx, iv, sizeof(iv), tag, sizeof(tag), ciphertext);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to encrypt data!");
goto exit;
@@ -212,13 +214,14 @@ static void example_tee_sec_stg_encrypt_decrypt(void *pvParameter)
ctx.input = (const uint8_t *)ciphertext;
ctx.input_len = plaintext_len;
err = esp_tee_sec_storage_aead_decrypt(&ctx, tag, sizeof(tag), ciphertext);
err = esp_tee_sec_storage_aead_decrypt(&ctx, iv, sizeof(iv), tag, sizeof(tag), ciphertext);
if (err != ESP_OK || memcmp(ciphertext, plaintext, plaintext_len) != 0) {
ESP_LOGE(TAG, "Encryption verification failed!");
err = ESP_FAIL;
goto exit;
}
ESP_LOG_BUFFER_HEX("IV", iv, sizeof(iv));
ESP_LOG_BUFFER_HEX("Tag", tag, sizeof(tag));
ESP_LOGI(TAG, "Done with encryption/decryption!");