From 3bb3f9362e4b7b0c138f0eb0900f25847ee921e8 Mon Sep 17 00:00:00 2001 From: Laukik Hase Date: Fri, 28 Mar 2025 16:44:05 +0530 Subject: [PATCH] refactor(esp_tee): Update TEE secure storage examples and test-apps --- .../scripts/esp_tee_sec_stg_keygen/README.md | 95 +++++ .../esp_tee_sec_stg_keygen.py | 156 +++++++ .../esp_tee/test_apps/tee_cli_app/README.md | 60 +-- .../test_apps/tee_cli_app/main/app_main.c | 1 + .../tee_cli_app/main/tee_srv_sec_str.c | 103 +++-- .../test_apps/tee_cli_app/pytest_tee_cli.py | 28 +- .../tee_cli_app/sdkconfig.ci.minimal_tee | 2 +- .../test_apps/tee_cli_app/sdkconfig.ci.sb_fe | 2 +- .../test_sec_srv/src/test_sec_srv.c | 2 +- .../esp_tee/test_apps/tee_test_fw/conftest.py | 175 +++++++- .../tee_test_fw/main/test_esp_tee_att.c | 16 +- .../main/test_esp_tee_flash_prot.c | 10 +- .../tee_test_fw/main/test_esp_tee_panic.c | 2 +- .../tee_test_fw/main/test_esp_tee_sec_stg.c | 395 ++++++++++++------ .../test_apps/tee_test_fw/partitions.csv | 7 - .../tee_test_fw/partitions_tee_ota.csv | 2 +- .../tee_test_fw/pytest_esp_tee_ut.py | 13 +- .../tee_test_fw/sdkconfig.ci.default | 5 + .../test_apps/tee_test_fw/sdkconfig.defaults | 6 +- .../tee_secure_storage/main/Kconfig.projbuild | 9 +- .../tee/tee_secure_storage/main/tee_main.c | 57 ++- 21 files changed, 839 insertions(+), 307 deletions(-) create mode 100644 components/esp_tee/scripts/esp_tee_sec_stg_keygen/README.md create mode 100644 components/esp_tee/scripts/esp_tee_sec_stg_keygen/esp_tee_sec_stg_keygen.py delete mode 100644 components/esp_tee/test_apps/tee_test_fw/partitions.csv 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 new file mode 100644 index 0000000000..59ea02d58a --- /dev/null +++ b/components/esp_tee/scripts/esp_tee_sec_stg_keygen/README.md @@ -0,0 +1,95 @@ +# TEE Secure Storage: Image Generation + + +## A. Generate Secure Key Blobs + +### `esp_tee_sec_stg_keygen` tool + +``` +$ python esp_tee_sec_stg_keygen.py --help +usage: esp_tee_sec_stg_keygen.py [-h] -k {aes256,ecdsa_p256,ecdsa_p192} -o OUTPUT [-i INPUT] [--write-once] + +Generate or import a cryptographic key structure for secure storage + +options: + -h, --help show this help message and exit + -k, --key-type {aes256,ecdsa_p256,ecdsa_p192} + key type to be processed + -o, --output OUTPUT output binary file name + -i, --input INPUT input key file (.pem for ecdsa, .bin for aes) + --write-once make key persistent - cannot be modified or deleted once written +``` + +### ECDSA Keys + +```bash +python esp_tee_sec_stg_keygen.py -k ecdsa_p256 -o ecdsa_p256_k0.bin +python esp_tee_sec_stg_keygen.py -k ecdsa_p192 -o ecdsa_p192_k0.bin +``` + +#### With custom PEM: + +```bash +openssl ecparam -name prime256v1 -genkey -noout -out ecdsa_p256.pem +python esp_tee_sec_stg_keygen.py -k ecdsa_p256 -o ecdsa_p256_k1.bin -i ecdsa_p256.pem --write-once +``` + +### AES-256 Key + +```bash +python esp_tee_sec_stg_keygen.py -k aes256 -o aes256_gcm_k0.bin --write-once +``` + +#### With custom key and IV + +```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 +python esp_tee_sec_stg_keygen.py -k aes256 -o aes256_gcm_k1.bin -i aes_key.bin +``` + +## B. NVS Partition Image Generation + +### Create the TEE Secure Storage CSV + +Prepare a CSV file that defines the data to be used as input for the NVS Partition Generator utility. + +```csv +key,type,encoding,value +tee_sec_stg_ns,namespace,, +aes256_key0,file,binary,aes256_gcm_k0.bin +p256_key0,file,binary,ecdsa_p256_k0.bin +p192_key0,file,binary,ecdsa_p192_k0.bin +attest_key0,file,binary,ecdsa_p256_k1.bin +``` +> [!IMPORTANT] +> As per the current implementation, all data objects in the TEE Secure Storage are to be stored in the `tee_sec_stg_ns` namespace. + +### Generate NVS Encryption Keys + +```bash +python nvs_partition_gen.py generate-key --key_protect_hmac --kp_hmac_inputkey hmac_key.bin --keyfile nvs_keys.bin +``` + +> [!IMPORTANT] +> `hmac_key.bin` must match the HMAC key programmed into the eFuse block specified by `CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID`. + +### Generate encrypted NVS partition + +```bash +python nvs_partition_gen.py encrypt tee_sec_stg_val.csv tee_sec_stg_nvs.bin 0x8000 --inputkey nvs_keys.bin +``` + +> [!NOTE] +> Replace `0x8000` with the actual size of the TEE Secure Storage partition as configured in your project's partition table. + +## (Optional) Decrypt for Verification + +```bash +python nvs_partition_gen.py decrypt tee_sec_stg_nvs.bin nvs_keys.bin tee_sec_stg_nvs_decr.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 new file mode 100644 index 0000000000..6a70113d32 --- /dev/null +++ b/components/esp_tee/scripts/esp_tee_sec_stg_keygen/esp_tee_sec_stg_keygen.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import os +import struct +from enum import Enum +from enum import IntFlag +from typing import Any +from typing import Optional + +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import serialization +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_P192_LEN = 24 + + +# === Key Type Enum === +class KeyType(Enum): + AES256 = 0 + ECDSA_P256 = 1 + ECDSA_P192 = 2 + + +# === Bitwise Flags Enum === +class Flags(IntFlag): + NONE = 0x00000000 + WRITE_ONCE = 0x00000001 + + +# === Key Generators === + + +def generate_aes256_key(flags: Flags, key_file: Optional[str] = None) -> bytes: + if key_file: + with open(key_file, 'rb') as f: + key_data = f.read() + + if len(key_data) < AES_KEY_LEN: + 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(' bytes: + if pem_file: + with open(pem_file, 'rb') as f: + private_key = serialization.load_pem_private_key(f.read(), password=None, backend=default_backend()) + if not isinstance(private_key, ec.EllipticCurvePrivateKey): + raise ValueError('Provided PEM does not contain an EC private key') + else: + private_key = ec.generate_private_key(curve, default_backend()) + + priv = private_key.private_numbers().private_value.to_bytes(key_len, 'big') + pub = private_key.public_key().public_numbers() + x = pub.x.to_bytes(key_len, 'big') + y = pub.y.to_bytes(key_len, 'big') + + packed = struct.pack(f' bytes: + if key_type == KeyType.AES256: + return generate_aes256_key(flags, input_file) + elif key_type == KeyType.ECDSA_P256: + return generate_ecdsa_key(ec.SECP256R1(), key_type, ECDSA_P256_LEN, flags, input_file) + elif key_type == KeyType.ECDSA_P192: + return generate_ecdsa_key(ec.SECP192R1(), key_type, ECDSA_P192_LEN, flags, input_file) + else: + raise ValueError(f'Unsupported key type: {key_type}') + + +# === CLI === + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description='Generate or import a cryptographic key structure for secure storage') + parser.add_argument( + '-k', + '--key-type', + type=str, + choices=[e.name.lower() for e in KeyType], + required=True, + help='key type to be processed', + ) + parser.add_argument( + '-o', + '--output', + required=True, + help='output binary file name', + ) + parser.add_argument( + '-i', + '--input', + help='input key file (.pem for ecdsa, .bin for aes)', + ) + parser.add_argument( + '--write-once', + action='store_true', + help='make key persistent - cannot be modified or deleted once written', + ) + return parser.parse_args() + + +def main() -> None: + args: Any = parse_args() + + key_type = KeyType[args.key_type.upper()] + flags = Flags.NONE + if args.write_once: + flags |= Flags.WRITE_ONCE + + print(f'[+] Generating key of type: {key_type.name} (value: {key_type.value})') + if args.input: + print(f'[+] Using user-provided key file: {args.input}') + if args.write_once: + print('[+] WRITE_ONCE flag is set') + + key_data = generate_key_data(key_type, flags, args.input) + + with open(args.output, 'wb') as f: + f.write(key_data) + + print(f'[✓] Key written to {args.output}') + + +if __name__ == '__main__': + main() 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 b57c21af35..2d1060e077 100644 --- a/components/esp_tee/test_apps/tee_cli_app/README.md +++ b/components/esp_tee/test_apps/tee_cli_app/README.md @@ -78,31 +78,33 @@ get_msg_sha256 "" Get the SHA256 digest for the given message "" Message for SHA256 digest calculation -tee_sec_stg_gen_key - Generate and store a new key of the specified type in the given TEE secure - storage slot - TEE Secure storage slot for storing the key - Key type (0: ECDSA_SECP256R1, 1: AES256) +tee_sec_stg_gen_key + Generate and store a new key of the specified type with the given ID + TEE Secure storage key ID + Key type (0: AES256, 1: ECDSA_SECP256R1) -tee_sec_stg_sign - Sign a message using the ECDSA keypair stored in the given slot ID and verify - the signature - TEE Secure storage slot storing the ecdsa-secp256r1 keypair +tee_sec_stg_sign + Sign a message using the ECDSA keypair stored with the given key ID and + verify the signature + TEE Secure storage key ID SHA256 digest of the message to be signed and verified -tee_sec_stg_encrypt - Encrypt data using AES-GCM with a key from secure storage - <slot_id> TEE Secure storage slot storing the AES key +tee_sec_stg_encrypt <key_id> <plaintext> + Encrypt data using AES-GCM key with the given ID from secure storage + <key_id> TEE Secure storage key ID <plaintext> Plaintext to be encrypted -tee_sec_stg_decrypt <slot_id> <ciphertext> <tag> - Decrypt data using AES-GCM with a key from secure storage - <slot_id> TEE Secure storage slot storing the AES key +tee_sec_stg_decrypt <key_id> <ciphertext> <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 <tag> AES-GCM authentication tag -help - Print the list of registered commands +help [<string>] [-v <0|1>] + Print the summary of all registered commands if no arguments are given, + otherwise print summary of given command. + <string> Name of command + -v, --verbose=<0|1> If specified, list console commands with given verbose level ``` ## Secure Services @@ -110,7 +112,7 @@ help ### Attestation - The `tee_att_info` command provided by the attestation service generates and dumps an Entity Attestation Token (EAT) signed by the TEE. -- The token is signed using the ECDSA key (`secp256r1` curve) stored in the configured slot ID of the TEE Secure Storage. +- The token is signed using the ECDSA key (`secp256r1` curve) stored in the TEE Secure Storage with the configured key ID. <details> <summary><b>Sample output:</b> <i>tee_att_info</i></summary> @@ -128,22 +130,22 @@ I (8180) tee_attest: Attestation token - Data: ### Secure Storage - The TEE secure storage service provides the following commands: - - `tee_sec_stg_gen_key`: Generate and store a new key (ECDSA or AES) in a specified TEE secure storage slot - - `tee_sec_stg_sign`: Sign a message using an ECDSA `secp256r1` key pair stored in a specified slot and verify the signature - - `tee_sec_stg_encrypt`: Encrypt data with AES256-GCM using the key from the specified slot and outputs the ciphertext and tag - - `tee_sec_stg_decrypt`: Decrypt ciphertext using key from the specified slot and tag for integrity verification + - `tee_sec_stg_gen_key`: Generate and store a new key (ECDSA or AES) in the TEE secure storage with the specified ID + - `tee_sec_stg_sign`: Sign a message using an ECDSA `secp256r1` key pair with the specified ID and verify the signature + - `tee_sec_stg_encrypt`: Encrypt data with AES256-GCM using the key with the specified ID and outputs the ciphertext and tag + - `tee_sec_stg_decrypt`: Decrypt ciphertext using key with the specified ID and tag for integrity verification - The `get_msg_sha256` command computes the SHA256 hash of a given message, which can be used as input for the `tee_sec_stg_sign` command. <details> <summary><b>Sample output:</b> <i>tee_sec_stg_gen_key + get_msg_sha256 + tee_sec_stg_sign</i></summary> ```log -esp32c6> tee_sec_stg_gen_key 7 0 -I (2964) tee_sec_stg: Generated ECDSA_SECP256R1 key in slot 7 +esp32c6> tee_sec_stg_gen_key ecdsa_p256_k0 1 +I (2964) tee_sec_stg: Generated ECDSA_SECP256R1 key with ID ecdsa_p256_k0 esp32c6> get_msg_sha256 "hello world" I (3984) tee_sec_stg: Message digest (SHA256) - b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 -esp32c6> tee_sec_stg_sign 7 b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 +esp32c6> tee_sec_stg_sign ecdsa_p256_k0 b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 I (5384) tee_sec_stg: Generated signature - 944684f6ddcf4c268ac6b65e34ccb8d95bd2849567a87867101bc1f09208f0885d935d7b3ba9d46014f28e4c7c988d68c775431fcb2cb2d4ca5c6862db771088 I (6404) tee_sec_stg: Public key (Uncompressed) - @@ -157,14 +159,14 @@ I (6444) tee_sec_stg: Signature verified successfully! <summary><b>Sample output:</b> <i>tee_sec_stg_gen_key + tee_sec_stg_encrypt + tee_sec_stg_decrypt</i></summary> ```log -esp32c6> tee_sec_stg_gen_key 8 1 -I (2784) tee_sec_stg: Generated AES256 key in slot 8 -esp32c6> tee_sec_stg_encrypt 8 b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 +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 I (3594) tee_sec_stg: Tag - caeedb43e08dc3b4e35a58b2412908cc -esp32c6> tee_sec_stg_decrypt 8 58054310a96d48c2dccdf2e34005aa63b40817723d3ec3d597ab362efea084c1 caeedb43e08dc3b4e35a58b2412908cc +esp32c6> tee_sec_stg_decrypt aes256_k0 58054310a96d48c2dccdf2e34005aa63b40817723d3ec3d597ab362efea084c1 caeedb43e08dc3b4e35a58b2412908cc 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 ea4f6c4473..678ed9c1f6 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 @@ -18,6 +18,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "esp_tee_sec_storage.h" #include "example_tee_srv.h" #define PROMPT_STR CONFIG_IDF_TARGET 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 82f60f9ea6..6d81b8f2ef 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 @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -79,7 +79,7 @@ static esp_err_t hexbuf_to_hexstr(const void *hexbuf, size_t hexbuf_sz, char *he return ESP_OK; } -static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_pubkey_t *pubkey, const esp_tee_sec_storage_sign_t *sign) +static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_ecdsa_pubkey_t *pubkey, const esp_tee_sec_storage_ecdsa_sign_t *sign) { if (pubkey == NULL || digest == NULL || sign == NULL) { return ESP_ERR_INVALID_ARG; @@ -197,7 +197,7 @@ void register_cmd_msg_sha256(void) } static struct { - struct arg_int *slot_id; + struct arg_str *key_str_id; struct arg_int *key_type; struct arg_end *end; } tee_sec_stg_gen_key_args; @@ -211,29 +211,27 @@ static int tee_sec_stg_gen_key(int argc, char **argv) } esp_err_t err = ESP_FAIL; - uint16_t slot_id = (uint16_t)tee_sec_stg_gen_key_args.slot_id->ival[0]; - esp_tee_sec_storage_type_t key_type = (esp_tee_sec_storage_type_t)tee_sec_stg_gen_key_args.key_type->ival[0]; - err = esp_tee_sec_storage_init(); - if (err != ESP_OK) { + esp_tee_sec_storage_key_cfg_t cfg = { + .id = (const char *)tee_sec_stg_gen_key_args.key_str_id->sval[0], + .type = (esp_tee_sec_storage_type_t)tee_sec_stg_gen_key_args.key_type->ival[0] + }; + + err = esp_tee_sec_storage_clear_key(cfg.id); + if (err != ESP_OK && err != ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to clear key %d!", cfg.id); goto exit; } - err = esp_tee_sec_storage_clear_slot(slot_id); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to clear slot %d!", slot_id); - goto exit; - } - - err = esp_tee_sec_storage_gen_key(slot_id, key_type); + err = esp_tee_sec_storage_gen_key(&cfg); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to generate key!"); goto exit; } - ESP_LOGI(TAG, "Generated %s key in slot %d", - (key_type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) ? "ECDSA_SECP256R1" : "AES256", - slot_id); + ESP_LOGI(TAG, "Generated %s key with ID %s", + (cfg.type == ESP_SEC_STG_KEY_ECDSA_SECP256R1) ? "ECDSA_SECP256R1" : "AES256", + cfg.id); exit: return err; @@ -241,13 +239,13 @@ exit: void register_srv_sec_stg_gen_key(void) { - tee_sec_stg_gen_key_args.slot_id = arg_int1(NULL, NULL, "<slot_id>", "TEE Secure storage slot for storing the key"); - tee_sec_stg_gen_key_args.key_type = arg_int1(NULL, NULL, "<key_type>", "Key type (0: ECDSA_SECP256R1, 1: AES256)"); + tee_sec_stg_gen_key_args.key_str_id = arg_str1(NULL, NULL, "<key_id>", "TEE Secure storage key ID"); + tee_sec_stg_gen_key_args.key_type = arg_int1(NULL, NULL, "<key_type>", "Key type (0: AES256, 1: ECDSA_SECP256R1)"); tee_sec_stg_gen_key_args.end = arg_end(2); const esp_console_cmd_t tee_sec_stg = { .command = "tee_sec_stg_gen_key", - .help = "Generate and store a new key of the specified type in the given TEE secure storage slot", + .help = "Generate and store a new key of the specified type with the given ID", .hint = NULL, .func = &tee_sec_stg_gen_key, .argtable = &tee_sec_stg_gen_key_args, @@ -257,7 +255,7 @@ void register_srv_sec_stg_gen_key(void) } static struct { - struct arg_int *slot_id; + struct arg_str *key_str_id; struct arg_str *msg_sha256; struct arg_end *end; } tee_sec_stg_sign_args; @@ -280,16 +278,13 @@ static int tee_sec_stg_sign(int argc, char **argv) uint8_t digest[SHA256_DIGEST_SZ] = {}; hexstr_to_hexbuf(msg_sha256, msg_sha256_len, digest, sizeof(digest)); - esp_err_t err = ESP_FAIL; - uint16_t slot_id = (uint16_t)tee_sec_stg_sign_args.slot_id->ival[0]; + esp_tee_sec_storage_key_cfg_t cfg = { + .id = (const char *)tee_sec_stg_sign_args.key_str_id->sval[0], + .type = ESP_SEC_STG_KEY_ECDSA_SECP256R1 + }; - err = esp_tee_sec_storage_init(); - if (err != ESP_OK) { - goto exit; - } - - esp_tee_sec_storage_sign_t sign = {}; - err = esp_tee_sec_storage_get_signature(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, digest, sizeof(digest), &sign); + esp_tee_sec_storage_ecdsa_sign_t sign = {}; + esp_err_t err = esp_tee_sec_storage_ecdsa_sign(&cfg, digest, sizeof(digest), &sign); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to generate signature!"); goto exit; @@ -306,8 +301,8 @@ static int tee_sec_stg_sign(int argc, char **argv) ESP_LOGI(TAG, "Generated signature -\n%s", sign_hexstr); free(sign_hexstr); - esp_tee_sec_storage_pubkey_t pubkey = {}; - err = esp_tee_sec_storage_get_pubkey(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, &pubkey); + esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {}; + err = esp_tee_sec_storage_ecdsa_get_pubkey(&cfg, &pubkey); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to fetch public-key!"); goto exit; @@ -338,13 +333,13 @@ exit: void register_srv_sec_stg_sign(void) { - tee_sec_stg_sign_args.slot_id = arg_int1(NULL, NULL, "<slot_id>", "TEE Secure storage slot storing the ecdsa-secp256r1 keypair"); + tee_sec_stg_sign_args.key_str_id = arg_str1(NULL, NULL, "<key_id>", "TEE Secure storage key ID"); tee_sec_stg_sign_args.msg_sha256 = arg_str1(NULL, NULL, "<msg_sha256>", "SHA256 digest of the message to be signed and verified"); tee_sec_stg_sign_args.end = arg_end(2); const esp_console_cmd_t tee_sec_stg = { .command = "tee_sec_stg_sign", - .help = "Sign a message using the ECDSA keypair stored in the given slot ID and verify the signature", + .help = "Sign a message using the ECDSA keypair stored with the given key ID and verify the signature", .hint = NULL, .func = &tee_sec_stg_sign, .argtable = &tee_sec_stg_sign_args, @@ -354,7 +349,7 @@ void register_srv_sec_stg_sign(void) } static struct { - struct arg_int *slot_id; + struct arg_str *key_str_id; struct arg_str *plaintext; struct arg_end *end; } tee_sec_stg_encrypt_args; @@ -369,7 +364,7 @@ static int tee_sec_stg_encrypt(int argc, char **argv) esp_err_t err = ESP_FAIL; uint8_t tag[AES256_GCM_TAG_LEN]; - uint16_t slot_id = (uint16_t)tee_sec_stg_encrypt_args.slot_id->ival[0]; + 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]; size_t plaintext_len = strnlen(plaintext, MAX_AES_PLAINTEXT_LEN); @@ -399,13 +394,13 @@ static int tee_sec_stg_encrypt(int argc, char **argv) goto exit; } - err = esp_tee_sec_storage_init(); - if (err != ESP_OK) { - goto exit; - } + esp_tee_sec_storage_aead_ctx_t ctx = { + .key_id = key_id, + .input = (uint8_t *)plaintext_buf, + .input_len = plaintext_buf_len + }; - err = esp_tee_sec_storage_encrypt(slot_id, (uint8_t *)plaintext_buf, plaintext_buf_len, - NULL, 0, tag, sizeof(tag), ciphertext_buf); + err = esp_tee_sec_storage_aead_encrypt(&ctx, tag, sizeof(tag), ciphertext_buf); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to encrypt data: %s", esp_err_to_name(err)); goto exit; @@ -434,13 +429,13 @@ exit: void register_srv_sec_stg_encrypt(void) { - tee_sec_stg_encrypt_args.slot_id = arg_int1(NULL, NULL, "<slot_id>", "TEE Secure storage slot storing the AES key"); + tee_sec_stg_encrypt_args.key_str_id = arg_str1(NULL, NULL, "<key_id>", "TEE Secure storage key ID"); tee_sec_stg_encrypt_args.plaintext = arg_str1(NULL, NULL, "<plaintext>", "Plaintext to be encrypted"); tee_sec_stg_encrypt_args.end = arg_end(2); const esp_console_cmd_t tee_sec_stg = { .command = "tee_sec_stg_encrypt", - .help = "Encrypt data using AES-GCM with a key from secure storage", + .help = "Encrypt data using AES-GCM key with the given ID from secure storage", .hint = NULL, .func = &tee_sec_stg_encrypt, .argtable = &tee_sec_stg_encrypt_args, @@ -450,7 +445,7 @@ void register_srv_sec_stg_encrypt(void) } static struct { - struct arg_int *slot_id; + struct arg_str *key_str_id; struct arg_str *ciphertext; struct arg_str *tag; struct arg_end *end; @@ -465,7 +460,7 @@ static int tee_sec_stg_decrypt(int argc, char **argv) } esp_err_t err = ESP_FAIL; - uint16_t slot_id = (uint16_t)tee_sec_stg_decrypt_args.slot_id->ival[0]; + const char *key_id = (const char *)tee_sec_stg_decrypt_args.key_str_id->sval[0]; const char *tag_hexstr = tee_sec_stg_decrypt_args.tag->sval[0]; uint8_t tag[AES256_GCM_TAG_LEN]; @@ -499,13 +494,13 @@ static int tee_sec_stg_decrypt(int argc, char **argv) goto exit; } - err = esp_tee_sec_storage_init(); - if (err != ESP_OK) { - goto exit; - } + esp_tee_sec_storage_aead_ctx_t ctx = { + .key_id = key_id, + .input = (uint8_t *)ciphertext_buf, + .input_len = ciphertext_buf_len + }; - err = esp_tee_sec_storage_decrypt(slot_id, ciphertext_buf, ciphertext_buf_len, - NULL, 0, tag, sizeof(tag), plaintext_buf); + err = esp_tee_sec_storage_aead_decrypt(&ctx, tag, sizeof(tag), plaintext_buf); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to decrypt data: %s", esp_err_to_name(err)); goto exit; @@ -530,14 +525,14 @@ exit: void register_srv_sec_stg_decrypt(void) { - tee_sec_stg_decrypt_args.slot_id = arg_int1(NULL, NULL, "<slot_id>", "TEE Secure storage slot storing the AES key"); + 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.tag = arg_str1(NULL, NULL, "<tag>", "AES-GCM authentication tag"); tee_sec_stg_decrypt_args.end = arg_end(3); const esp_console_cmd_t tee_sec_stg = { .command = "tee_sec_stg_decrypt", - .help = "Decrypt data using AES-GCM with a key from secure storage", + .help = "Decrypt data using AES-GCM key with the given ID from secure storage", .hint = NULL, .func = &tee_sec_stg_decrypt, .argtable = &tee_sec_stg_decrypt_args, 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 35ebd12a42..587c297c13 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 @@ -53,13 +53,14 @@ def test_tee_cli_secure_storage(dut: Dut) -> None: time.sleep(1) # Test out the TEE secure storage workflow - Message signing and verification - iterations = 3 - sec_stg_slots = {0: 0, 1: 14, 2: 7} - for i in range(iterations): - dut.write(f'tee_sec_stg_gen_key {sec_stg_slots.get(i)} 0') - dut.expect(r'Generated ECDSA_SECP256R1 key in slot (\d+)', timeout=30) + sec_stg_key_ids = {0: 'key0', 1: 'key1', 2: 'key2'} + iterations = len(sec_stg_key_ids) - dut.write(f'tee_sec_stg_sign {sec_stg_slots.get(i)} {test_msg_hash}') + for i in range(iterations): + dut.write(f'tee_sec_stg_gen_key {sec_stg_key_ids.get(i)} 1') + dut.expect(r'Generated ECDSA_SECP256R1 key with ID (\S+)', timeout=30) + + dut.write(f'tee_sec_stg_sign {sec_stg_key_ids.get(i)} {test_msg_hash}') test_msg_sign = dut.expect(r'Generated signature -\s*([0-9a-fA-F]{128})', timeout=30)[1].decode() test_msg_pubkey = dut.expect(r'Public key \(Uncompressed\) -\s*([0-9a-fA-F]{130})', timeout=30)[1].decode() dut.expect('Signature verified successfully', timeout=30) @@ -69,16 +70,15 @@ def test_tee_cli_secure_storage(dut: Dut) -> None: time.sleep(1) # Test out the TEE secure storage workflow - Encryption and decryption - sec_stg_slots = {0: 1, 1: 14, 2: 9} for i in range(iterations): - dut.write(f'tee_sec_stg_gen_key {sec_stg_slots.get(i)} 1') - dut.expect(r'Generated AES256 key in slot (\d+)', timeout=30) + dut.write(f'tee_sec_stg_gen_key {sec_stg_key_ids.get(i)} 0') + dut.expect(r'Generated AES256 key with ID (\S+)', timeout=30) - dut.write(f'tee_sec_stg_encrypt {sec_stg_slots.get(i)} {test_msg_hash}') + 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_tag = dut.expect(r'Tag -\s*([0-9a-fA-F]{32})', timeout=30)[1].decode() - dut.write(f'tee_sec_stg_decrypt {sec_stg_slots.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_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 @@ -133,9 +133,9 @@ def test_tee_cli_attestation(dut: Dut) -> None: dut.expect('ESP-TEE: Secure services demonstration', timeout=30) time.sleep(1) - att_key_slot = dut.app.sdkconfig.get('SECURE_TEE_ATT_KEY_SLOT_ID') - dut.write(f'tee_sec_stg_gen_key {att_key_slot} 0') - dut.expect(r'Generated ECDSA_SECP256R1 key in slot (\d+)', timeout=30) + att_key_id = dut.app.sdkconfig.get('SECURE_TEE_ATT_KEY_STR_ID') + dut.write(f'tee_sec_stg_gen_key {att_key_id} 1') + dut.expect(r'Generated ECDSA_SECP256R1 key with ID (\S+)', timeout=30) # Get the Entity Attestation token from TEE and verify its signature dut.write('tee_att_info') diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.minimal_tee b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.minimal_tee index aec152b4a6..c26a4dbadb 100644 --- a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.minimal_tee +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.minimal_tee @@ -1,6 +1,6 @@ # Minimal TEE configuration CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y -CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK=9 +CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID=5 # Reducing TEE DRAM and STACK sizes # 21KB diff --git a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe index 7ae1369488..b1d65ee809 100644 --- a/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe +++ b/components/esp_tee/test_apps/tee_cli_app/sdkconfig.ci.sb_fe @@ -12,4 +12,4 @@ CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE=y # TEE Secure Storage: Release mode CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE=y -CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK=9 +CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID=5 diff --git a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c index 4fc14500cf..e90aef0119 100644 --- a/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c +++ b/components/esp_tee/test_apps/tee_test_fw/components/test_sec_srv/src/test_sec_srv.c @@ -42,7 +42,7 @@ uint32_t _ss_add_in_loop(uint32_t a, uint32_t b, uint32_t iter) for (int i = 0; i < iter; i++) { a += b; esp_rom_delay_us(1000000); - ESP_LOGD(TAG, "[mode: %d] val: %d", esp_cpu_get_curr_privilege_level(), a); + esp_rom_printf("[mode: %d] val: %d\n", esp_cpu_get_curr_privilege_level(), a); } return a; } 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 67055572ee..bf076ee6d6 100644 --- a/components/esp_tee/test_apps/tee_test_fw/conftest.py +++ b/components/esp_tee/test_apps/tee_test_fw/conftest.py @@ -1,9 +1,17 @@ -# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 # pylint: disable=W0621 # redefined-outer-name +import base64 +import csv import os +import shutil +import subprocess +import sys import tempfile +from pathlib import Path from typing import Any +from typing import Dict +from typing import List import espsecure import esptool @@ -13,6 +21,7 @@ from _pytest.monkeypatch import MonkeyPatch from pytest_embedded_idf.serial import IdfSerial from pytest_embedded_serial_esp.serial import EspSerial +# fmt: off esp_tee_empty_bin = { 'esp32c6': [ 0xE9, 0x04, 0x02, 0x10, 0x00, 0x00, 0x80, 0x40, 0xEE, 0x00, 0x00, 0x00, @@ -56,6 +65,7 @@ esp_tee_empty_bin = { 0xFC, 0x74, 0xB2, 0xB9, 0x34, 0x72, 0xC3, 0x00 ] } +# fmt: on # This is a custom IdfSerial class to support custom functionality @@ -70,10 +80,12 @@ class TEESerial(IdfSerial): @EspSerial.use_esptool() def bootloader_force_flash_if_req(self) -> None: # Forcefully flash the bootloader only if security features are enabled - if any(( - self.app.sdkconfig.get('SECURE_BOOT', True), - self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED', True), - )): + if any( + ( + self.app.sdkconfig.get('SECURE_BOOT', True), + self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED', True), + ) + ): offs = int(self.app.sdkconfig.get('BOOTLOADER_OFFSET_IN_FLASH', 0)) bootloader_path = os.path.join(self.app.binary_path, 'bootloader', 'bootloader.bin') encrypt = '--encrypt' if self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED') else '' @@ -81,7 +93,7 @@ class TEESerial(IdfSerial): esptool.main( f'--no-stub write_flash {offs} {bootloader_path} --force {encrypt} --flash_size {flash_size}'.split(), - esp=self.esp + esp=self.esp, ) @EspSerial.use_esptool() @@ -97,20 +109,30 @@ class TEESerial(IdfSerial): temp_file.flush() esptool.main( - f'--no-stub write_flash {offs} {temp_file.name} --flash_size {flash_size}'.split(), - esp=self.esp + f'--no-stub write_flash {offs} {temp_file.name} --flash_size {flash_size}'.split(), esp=self.esp ) else: self.erase_partition(partition) @EspSerial.use_esptool() - def copy_test_tee_img(self, partition: str, is_rollback: bool = False) -> None: + def custom_write_partition(self, partition: str, bin_path: str, encrypt: bool = False) -> None: offs = self.app.partition_table[partition]['offset'] no_stub = '--no-stub' if self.app.sdkconfig.get('SECURE_ENABLE_SECURE_ROM_DL_MODE') else '' - encrypt = '--encrypt' if self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED') else '' flash_size = self._get_flash_size() + flash_file = bin_path + args = f'{no_stub} write_flash {offs} {flash_file}'.split() + + if encrypt: + args.append('--encrypt') + args += f'--flash_size {flash_size}'.split() + + esptool.main(args, esp=self.esp) + + @EspSerial.use_esptool() + def copy_test_tee_img(self, partition: str, is_rollback: bool = False) -> None: flash_file = os.path.join(self.app.binary_path, 'esp_tee', 'esp_tee.bin') + encrypt = self.app.sdkconfig.get('SECURE_FLASH_ENC_ENABLED', False) if is_rollback: datafile = 'esp_tee_empty.bin' @@ -125,22 +147,27 @@ class TEESerial(IdfSerial): if self.app.sdkconfig.get('SECURE_BOOT'): keyfile = self.app.sdkconfig.get('SECURE_BOOT_SIGNING_KEY') - # Signing the image with espsecure espsecure.main( - f'sign_data --version 2 --append_signatures --keyfile {keyfile} --output {datafile_signed} {datafile}'.split() + [ + 'sign_data', + '--version', + '2', + '--append_signatures', + '--keyfile', + keyfile, + '--output', + datafile_signed, + datafile, + ] ) flash_file = datafile_signed - esptool.main( - f'{no_stub} write_flash {offs} {flash_file} {encrypt} --flash_size {flash_size}'.split(), - esp=self.esp - ) + self.custom_write_partition(partition, flash_file, encrypt=encrypt) if is_rollback: - if os.path.exists(datafile): - os.remove(datafile) - if os.path.exists(datafile_signed): - os.remove(datafile_signed) + for file in [datafile, datafile_signed]: + if os.path.exists(file): + os.remove(file) @EspSerial.use_esptool() def custom_flash(self) -> None: @@ -165,6 +192,114 @@ class TEESerial(IdfSerial): self.flash() self.custom_erase_partition('secure_storage') + KEY_DEFS: List[Dict[str, Any]] = [ + {'key': 'aes256_key0', 'type': 'aes256', 'input': None, 'write_once': True}, + { + 'key': 'aes256_key1', + 'type': 'aes256', + 'input': 'aes256_key.bin', + 'write_once': False, + 'b64': 'qZxftt2T8mOpLxALIfsDqI65srqPxrJtCVnDU8wrKXbFCJekDRzXqINlU5s=', + }, + {'key': 'p256_key0', 'type': 'ecdsa_p256', 'input': None, 'write_once': False}, + { + 'key': 'attest_key', + 'type': 'ecdsa_p256', + 'input': 'ecdsa_p256_key.pem', + 'write_once': True, + 'b64': ( + 'LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUlNU1VpUktHaVZjSTIvbUZFekI3eXRIOVJj' + 'd0wyUThkNDhONHNFUHFYc0RvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFSkYxYXRZQUxrdnB4cCt4N3c1dmVPQ1Vj' + 'RUhFRTY5azkvcFB5eFdTbEZkbW5wMnBmbVJpZwp5NnRTMDNaM2tnN2hYcitTQmNLbmRCV2RlZW81Vm9XV29nPT0K' + 'LS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=' + ), + }, + ] + + NVS_KEYS_B64 = 'MzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzPMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzA==' + + TMP_DIR = Path('tmp') + NVS_KEYS_PATH = TMP_DIR / 'nvs_keys.bin' + NVS_CSV_PATH = TMP_DIR / 'tee_sec_stg_val.csv' + NVS_BIN_PATH = TMP_DIR / 'tee_sec_stg_nvs.bin' + + def run_command(self, command: List[str]) -> None: + try: + subprocess.check_call(command, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError: + print(f'Command failed: {" ".join(command)}') + raise + + def write_keys_to_file(self, b64_data: str, path: Path) -> None: + path.write_bytes(base64.b64decode(b64_data)) + + def create_tee_sec_stg_csv(self, tmp_dir: Path) -> Path: + csv_path = self.NVS_CSV_PATH + rows: List[List[str]] = [ + ['key', 'type', 'encoding', 'value'], + ['tee_sec_stg_ns', 'namespace', '', ''], + ] + rows += [[entry['key'], 'file', 'binary', str(tmp_dir / f'{entry["key"]}.bin')] for entry in self.KEY_DEFS] + with csv_path.open('w', newline='') as f: + csv.writer(f).writerows(rows) + return csv_path + + def custom_flash_with_host_gen_sec_stg_img(self) -> None: + tmp_dir = self.TMP_DIR + tmp_dir.mkdir(parents=True, exist_ok=True) + + for entry in self.KEY_DEFS: + if entry['input']: + input_path = tmp_dir / entry['input'] + self.write_keys_to_file(entry['b64'], input_path) + entry['input'] = str(input_path) + self.write_keys_to_file(self.NVS_KEYS_B64, self.NVS_KEYS_PATH) + + idf_path = Path(os.environ['IDF_PATH']) + ESP_TEE_SEC_STG_KEYGEN = os.path.join( + idf_path, 'components', 'esp_tee', 'scripts', 'esp_tee_sec_stg_keygen', 'esp_tee_sec_stg_keygen.py' + ) + NVS_PARTITION_GEN = os.path.join( + idf_path, 'components', 'nvs_flash', 'nvs_partition_generator', 'nvs_partition_gen.py' + ) + + cmds = [ + [sys.executable, ESP_TEE_SEC_STG_KEYGEN, '-k', entry['type'], '-o', str(tmp_dir / f'{entry["key"]}.bin')] + + (['-i', entry['input']] if entry['input'] else []) + + (['--write-once'] if entry['write_once'] else []) + for entry in self.KEY_DEFS + ] + + csv_path = self.create_tee_sec_stg_csv(tmp_dir) + nvs_bin = self.NVS_BIN_PATH + nvs_keys = self.NVS_KEYS_PATH + size = self.app.partition_table['secure_storage']['size'] + + cmds.append( + [ + sys.executable, + NVS_PARTITION_GEN, + 'encrypt', + str(csv_path), + str(nvs_bin), + str(size), + '--inputkey', + str(nvs_keys), + ] + ) + + try: + for cmd in cmds: + self.run_command(cmd) + + self.bootloader_force_flash_if_req() + self.flash() + self.custom_erase_partition('secure_storage') + self.custom_write_partition('secure_storage', nvs_bin) + + finally: + shutil.rmtree(tmp_dir) + @pytest.fixture(scope='module') def monkeypatch_module(request: FixtureRequest) -> MonkeyPatch: diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_att.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_att.c index 105403c3ba..dc010d2cc4 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_att.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_att.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,14 +29,14 @@ #define ECDSA_SECP256R1_KEY_LEN (32) #define ESP_ATT_TK_BUF_SIZE (1792) -#define ESP_ATT_TK_PSA_CERT_REF ("0716053550477-10100") +#define ESP_ATT_TK_PSA_CERT_REF ("0632793520245-10010") #define ESP_ATT_TK_NONCE (0xABCD1234) #define ESP_ATT_TK_CLIENT_ID (0x0FACADE0) static const char *TAG = "test_esp_tee_att"; -extern int verify_ecdsa_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_pubkey_t *pubkey, const esp_tee_sec_storage_sign_t *sign, bool is_crv_p192); +extern int verify_ecdsa_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_ecdsa_pubkey_t *pubkey, const esp_tee_sec_storage_ecdsa_sign_t *sign, bool is_crv_p192); static uint8_t hexchar_to_byte(char hex) { @@ -72,7 +72,7 @@ static void hexstr_to_bytes(const char *hex_str, uint8_t **hex_buf, size_t *buf_ } } -static int decompress_ecdsa_pubkey(const mbedtls_ecp_group *grp, const unsigned char *input, size_t ilen, esp_tee_sec_storage_pubkey_t *pubkey) +static int decompress_ecdsa_pubkey(const mbedtls_ecp_group *grp, const unsigned char *input, size_t ilen, esp_tee_sec_storage_ecdsa_pubkey_t *pubkey) { int ret = -1; mbedtls_mpi r, x, n; @@ -186,7 +186,7 @@ static void prehash_token_data(const char *token_json, uint8_t *digest, size_t l cJSON_Delete(root); } -static void fetch_pubkey(const char *token_json, esp_tee_sec_storage_pubkey_t *pubkey_ctx) +static void fetch_pubkey(const char *token_json, esp_tee_sec_storage_ecdsa_pubkey_t *pubkey_ctx) { TEST_ASSERT_NOT_NULL(token_json); TEST_ASSERT_NOT_NULL(pubkey_ctx); @@ -218,7 +218,7 @@ static void fetch_pubkey(const char *token_json, esp_tee_sec_storage_pubkey_t *p cJSON_Delete(root); } -static void fetch_signature(const char *token_json, esp_tee_sec_storage_sign_t *sign_ctx) +static void fetch_signature(const char *token_json, esp_tee_sec_storage_ecdsa_sign_t *sign_ctx) { TEST_ASSERT_NOT_NULL(token_json); TEST_ASSERT_NOT_NULL(sign_ctx); @@ -267,11 +267,11 @@ TEST_CASE("Test TEE Attestation - Generate and verify the EAT", "[attestation]") prehash_token_data((const char *)token_buf, digest, sizeof(digest)); // Fetching and decompressing the public key - esp_tee_sec_storage_pubkey_t pubkey_ctx = {}; + esp_tee_sec_storage_ecdsa_pubkey_t pubkey_ctx = {}; fetch_pubkey((const char *)token_buf, &pubkey_ctx); // Fetching the signature components - esp_tee_sec_storage_sign_t sign_ctx = {}; + esp_tee_sec_storage_ecdsa_sign_t sign_ctx = {}; fetch_signature((const char *)token_buf, &sign_ctx); // Verifying the generated token diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c index ffd979db81..c6172ea3e0 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_flash_prot.c @@ -27,6 +27,8 @@ #define TEST_PART_LABEL "custom" #define TEST_BUF_SZ 256 +#define ESP_TEE_SEC_STG_PART_LABEL "secure_storage" + static const char *TAG = "test_esp_tee_flash_prot"; static void set_boot_count_in_nvs(uint8_t boot_count) @@ -93,7 +95,7 @@ static void test_esp_partition_mmap_api(void) TEST_FAIL_MESSAGE("System fault should have been generated"); break; case 5: - part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL); + part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, ESP_TEE_SEC_STG_PART_LABEL); TEST_ASSERT_NOT_NULL(part); TEST_ESP_OK(esp_partition_mmap(part, 0, part->size, ESP_PARTITION_MMAP_DATA, &outptr, &out_handle)); ESP_LOG_BUFFER_HEXDUMP(TAG, outptr, 0x20, ESP_LOG_INFO); @@ -149,7 +151,7 @@ static void test_esp_partition_api(void) test_esp_partition_api_w(part); break; case 4: - part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL); + part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, ESP_TEE_SEC_STG_PART_LABEL); test_esp_partition_api_w(part); break; case 5: @@ -255,7 +257,7 @@ static void test_esp_flash_api(void) test_esp_flash_api_r(part->address); break; case 4: - part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL); + part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, ESP_TEE_SEC_STG_PART_LABEL); TEST_ASSERT_NOT_NULL(part); test_esp_flash_api_e(part->address); break; @@ -327,7 +329,7 @@ static void test_esp_rom_spiflash_api(void) TEST_FAIL_MESSAGE("System fault should have been generated"); break; case 4: - part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL); + part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, ESP_TEE_SEC_STG_PART_LABEL); TEST_ASSERT_NOT_NULL(part); test_esp_rom_spiflash_api_e(part->address); TEST_FAIL_MESSAGE("System fault should have been generated"); diff --git a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c index 985a611ee9..79c9acc1ff 100644 --- a/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c +++ b/components/esp_tee/test_apps/tee_test_fw/main/test_esp_tee_panic.c @@ -30,7 +30,7 @@ extern uint32_t _instruction_reserved_start; #if CONFIG_SECURE_TEE_SEC_STG_MODE_RELEASE #define TEST_APM_EFUSE_PROT_REG \ - (EFUSE_RD_KEY0_DATA0_REG + (((CONFIG_SECURE_TEE_SEC_STG_KEY_EFUSE_BLK) - 4) * 0x20)) + (EFUSE_RD_KEY0_DATA0_REG + (CONFIG_SECURE_TEE_SEC_STG_EFUSE_HMAC_KEY_ID * 0x20)) #else #define TEST_APM_EFUSE_PROT_REG EFUSE_RD_KEY5_DATA0_REG #endif 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 bfbb349dfc..4f979a0e95 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 @@ -17,9 +17,12 @@ #include "esp_tee.h" #include "esp_tee_sec_storage.h" #include "secure_service_num.h" +#if CONFIG_SECURE_TEE_ATTESTATION +#include "esp_tee_attestation.h" +#endif #include "esp_random.h" - +#include "nvs.h" #include "unity.h" #include "sdkconfig.h" @@ -31,9 +34,14 @@ #define ECDSA_SECP256R1_KEY_LEN (32) #define ECDSA_SECP192R1_KEY_LEN (24) +#define ESP_ATT_TK_BUF_SIZE (1792) +#define ESP_ATT_TK_PSA_CERT_REF ("0632793520245-10010") + +#define MAX_SEC_STG_ITER (16) + static const char *TAG = "test_esp_tee_sec_storage"; -int verify_ecdsa_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_pubkey_t *pubkey, const esp_tee_sec_storage_sign_t *sign, bool is_crv_p192) +int verify_ecdsa_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_ecdsa_pubkey_t *pubkey, const esp_tee_sec_storage_ecdsa_sign_t *sign, bool is_crv_p192) { #if !CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN TEST_ASSERT_FALSE(is_crv_p192); @@ -73,7 +81,7 @@ int verify_ecdsa_sign(const uint8_t *digest, size_t len, const esp_tee_sec_stora return 0; } -TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp256r1) with all key-slot IDs", "[secure_storage]") +TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp256r1)", "[sec_storage]") { const size_t buf_sz = 16 * 1024 + 6; // NOTE: Not an exact multiple of SHA block size unsigned char *message = heap_caps_malloc(buf_sz, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); @@ -85,27 +93,34 @@ TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp256r1) with all key- TEST_ASSERT_MBEDTLS_OK(mbedtls_sha256(message, buf_sz, msg_digest, false)); free(message); - TEST_ESP_OK(esp_tee_sec_storage_init()); + esp_tee_sec_storage_key_cfg_t key_cfg = { + .type = ESP_SEC_STG_KEY_ECDSA_SECP256R1 + }; - for (uint16_t slot_id = 0; slot_id <= MAX_SEC_STG_SLOT_ID; slot_id++) { - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1)); + for (unsigned int i = 0; i < MAX_SEC_STG_ITER; i++) { + char key_id[32]; + int ret = snprintf(key_id, sizeof(key_id), "ecdsa_key_%u", i); + TEST_ASSERT_TRUE(ret > 0 && ret < sizeof(key_id)); - esp_tee_sec_storage_sign_t sign = {}; - TEST_ESP_OK(esp_tee_sec_storage_get_signature(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, msg_digest, sizeof(msg_digest), &sign)); + key_cfg.id = key_id; + 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)); - esp_tee_sec_storage_pubkey_t pubkey = {}; - TEST_ESP_OK(esp_tee_sec_storage_get_pubkey(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1, &pubkey)); + esp_tee_sec_storage_ecdsa_sign_t sign = {}; + TEST_ESP_OK(esp_tee_sec_storage_ecdsa_sign(&key_cfg, msg_digest, sizeof(msg_digest), &sign)); + + esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {}; + TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey)); TEST_ESP_OK(verify_ecdsa_sign(msg_digest, sizeof(msg_digest), &pubkey, &sign, false)); - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - TEST_ASSERT_TRUE(esp_tee_sec_storage_is_slot_empty(slot_id)); + TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id)); } } #if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN -TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp192r1) with all key-slot IDs", "[secure_storage]") +TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp192r1)", "[sec_storage]") { const size_t buf_sz = 16 * 1024 + 6; // NOTE: Not an exact multiple of SHA block size unsigned char *message = heap_caps_malloc(buf_sz, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); @@ -117,27 +132,34 @@ TEST_CASE("Test TEE Secure Storage - Sign-verify (ecdsa_secp192r1) with all key- TEST_ASSERT_MBEDTLS_OK(mbedtls_sha256(message, buf_sz, msg_digest, false)); free(message); - TEST_ESP_OK(esp_tee_sec_storage_init()); + esp_tee_sec_storage_key_cfg_t key_cfg = { + .type = ESP_SEC_STG_KEY_ECDSA_SECP192R1 + }; - for (uint16_t slot_id = 0; slot_id <= MAX_SEC_STG_SLOT_ID; slot_id++) { - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP192R1)); + for (unsigned int i = 0; i < MAX_SEC_STG_ITER; i++) { + char key_id[32]; + int ret = snprintf(key_id, sizeof(key_id), "ecdsa_key_%u", i); + TEST_ASSERT_TRUE(ret > 0 && ret < sizeof(key_id)); - esp_tee_sec_storage_sign_t sign = {}; - TEST_ESP_OK(esp_tee_sec_storage_get_signature(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP192R1, msg_digest, sizeof(msg_digest), &sign)); + key_cfg.id = key_id; + 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)); - esp_tee_sec_storage_pubkey_t pubkey = {}; - TEST_ESP_OK(esp_tee_sec_storage_get_pubkey(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP192R1, &pubkey)); + esp_tee_sec_storage_ecdsa_sign_t sign = {}; + TEST_ESP_OK(esp_tee_sec_storage_ecdsa_sign(&key_cfg, msg_digest, sizeof(msg_digest), &sign)); + + esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {}; + TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey)); TEST_ESP_OK(verify_ecdsa_sign(msg_digest, sizeof(msg_digest), &pubkey, &sign, true)); - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - TEST_ASSERT_TRUE(esp_tee_sec_storage_is_slot_empty(slot_id)); + TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id)); } } #endif -TEST_CASE("Test TEE Secure Storage - Encrypt-decrypt (aes256_gcm) with all key-slot IDs", "[secure_storage]") +TEST_CASE("Test TEE Secure Storage - Encrypt-decrypt (aes256_gcm)", "[sec_storage]") { const uint8_t SZ = 100; uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); @@ -154,21 +176,37 @@ TEST_CASE("Test TEE Secure Storage - Encrypt-decrypt (aes256_gcm) with all key-s uint8_t aad[16]; memset(aad, 0xA5, sizeof(aad)); - TEST_ESP_OK(esp_tee_sec_storage_init()); + esp_tee_sec_storage_key_cfg_t key_cfg = { + .type = ESP_SEC_STG_KEY_AES256 + }; - for (uint16_t slot_id = 0; slot_id <= MAX_SEC_STG_SLOT_ID; slot_id++) { - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_AES256)); + for (unsigned int i = 0; i < MAX_SEC_STG_ITER; i++) { + char test_key_id[32]; + int ret = snprintf(test_key_id, sizeof(test_key_id), "aes_key_%u", i); + TEST_ASSERT_TRUE(ret > 0 && ret < sizeof(test_key_id)); - TEST_ESP_OK(esp_tee_sec_storage_encrypt(slot_id, plaintext, SZ, aad, sizeof(aad), - tag, sizeof(tag), ciphertext)); - TEST_ESP_OK(esp_tee_sec_storage_decrypt(slot_id, ciphertext, SZ, aad, sizeof(aad), - tag, sizeof(tag), decryptedtext)); + key_cfg.id = test_key_id; + 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)); + + esp_tee_sec_storage_aead_ctx_t aead_ctx = { + .key_id = test_key_id, + .aad = aad, + .aad_len = sizeof(aad), + }; + + aead_ctx.input = plaintext; + aead_ctx.input_len = SZ; + TEST_ESP_OK(esp_tee_sec_storage_aead_encrypt(&aead_ctx, 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_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ); - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - TEST_ASSERT_TRUE(esp_tee_sec_storage_is_slot_empty(slot_id)); + TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id)); } free(plaintext); @@ -176,7 +214,7 @@ TEST_CASE("Test TEE Secure Storage - Encrypt-decrypt (aes256_gcm) with all key-s free(decryptedtext); } -TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys", "[secure_storage]") +TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys", "[sec_storage]") { // Setup for ECDSA const uint8_t SZ = 100; @@ -187,6 +225,12 @@ TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys", TEST_ASSERT_MBEDTLS_OK(mbedtls_sha256(message, SZ, msg_digest, false)); free(message); + const char *key_id = "key_id_misc"; + esp_tee_sec_storage_key_cfg_t key_cfg = { + .id = key_id, + .type = ESP_SEC_STG_KEY_ECDSA_SECP256R1 + }; + // Setup for AES uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); TEST_ASSERT_NOT_NULL(plaintext); @@ -197,127 +241,195 @@ TEST_CASE("Test TEE Secure Storage - Operations with invalid/non-existent keys", uint8_t aad[16]; memset(aad, 0xA5, sizeof(aad)); - TEST_ESP_OK(esp_tee_sec_storage_init()); + esp_tee_sec_storage_aead_ctx_t aead_ctx = { + .key_id = key_id, + .aad = aad, + .aad_len = sizeof(aad), + .input = plaintext, + .input_len = SZ + }; // Test ECDSA key with AES operation - const uint16_t slot_id = 7; - ESP_LOGI(TAG, "Slot ID: %u - Trying AES operation with ECDSA key...", slot_id); - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); + ESP_LOGI(TAG, "Key ID: %s - Trying AES operation with ECDSA key...", key_cfg.id); + esp_err_t err = esp_tee_sec_storage_clear_key(key_cfg.id); + ESP_LOGW(TAG, "err: %x", err); + 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)); - esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; - TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, key_type)); - - TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_tee_sec_storage_encrypt(slot_id, plaintext, SZ, aad, sizeof(aad), - tag, sizeof(tag), ciphertext)); + TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id)); // Test AES key with ECDSA operation - ESP_LOGI(TAG, "Slot ID: %u - Trying ECDSA operation with AES key...", slot_id); - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_AES256)); + ESP_LOGI(TAG, "Key ID: %s - Trying ECDSA operation with AES key...", key_cfg.id); + TEST_ASSERT_TRUE(err == ESP_OK || err == ESP_ERR_NOT_FOUND); + key_cfg.type = ESP_SEC_STG_KEY_AES256; + TEST_ESP_OK(esp_tee_sec_storage_gen_key(&key_cfg)); - esp_tee_sec_storage_sign_t sign = {}; - TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_tee_sec_storage_get_signature(slot_id, key_type, msg_digest, sizeof(msg_digest), &sign)); - - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - TEST_ASSERT_TRUE(esp_tee_sec_storage_is_slot_empty(slot_id)); + esp_tee_sec_storage_ecdsa_sign_t sign = {}; + TEST_ESP_ERR(ESP_FAIL, esp_tee_sec_storage_ecdsa_sign(&key_cfg, msg_digest, sizeof(msg_digest), &sign)); + TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id)); // Test with non-existent data - TEST_ESP_ERR(ESP_ERR_NOT_FOUND, esp_tee_sec_storage_encrypt(slot_id, plaintext, SZ, aad, sizeof(aad), - tag, sizeof(tag), ciphertext)); + TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, esp_tee_sec_storage_aead_encrypt(&aead_ctx, tag, sizeof(tag), ciphertext)); free(plaintext); free(ciphertext); } -TEST_CASE("Test TEE Secure Storage - Invalid key-slot IDs", "[secure_storage]") +TEST_CASE("Test TEE Secure Storage - Null Pointer and Zero Length", "[sec_storage]") { - TEST_ESP_OK(esp_tee_sec_storage_init()); - - uint16_t slot_id = MAX_SEC_STG_SLOT_ID + 1; - TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_ECDSA_SECP256R1)); - - slot_id = MIN_SEC_STG_SLOT_ID - 1; - TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_AES256)); -} - -TEST_CASE("Test TEE Secure Storage - Exhaust all key-slots", "[secure_storage]") -{ - TEST_ESP_OK(esp_tee_sec_storage_init()); - - esp_err_t err = ESP_FAIL; - uint16_t slot_id = MIN_SEC_STG_SLOT_ID; - - while (1) { - esp_tee_sec_storage_clear_slot(slot_id); - err = esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_AES256); - if (err != ESP_OK) { - break; - } - TEST_ASSERT_FALSE(esp_tee_sec_storage_is_slot_empty(slot_id)); - slot_id++; - } - TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err); - - TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_gen_key(MAX_SEC_STG_SLOT_ID, ESP_SEC_STG_KEY_AES256)); - TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_gen_key(MIN_SEC_STG_SLOT_ID, ESP_SEC_STG_KEY_AES256)); - - uint16_t mid_slot = (MIN_SEC_STG_SLOT_ID + MAX_SEC_STG_SLOT_ID) / 2; - TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_gen_key(mid_slot, ESP_SEC_STG_KEY_AES256)); -} - -TEST_CASE("Test TEE Secure Storage - Null Pointer and Zero Length", "[secure_storage]") -{ - TEST_ESP_OK(esp_tee_sec_storage_init()); - - const uint16_t slot_id = 7; + const char *key_id = "key_id_misc"; uint8_t data[31], tag[12]; - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, ESP_SEC_STG_KEY_AES256)); + esp_tee_sec_storage_key_cfg_t key_cfg = { + .id = key_id, + .type = ESP_SEC_STG_KEY_AES256 + }; - TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_encrypt(slot_id, NULL, sizeof(data), NULL, 0, tag, sizeof(tag), data)); - TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_encrypt(slot_id, data, 0, NULL, 0, tag, sizeof(tag), data)); - TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_encrypt(slot_id, data, sizeof(data), NULL, 0, NULL, sizeof(tag), data)); - TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_encrypt(slot_id, data, sizeof(data), NULL, 0, tag, 0, data)); + 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_ARG, esp_tee_sec_storage_decrypt(slot_id, NULL, sizeof(data), NULL, 0, tag, sizeof(tag), data)); - TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_decrypt(slot_id, data, 0, NULL, 0, tag, sizeof(tag), data)); - TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_decrypt(slot_id, data, sizeof(data), NULL, 0, NULL, sizeof(tag), data)); - TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_decrypt(slot_id, data, sizeof(data), NULL, 0, tag, 0, data)); + esp_tee_sec_storage_aead_ctx_t aead_ctx = { + .key_id = key_cfg.id, + .input = data, + .input_len = sizeof(data), + }; - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); + 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)); - esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; - TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, key_type)); + 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)); - esp_tee_sec_storage_sign_t sign = {}; - TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_get_signature(slot_id, key_type, NULL, sizeof(data), &sign)); - TEST_ESP_ERR(ESP_ERR_INVALID_SIZE, esp_tee_sec_storage_get_signature(slot_id, key_type, data, 0, &sign)); - TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_get_signature(slot_id, key_type, data, sizeof(data), NULL)); + 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_ARG, esp_tee_sec_storage_get_pubkey(slot_id, key_type, NULL)); + TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_id)); - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); + key_cfg.type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; + 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)); + + esp_tee_sec_storage_ecdsa_sign_t sign = {}; + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_ecdsa_sign(&key_cfg, NULL, sizeof(data), &sign)); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_ecdsa_sign(&key_cfg, data, 0, &sign)); + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_ecdsa_sign(&key_cfg, data, sizeof(data), NULL)); + + TEST_ESP_ERR(ESP_ERR_INVALID_ARG, esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, NULL)); + + TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id)); } -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6) -TEST_CASE("Test TEE Secure Storage - Corruption from non-secure world", "[secure_storage_neg]") +TEST_CASE("Test TEE Secure Storage - WRITE_ONCE keys", "[sec_storage]") { - const esp_partition_t *tee_sec_stg = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_TEE_SEC_STORAGE, NULL); - TEST_ASSERT_NOT_NULL(tee_sec_stg); + const char *key_id = "key_id_test_wo"; - uint8_t buf_w[128]; - memset(buf_w, 0xA5, sizeof(buf_w)); - TEST_ESP_OK(esp_partition_write(tee_sec_stg, 0x00, buf_w, sizeof(buf_w))); + esp_tee_sec_storage_key_cfg_t key_cfg = { + .id = key_id, + .type = ESP_SEC_STG_KEY_AES256, + .flags = SEC_STORAGE_FLAG_WRITE_ONCE, + }; - uint8_t buf_r[128]; - memset(buf_r, 0x00, sizeof(buf_r)); - TEST_ESP_OK(esp_partition_read(tee_sec_stg, 0x00, buf_r, sizeof(buf_r))); - ESP_LOG_BUFFER_HEXDUMP(TAG, buf_r, sizeof(buf_r), ESP_LOG_INFO); + 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_FAIL_MESSAGE("APM violation interrupt should have been generated"); + TEST_ESP_OK(esp_tee_sec_storage_gen_key(&key_cfg)); + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_gen_key(&key_cfg)); + + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(key_cfg.id)); } + +static void test_aead_encrypt_decrypt(const char *key_id, const uint8_t *input, size_t len) +{ + uint8_t *ciphertext = heap_caps_malloc(len, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(ciphertext); + uint8_t *decrypted = heap_caps_malloc(len, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(decrypted); + + uint8_t tag[12]; + uint8_t aad[16]; + esp_fill_random(aad, sizeof(aad)); + + esp_tee_sec_storage_aead_ctx_t ctx = { + .key_id = key_id, + .aad = aad, + .aad_len = sizeof(aad), + }; + + ctx.input = input; + ctx.input_len = len; + TEST_ESP_OK(esp_tee_sec_storage_aead_encrypt(&ctx, 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_ASSERT_EQUAL_HEX8_ARRAY(input, decrypted, len); + + free(ciphertext); + free(decrypted); +} + +TEST_CASE("Test TEE Secure Storage - Host-generated keys", "[sec_storage_host_keygen]") +{ + const char *aes_key_id0 = "aes256_key0"; + const char *aes_key_id1 = "aes256_key1"; + const char *ecdsa_key_id0 = "p256_key0"; + const char *attest_key_id = "attest_key"; + + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(aes_key_id0)); + + const size_t SZ = 100; + uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(plaintext); + esp_fill_random(plaintext, SZ); + + test_aead_encrypt_decrypt(aes_key_id0, plaintext, SZ); + test_aead_encrypt_decrypt(aes_key_id1, plaintext, SZ); + + free(plaintext); + + TEST_ESP_OK(esp_tee_sec_storage_clear_key(aes_key_id1)); + + uint8_t msg_digest[SHA256_DIGEST_SZ]; + esp_fill_random(msg_digest, sizeof(msg_digest)); + + esp_tee_sec_storage_key_cfg_t key_cfg = { + .id = ecdsa_key_id0, + .type = ESP_SEC_STG_KEY_ECDSA_SECP256R1, + }; + + esp_tee_sec_storage_ecdsa_sign_t sign = {}; + TEST_ESP_OK(esp_tee_sec_storage_ecdsa_sign(&key_cfg, msg_digest, sizeof(msg_digest), &sign)); + + esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {}; + TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey)); + + TEST_ESP_OK(verify_ecdsa_sign(msg_digest, sizeof(msg_digest), &pubkey, &sign, false)); + + TEST_ESP_OK(esp_tee_sec_storage_clear_key(ecdsa_key_id0)); + + TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_tee_sec_storage_clear_key(attest_key_id)); + +#if CONFIG_SECURE_TEE_ATTESTATION + uint8_t *token_buf = heap_caps_calloc(ESP_ATT_TK_BUF_SIZE, sizeof(uint8_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(token_buf); + + uint32_t token_len = 0; + TEST_ESP_OK(esp_tee_att_generate_token(0xA1B2C3D4, 0x0FACADE0, (const char *)ESP_ATT_TK_PSA_CERT_REF, + token_buf, ESP_ATT_TK_BUF_SIZE, &token_len)); + + free(token_buf); #endif +} #if CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN static const uint8_t sha[] = { @@ -327,11 +439,8 @@ static const uint8_t sha[] = { 0x91, 0xbe, 0x58, 0x10, 0xfe, 0x80, 0x65, 0x6e }; -static void test_ecdsa_sign(mbedtls_ecp_group_id gid, const uint8_t *hash, int slot_id) +static void test_ecdsa_sign(mbedtls_ecp_group_id gid) { - TEST_ESP_OK(esp_tee_sec_storage_init()); - TEST_ESP_OK(esp_tee_sec_storage_clear_slot(slot_id)); - bool is_crv_p192 = false; esp_tee_sec_storage_type_t key_type = ESP_SEC_STG_KEY_ECDSA_SECP256R1; size_t key_len = ECDSA_SECP256R1_KEY_LEN; @@ -342,10 +451,20 @@ static void test_ecdsa_sign(mbedtls_ecp_group_id gid, const uint8_t *hash, int s key_len = ECDSA_SECP192R1_KEY_LEN; } - TEST_ESP_OK(esp_tee_sec_storage_gen_key(slot_id, key_type)); + const char *key_id = "ecdsa_k0"; - esp_tee_sec_storage_pubkey_t pubkey = {}; - TEST_ESP_OK(esp_tee_sec_storage_get_pubkey(slot_id, key_type, &pubkey)); + esp_tee_sec_storage_key_cfg_t key_cfg = { + .id = key_id, + .type = key_type + }; + + 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)); + + esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {}; + TEST_ESP_OK(esp_tee_sec_storage_ecdsa_get_pubkey(&key_cfg, &pubkey)); mbedtls_mpi r, s; mbedtls_mpi_init(&r); @@ -360,7 +479,7 @@ static void test_ecdsa_sign(mbedtls_ecp_group_id gid, const uint8_t *hash, int s esp_ecdsa_pk_conf_t conf = { .grp_id = gid, - .tee_slot_id = slot_id, + .tee_key_id = key_id, .load_pubkey = true, .use_tee_sec_stg_key = true, }; @@ -371,7 +490,7 @@ static void test_ecdsa_sign(mbedtls_ecp_group_id gid, const uint8_t *hash, int s TEST_ASSERT_MBEDTLS_OK(mbedtls_ecdsa_sign(&ecdsa_context.MBEDTLS_PRIVATE(grp), &r, &s, &key_mpi, sha, SHA256_DIGEST_SZ, NULL, NULL)); - esp_tee_sec_storage_sign_t sign = {}; + esp_tee_sec_storage_ecdsa_sign_t sign = {}; TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&r, sign.sign_r, key_len)); TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&s, sign.sign_s, key_len)); @@ -381,13 +500,15 @@ static void test_ecdsa_sign(mbedtls_ecp_group_id gid, const uint8_t *hash, int s mbedtls_ecdsa_free(&ecdsa_context); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); + + TEST_ESP_OK(esp_tee_sec_storage_clear_key(key_cfg.id)); } TEST_CASE("Test TEE Secure Storage - mbedtls ECDSA signing", "[mbedtls]") { - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1, sha, MIN_SEC_STG_SLOT_ID); + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP256R1); #if CONFIG_SECURE_TEE_SEC_STG_SUPPORT_SECP192R1_SIGN - test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1, sha, MAX_SEC_STG_SLOT_ID); + test_ecdsa_sign(MBEDTLS_ECP_DP_SECP192R1); #endif } #endif diff --git a/components/esp_tee/test_apps/tee_test_fw/partitions.csv b/components/esp_tee/test_apps/tee_test_fw/partitions.csv deleted file mode 100644 index d79624198b..0000000000 --- a/components/esp_tee/test_apps/tee_test_fw/partitions.csv +++ /dev/null @@ -1,7 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -tee, app, tee_0, , 192K, -secure_storage, data, tee_sec_stg, , 64K, -factory, app, factory, , 512K, -nvs, data, nvs, , 24K, -custom, data, , , 1M diff --git a/components/esp_tee/test_apps/tee_test_fw/partitions_tee_ota.csv b/components/esp_tee/test_apps/tee_test_fw/partitions_tee_ota.csv index 6708e6401e..b160851614 100644 --- a/components/esp_tee/test_apps/tee_test_fw/partitions_tee_ota.csv +++ b/components/esp_tee/test_apps/tee_test_fw/partitions_tee_ota.csv @@ -3,7 +3,7 @@ tee_0, app, tee_0, , 192K, tee_1, app, tee_1, , 192K, tee_otadata, data, tee_ota, , 8K, -secure_storage, data, tee_sec_stg, , 56K, +secure_storage, data, nvs, , 56K, ota_0, app, ota_0, , 512K, ota_1, app, ota_1, , 512K, otadata, data, ota, , 8K, diff --git a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py index b0d2afc6b2..2dd5eae1fe 100644 --- a/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py +++ b/components/esp_tee/test_apps/tee_test_fw/pytest_esp_tee_ut.py @@ -442,7 +442,18 @@ def test_esp_tee_secure_storage(dut: IdfDut) -> None: # Flash image and erase the secure_storage partition dut.serial.custom_flash_with_empty_sec_stg() - dut.run_all_single_board_cases(group='secure_storage') + dut.run_all_single_board_cases(group='sec_storage') + + +@pytest.mark.generic +@idf_parametrize('config', ['ota'], indirect=['config']) +@idf_parametrize('skip_autoflash', ['y'], indirect=['skip_autoflash']) +@idf_parametrize('target', ['esp32c6'], indirect=['target']) +def test_esp_tee_secure_storage_with_host_img(dut: IdfDut) -> None: + # Flash image and write the secure_storage partition with host-generated keys + dut.serial.custom_flash_with_host_gen_sec_stg_img() + + dut.run_all_single_board_cases(group='sec_storage_host_keygen') # ---------------- TEE Attestation tests ---------------- diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.default b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.default index e69de29bb2..7cfae6816f 100644 --- a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.default +++ b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.ci.default @@ -0,0 +1,5 @@ +# Decreasing Bootloader log verbosity +CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y + +# Disabling ATTESTATION +CONFIG_SECURE_TEE_ATTESTATION=n diff --git a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults index a9385d8937..9e3a863aba 100644 --- a/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults +++ b/components/esp_tee/test_apps/tee_test_fw/sdkconfig.defaults @@ -7,10 +7,8 @@ CONFIG_SECURE_ENABLE_TEE=y CONFIG_SECURE_TEE_DEBUG_MODE=y CONFIG_SECURE_TEE_TEST_MODE=y -# Custom partition table -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +# Setting partition table +CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y # TEE IRAM size CONFIG_SECURE_TEE_IRAM_SIZE=0x8400 diff --git a/examples/security/tee/tee_secure_storage/main/Kconfig.projbuild b/examples/security/tee/tee_secure_storage/main/Kconfig.projbuild index f6ad163e6f..0246a1e935 100644 --- a/examples/security/tee/tee_secure_storage/main/Kconfig.projbuild +++ b/examples/security/tee/tee_secure_storage/main/Kconfig.projbuild @@ -1,11 +1,10 @@ menu "Example Configuration" - config EXAMPLE_TEE_SEC_STG_SLOT_ID - int "TEE: Secure Storage keypair slot ID" - default 0 - range 0 15 + config EXAMPLE_TEE_SEC_STG_KEY_STR_ID + string "TEE: Secure Storage Key ID" + default "key_id_0" help - This configuration sets the slot ID from the TEE secure storage + This configuration sets the key string identifier from the TEE secure storage storing the ECDSA keypair for executing sign/verify operations from the TEE side 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 14742ef03d..767a9fbd7d 100644 --- a/examples/security/tee/tee_secure_storage/main/tee_main.c +++ b/examples/security/tee/tee_secure_storage/main/tee_main.c @@ -1,7 +1,7 @@ /* * TEE Secure Storage example * - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -21,20 +21,21 @@ #include "esp_tee_sec_storage.h" #include "secure_service_num.h" +#include "sdkconfig.h" #define SHA256_DIGEST_SZ (32) #define ECDSA_SECP256R1_KEY_LEN (32) #define AES256_GCM_TAG_LEN (16) #define AES256_GCM_AAD_LEN (16) -#define KEY_SLOT_ID (CONFIG_EXAMPLE_TEE_SEC_STG_SLOT_ID) +#define KEY_STR_ID (CONFIG_EXAMPLE_TEE_SEC_STG_KEY_STR_ID) #define MAX_AES_PLAINTEXT_LEN (128) static const char *message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."; static const char *TAG = "example_tee_sec_stg"; -static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_pubkey_t *pubkey, const esp_tee_sec_storage_sign_t *sign) +static esp_err_t verify_ecdsa_secp256r1_sign(const uint8_t *digest, size_t len, const esp_tee_sec_storage_ecdsa_pubkey_t *pubkey, const esp_tee_sec_storage_ecdsa_sign_t *sign) { if (pubkey == NULL || digest == NULL || sign == NULL) { return ESP_ERR_INVALID_ARG; @@ -112,20 +113,25 @@ static void example_tee_sec_stg_sign_verify(void *pvParameter) goto exit; } - esp_err_t err = esp_tee_sec_storage_clear_slot(KEY_SLOT_ID); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to clear slot %d!", KEY_SLOT_ID); + esp_tee_sec_storage_key_cfg_t cfg = { + .id = (const char *)(KEY_STR_ID), + .type = ESP_SEC_STG_KEY_ECDSA_SECP256R1 + }; + + esp_err_t err = esp_tee_sec_storage_clear_key(cfg.id); + if (err != ESP_OK && err != ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to clear key %d!", cfg.id); goto exit; } - err = esp_tee_sec_storage_gen_key(KEY_SLOT_ID, ESP_SEC_STG_KEY_ECDSA_SECP256R1); + err = esp_tee_sec_storage_gen_key(&cfg); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to generate keypair!"); goto exit; } - esp_tee_sec_storage_sign_t sign = {}; - err = esp_tee_sec_storage_get_signature(KEY_SLOT_ID, ESP_SEC_STG_KEY_ECDSA_SECP256R1, msg_digest, sizeof(msg_digest), &sign); + esp_tee_sec_storage_ecdsa_sign_t sign = {}; + err = esp_tee_sec_storage_ecdsa_sign(&cfg, msg_digest, sizeof(msg_digest), &sign); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to generate signature!"); goto exit; @@ -133,8 +139,8 @@ static void example_tee_sec_stg_sign_verify(void *pvParameter) ESP_LOG_BUFFER_HEX("Signature", &sign, sizeof(sign)); - esp_tee_sec_storage_pubkey_t pubkey = {}; - err = esp_tee_sec_storage_get_pubkey(KEY_SLOT_ID, ESP_SEC_STG_KEY_ECDSA_SECP256R1, &pubkey); + esp_tee_sec_storage_ecdsa_pubkey_t pubkey = {}; + err = esp_tee_sec_storage_ecdsa_get_pubkey(&cfg, &pubkey); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to fetch public-key!"); goto exit; @@ -175,19 +181,32 @@ static void example_tee_sec_stg_encrypt_decrypt(void *pvParameter) goto exit; } - err = esp_tee_sec_storage_clear_slot(KEY_SLOT_ID); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to clear slot %d!", KEY_SLOT_ID); + esp_tee_sec_storage_key_cfg_t cfg = { + .id = (const char *)(KEY_STR_ID), + .type = ESP_SEC_STG_KEY_AES256 + }; + + err = esp_tee_sec_storage_clear_key(cfg.id); + if (err != ESP_OK && err != ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Failed to clear key %d!", cfg.id); goto exit; } - err = esp_tee_sec_storage_gen_key(KEY_SLOT_ID, ESP_SEC_STG_KEY_AES256); + err = esp_tee_sec_storage_gen_key(&cfg); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to generate key!"); goto exit; } - err = esp_tee_sec_storage_encrypt(KEY_SLOT_ID, (uint8_t *)plaintext, plaintext_len, aad_buf, sizeof(aad_buf), tag, sizeof(tag), ciphertext); + esp_tee_sec_storage_aead_ctx_t ctx = { + .key_id = cfg.id, + .aad = aad_buf, + .aad_len = sizeof(aad_buf), + }; + + ctx.input = (const uint8_t *)plaintext; + ctx.input_len = plaintext_len; + err = esp_tee_sec_storage_aead_encrypt(&ctx, tag, sizeof(tag), ciphertext); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to encrypt data!"); goto exit; @@ -195,7 +214,9 @@ static void example_tee_sec_stg_encrypt_decrypt(void *pvParameter) ESP_LOG_BUFFER_HEX("Encrypted data", ciphertext, plaintext_len); - err = esp_tee_sec_storage_decrypt(KEY_SLOT_ID, (uint8_t *)ciphertext, plaintext_len, aad_buf, sizeof(aad_buf), tag, sizeof(tag), ciphertext); + ctx.input = (const uint8_t *)ciphertext; + ctx.input_len = plaintext_len; + err = esp_tee_sec_storage_aead_decrypt(&ctx, tag, sizeof(tag), ciphertext); if (err != ESP_OK || memcmp(ciphertext, plaintext, plaintext_len) != 0) { ESP_LOGE(TAG, "Encryption verification failed!"); err = ESP_FAIL; @@ -216,8 +237,6 @@ void app_main(void) { ESP_LOGI(TAG, "TEE Secure Storage"); - ESP_ERROR_CHECK(esp_tee_sec_storage_init()); - xTaskCreate(example_tee_sec_stg_sign_verify, "tee_sec_stg_sign_verify", 4096, (void *)message, 5, NULL); xTaskCreate(example_tee_sec_stg_encrypt_decrypt, "tee_sec_stg_encrypt_decrypt", 4096, (void *)message, 5, NULL); }