From 68d31180f0ecbc530da91a31034ffceefd641ac8 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Mon, 2 Feb 2026 18:47:36 +0530 Subject: [PATCH] fix(esp_tee): Prevent IV reuse in the TEE secure storage AES-GCM service --- .../scripts/esp32c5/sec_srv_tbl_default.yml | 4 +- .../scripts/esp32c6/sec_srv_tbl_default.yml | 4 +- .../scripts/esp32c61/sec_srv_tbl_default.yml | 4 +- .../scripts/esp32h2/sec_srv_tbl_default.yml | 4 +- .../scripts/esp_tee_sec_stg_keygen/README.md | 7 +-- .../esp_tee_sec_stg_keygen.py | 16 +------ .../include/esp_tee_sec_storage.h | 8 +++- .../tee_sec_storage/tee_sec_storage.c | 46 ++++++------------- .../tee_sec_storage/tee_sec_storage_wrapper.c | 10 ++-- .../main/core/esp_secure_services_iram.c | 14 ++++-- .../esp_tee/test_apps/tee_cli_app/README.md | 11 +++-- .../test_apps/tee_cli_app/main/app_main.c | 2 +- .../tee_cli_app/main/tee_srv_sec_str.c | 18 ++++++-- .../test_apps/tee_cli_app/pytest_tee_cli.py | 3 +- .../esp_tee/test_apps/tee_test_fw/conftest.py | 2 +- .../tee_test_fw/main/test_esp_tee_sec_stg.c | 37 +++++++++------ .../security/tee/tee_secure_storage/README.md | 12 +++-- .../tee/tee_secure_storage/main/tee_main.c | 7 ++- 18 files changed, 105 insertions(+), 104 deletions(-) diff --git a/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml index 473b16e2c2..4ff99e0e2a 100644 --- a/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c5/sec_srv_tbl_default.yml @@ -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 diff --git a/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml index 4890d1e5e8..16fa321453 100644 --- a/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c6/sec_srv_tbl_default.yml @@ -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 diff --git a/components/esp_tee/scripts/esp32c61/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32c61/sec_srv_tbl_default.yml index f334bb360d..2f07a5812d 100644 --- a/components/esp_tee/scripts/esp32c61/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32c61/sec_srv_tbl_default.yml @@ -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: diff --git a/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml b/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml index b6a775b878..0a5321f6e2 100644 --- a/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml +++ b/components/esp_tee/scripts/esp32h2/sec_srv_tbl_default.yml @@ -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 diff --git a/components/esp_tee/scripts/esp_tee_sec_stg_keygen/README.md b/components/esp_tee/scripts/esp_tee_sec_stg_keygen/README.md index a7a040b722..3e949fab7b 100644 --- a/components/esp_tee/scripts/esp_tee_sec_stg_keygen/README.md +++ b/components/esp_tee/scripts/esp_tee_sec_stg_keygen/README.md @@ -40,16 +40,13 @@ python esp_tee_sec_stg_keygen.py -k ecdsa_p256 -o ecdsa_p256_k1.bin -i ecdsa_p25 python esp_tee_sec_stg_keygen.py -k aes256 -o aes256_gcm_k0.bin --write-once ``` -#### With custom key and IV +#### With custom key ```bash # Generate 32 bytes AES key openssl rand 32 > aes_key.bin -# Generate 12 bytes IV (optional) -openssl rand 12 >> aes_key.bin - -# Generate AES key blob using custom key + IV +# Generate AES key blob using custom key python esp_tee_sec_stg_keygen.py -k aes256 -o aes256_gcm_k1.bin -i aes_key.bin ``` diff --git a/components/esp_tee/scripts/esp_tee_sec_stg_keygen/esp_tee_sec_stg_keygen.py b/components/esp_tee/scripts/esp_tee_sec_stg_keygen/esp_tee_sec_stg_keygen.py index d6bc900576..49b3836a43 100644 --- a/components/esp_tee/scripts/esp_tee_sec_stg_keygen/esp_tee_sec_stg_keygen.py +++ b/components/esp_tee/scripts/esp_tee_sec_stg_keygen/esp_tee_sec_stg_keygen.py @@ -16,8 +16,6 @@ from cryptography.hazmat.primitives.asymmetric import ec # === Constants === SEC_STG_KEY_DATA_SZ = 256 AES_KEY_LEN = 32 -AES_DEFAULT_IV_LEN = 16 -AES_GCM_IV_LEN = 12 ECDSA_P256_LEN = 32 ECDSA_P384_LEN = 48 @@ -47,22 +45,10 @@ def generate_aes256_key(flags: Flags, key_file: str | None = None) -> bytes: raise ValueError('AES key file must be at least 32 bytes long') key = key_data[:AES_KEY_LEN] - iv_data = key_data[AES_KEY_LEN:] - - iv_len = len(iv_data) - if iv_len == 0: - iv = os.urandom(AES_DEFAULT_IV_LEN) - elif iv_len == AES_GCM_IV_LEN: - iv = iv_data + b'\x00' * (AES_DEFAULT_IV_LEN - AES_GCM_IV_LEN) - elif iv_len == AES_DEFAULT_IV_LEN: - iv = iv_data - else: - raise ValueError('IV length must be exactly 12 or 16 bytes, or omitted to generate one') else: key = os.urandom(AES_KEY_LEN) - iv = os.urandom(AES_DEFAULT_IV_LEN) - packed = struct.pack('aes256.key, AES256_KEY_LEN); - esp_fill_random(&keyctx->aes256.iv, AES256_DEFAULT_IV_LEN); return 0; } @@ -560,7 +552,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 +627,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 +673,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 +680,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 +708,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 +717,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 +734,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 +812,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 +823,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 +834,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 +842,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; diff --git a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage_wrapper.c b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage_wrapper.c index ae1fa9564c..e4b82db00a 100644 --- a/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage_wrapper.c +++ b/components/esp_tee/subproject/components/tee_sec_storage/tee_sec_storage_wrapper.c @@ -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 diff --git a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c index dc3437acac..866d40217e 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_services_iram.c +++ b/components/esp_tee/subproject/main/core/esp_secure_services_iram.c @@ -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) diff --git a/components/esp_tee/test_apps/tee_cli_app/README.md b/components/esp_tee/test_apps/tee_cli_app/README.md index bc661586bd..21e76c7d67 100644 --- a/components/esp_tee/test_apps/tee_cli_app/README.md +++ b/components/esp_tee/test_apps/tee_cli_app/README.md @@ -112,10 +112,11 @@ tee_sec_stg_encrypt <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 ``` diff --git a/components/esp_tee/test_apps/tee_cli_app/main/app_main.c b/components/esp_tee/test_apps/tee_cli_app/main/app_main.c index 678ed9c1f6..0fe39fface 100644 --- a/components/esp_tee/test_apps/tee_cli_app/main/app_main.c +++ b/components/esp_tee/test_apps/tee_cli_app/main/app_main.c @@ -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()); diff --git a/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_sec_str.c b/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_sec_str.c index f2ee33060a..727e90ce13 100644 --- a/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_sec_str.c +++ b/components/esp_tee/test_apps/tee_cli_app/main/tee_srv_sec_str.c @@ -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) @@ -347,6 +348,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]; @@ -383,7 +385,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; @@ -399,7 +401,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); @@ -430,6 +436,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; @@ -445,6 +452,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)); @@ -483,7 +494,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; @@ -510,8 +521,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", diff --git a/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py b/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py index 2bf3600386..6f1e0f9a7b 100644 --- a/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py +++ b/components/esp_tee/test_apps/tee_cli_app/pytest_tee_cli.py @@ -76,9 +76,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 diff --git a/components/esp_tee/test_apps/tee_test_fw/conftest.py b/components/esp_tee/test_apps/tee_test_fw/conftest.py index b23a21b0dd..66cdddb7d6 100644 --- a/components/esp_tee/test_apps/tee_test_fw/conftest.py +++ b/components/esp_tee/test_apps/tee_test_fw/conftest.py @@ -324,7 +324,7 @@ class TEESerial(IdfSerial): 'type': 'aes256', 'input': 'aes256_key.bin', 'write_once': False, - 'b64': 'qZxftt2T8mOpLxALIfsDqI65srqPxrJtCVnDU8wrKXbFCJekDRzXqINlU5s=', + 'b64': 'qZxftt2T8mOpLxALIfsDqI65srqPxrJtCVnDU8wrKXY=', }, {'key': 'p256_key0', 'type': 'ecdsa_p256', 'input': None, 'write_once': False}, { 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 8fd3bd847c..4d8f2dcdf7 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 @@ -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); diff --git a/examples/security/tee/tee_secure_storage/README.md b/examples/security/tee/tee_secure_storage/README.md index 579d93d69a..efda2d265f 100644 --- a/examples/security/tee/tee_secure_storage/README.md +++ b/examples/security/tee/tee_secure_storage/README.md @@ -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() ``` diff --git a/examples/security/tee/tee_secure_storage/main/tee_main.c b/examples/security/tee/tee_secure_storage/main/tee_main.c index 094643249b..aebdf0e1c2 100644 --- a/examples/security/tee/tee_secure_storage/main/tee_main.c +++ b/examples/security/tee/tee_secure_storage/main/tee_main.c @@ -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!");