| Supported Targets | ESP32-C6 | | ----------------- | -------- | # TEE CLI Application: Secure Services Demonstration ## Example Usage ### Hardware Required This example can be executed on any development board with a Espressif SOC chip supporting the TEE framework (see Supported Targets table above). ### Configure the project - Before the project configuration and build, be sure to set the correct chip target using `idf.py set-target `. - Open the project configuration menu (`idf.py menuconfig`). - Configure the secure storage slot ID for generating/fetching the ECDSA keypair for attestation token signing at `(Top) → Security features → TEE: Secure Storage slot ID for EAT signing`. If this configuration is not set, the slot with ID **0** will be used as default. - Configure the Secure Storage mode for determining which eFuse block stores the encryption key at `(Top) → Security features → Trusted Execution Environment → TEE: Secure Storage Mode`. - **Development** Mode: The encryption key is statically embedded in the TEE firmware. - **Release** Mode: The encryption key is stored in eFuse BLK4 - BLK9, depending on the `SECURE_TEE_SEC_STG_KEY_EFUSE_BLK` Kconfig option. - Set the eFuse block ID to store the encryption key in `Security features → Trusted Execution Environment → TEE: Secure Storage encryption key eFuse block`. - Snippet for burning the secure storage key in eFuse is given below. ```shell # Programming user key (256-bit) in eFuse # Here, BLOCK_KEYx is a free eFuse key-block between BLOCK_KEY0 and BLOCK_KEY5 espefuse.py -p PORT burn_key BLOCK_KEYx user_key.bin USER ``` ### Build and Flash - Build the project and flash it to the board, then run the monitor tool to view the serial output: ```shell # Replace PORT with the name of the serial port to use idf.py -p flash monitor ``` (To exit the serial monitor, type `Ctrl-]`.) Refer the _Getting Started_ guide for full steps to configure and use ESP-IDF to build projects. ### Example Output Enter the `help` command get a full list of all available commands provided by the example. ```log I (627) app_start: Starting scheduler on CPU0 I (632) main_task: Started on CPU0 I (632) main_task: Calling app_main() I (632) example: ESP-TEE: Secure services demonstration Type 'help' to get the list of commands. Use UP/DOWN arrows to navigate through command history. Press TAB when typing command name to auto-complete. I (702) main_task: Returned from app_main() esp32c6> help wifi_connect [--timeout=] [] Join WiFi AP as a station --timeout= Connection timeout, ms SSID of AP PSK of AP tee_ota Initiate TEE app OTA URL for fetching the update user_ota Initiate User app OTA URL for fetching the update tee_att_info Dump the TEE-generated entity attestation token 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_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 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 <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 <ciphertext> Ciphertext to be decrypted <tag> AES-GCM authentication tag help Print the list of registered commands ``` ## Secure Services ### 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. <details> <summary><b>Sample output:</b> <i>tee_att_info</i></summary> ```log esp32c6> tee_att_info I (8180) tee_attest: Attestation token - Length: 1455 I (8180) tee_attest: Attestation token - Data: '{"header":{"magic":"44fef7cc","encr_alg":"","sign_alg":"ecdsa_secp256r1_sha256","key_id":0},"eat":{"nonce":-1582119980,"client_id":262974944,"device_ver":0,"device_id":"cd9c173cb3675c7adfae243f0cd9841e4bce003237cb5321927a85a86cb4b32e","instance_id":"9616ef0ecf02cdc89a3749f8fc16b3103d5100bd42d9312fcd04593baa7bac64","psa_cert_ref":"0716053550477-10100","device_status":165,"sw_claims":{"tee":{"type":1,"ver":"v0.3.0","idf_ver":"v5.1.4-241-g7ff01fd46f-dirty","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"94536998e1dcb2a036477cb2feb01ed4fff67ba6208f30482346c62bca64b280","digest_validated":true,"sign_verified":true}},"app":{"type":2,"ver":"v0.1.0","idf_ver":"v5.1.4-241-g7ff01fd46f-dirty","secure_ver":0,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"3d4c038fcec76852b4d07acb9e94afaf5fca69fc2eb212a32032d09ce5b4f2b3","digest_validated":true,"sign_verified":true,"secure_padding":true}},"bootloader":{"type":0,"ver":"","idf_ver":"","secure_ver":-1,"part_chip_rev":{"min":0,"max":99},"part_digest":{"type":0,"calc_digest":"1bef421beb1a4642c6fcefb3e37fd4afad60cb4074e538f42605b012c482b946","digest_validated":true,"sign_verified":true}}}},"public_key":{"compressed":"02039c4bfab0762af1aff2fe5596b037f629cf839da8c4a9c0018afedfccf519a6"},"sign":{"r":"915e749f5a780bc21a2b21821cfeb54286dc742e9f12f2387e3de9b8b1a70bc9","s":"1e583236f2630b0fe8e291645ffa35d429f14035182e19868508d4dac0e1a441"}}' ``` </details> ### 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 - 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> get_msg_sha256 "hello world" I (3984) tee_sec_stg: Message digest (SHA256) - b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 esp32c6> tee_sec_stg_sign 7 b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 I (5384) tee_sec_stg: Generated signature - 944684f6ddcf4c268ac6b65e34ccb8d95bd2849567a87867101bc1f09208f0885d935d7b3ba9d46014f28e4c7c988d68c775431fcb2cb2d4ca5c6862db771088 I (6404) tee_sec_stg: Public key (Uncompressed) - 04a515bf1c43766cc34980dd6934b9ff54fd3d5d70fe7a694b1fea7a0bbc74434d008c7c3117ce0a5216ffdb2b807f2668cce9c973d524c038ab47b4344064dbbf I (6444) tee_sec_stg: Signature verified successfully! ``` </details> <details> <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 I (3084) tee_sec_stg: Ciphertext - 58054310a96d48c2dccdf2e34005aa63b40817723d3ec3d597ab362efea084c1 I (3594) tee_sec_stg: Tag - caeedb43e08dc3b4e35a58b2412908cc esp32c6> tee_sec_stg_decrypt 8 58054310a96d48c2dccdf2e34005aa63b40817723d3ec3d597ab362efea084c1 caeedb43e08dc3b4e35a58b2412908cc I (4314) tee_sec_stg: Decrypted plaintext - b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 ``` </details> ### Over-the-Air updates - The TEE/REE OTA service demonstrates the following workflow: 1. Connect to a WiFi network (`wifi_connect` command) 2. Initiate the TEE/REE OTA update, fetching the _new_ application image from the given URL (`tee_ota` and `user_ota` commands) <details> <summary><b>Sample output:</b> <i>wifi_connect</i></summary> ```log esp32c6> wifi_connect myssid mypassword I (498) connect: Connecting to 'myssid' I (498) pp: pp rom version: 5b8dcfa I (508) net80211: net80211 rom version: 5b8dcfa I (518) wifi_init: rx ba win: 6 I (518) wifi_init: tcpip mbox: 32 I (518) wifi_init: udp mbox: 6 I (518) wifi_init: tcp mbox: 6 I (528) wifi_init: tcp tx win: 5760 I (528) wifi_init: tcp rx win: 5760 I (538) wifi_init: tcp mss: 1440 I (538) wifi_init: WiFi IRAM OP enabled I (538) wifi_init: WiFi RX IRAM OP enabled I (548) phy_init: phy_version 290,81efd96,May 8 2024,10:42:13 W (598) wifi:(bf)761:0x600a7cac:0x01b4b4b0 W (598) wifi:(agc)0x600a7128:0xd2173800, min.avgNF:0xce->0xd2(dB), RCalCount:0x173, min.RRssi:0x800(-128.00) W (608) wifi:(TB)WDEV_PWR_TB_MCS0:19 W (608) wifi:(TB)WDEV_PWR_TB_MCS1:19 W (608) wifi:(TB)WDEV_PWR_TB_MCS2:19 W (608) wifi:(TB)WDEV_PWR_TB_MCS3:19 W (618) wifi:(TB)WDEV_PWR_TB_MCS4:19 W (618) wifi:(TB)WDEV_PWR_TB_MCS5:19 W (618) wifi:(TB)WDEV_PWR_TB_MCS6:18 W (628) wifi:(TB)WDEV_PWR_TB_MCS7:18 W (628) wifi:(TB)WDEV_PWR_TB_MCS8:17 W (628) wifi:(TB)WDEV_PWR_TB_MCS9:15 W (648) wifi:(TB)WDEV_PWR_TB_MCS10:15 W (648) wifi:(TB)WDEV_PWR_TB_MCS11:15 W (1328) wifi:<ba-add>idx:0, ifx:0, tid:0, TAHI:0x1008fe0, TALO:0xc7e45510, (ssn:0, win:64, cur_ssn:0), CONF:0xc0000005 I (6358) esp_netif_handlers: sta ip: 192.168.1.30, mask: 255.255.255.0, gw: 192.168.1.1 I (6358) event_handler: got ip:192.168.1.30 I (6368) connect: Connected ``` </details> <details> <summary><b>Sample output:</b> <i>tee_ota</i></summary> ```log esp32c6> tee_ota https://192.168.1.1:4443/esp_tee/esp_tee.bin I (5884) ota_with_tee: Starting TEE OTA... esp32c6> I (1066394) esp-x509-crt-bundle: Certificate validated I (7424) ota_with_tee: esp_tee_ota_begin succeeded I (7904) ota_with_tee: Connection closed I (7904) ota_with_tee: esp_tee_ota_write succeeded I (7904) ota_with_tee: Total binary data written: 118784 I (8064) ota_with_tee: esp_tee_ota_end succeeded I (8064) ota_with_tee: Prepare to restart system! ``` </details> <details> <summary><b>Sample output:</b> <i>user_ota</i></summary> ```log esp32c6> user_ota https://192.168.1.1:4443/tee_cli.bin I (2388) ota_with_tee: Starting User OTA task... I (2388) ota_with_tee: Attempting to download update from https://192.168.1.1:4443/tee_cli.bin I (2438) esp-x509-crt-bundle: Certificate validated esp32c6> I (62888) esp_https_ota: Starting OTA... I (2888) esp_https_ota: Writing to partition subtype 17 at offset 0x1f0000 I (37338) esp_image: segment 0: paddr=001f0020 vaddr=420e0020 size=2ecc0h (191680) map I (37368) esp_image: segment 1: paddr=0021ece8 vaddr=40811000 size=01330h ( 4912) I (37378) esp_image: segment 2: paddr=00220020 vaddr=42020020 size=b88b0h (755888) map I (37518) esp_image: segment 3: paddr=002d88d8 vaddr=40812330 size=14488h ( 83080) I (37538) esp_image: segment 4: paddr=002ecd68 vaddr=408267c0 size=032c0h ( 12992) I (37538) esp_image: segment 5: paddr=002f0030 vaddr=00000000 size=0ffa0h ( 65440) I (37568) esp_image: Verifying image signature... I (37568) secure_boot_v2: Take trusted digest key(s) from eFuse block(s) I (37568) secure_boot_v2: #0 app key digest == #0 trusted key digest I (37578) secure_boot_v2: Verifying with RSA-PSS... I (37638) secure_boot_v2_rsa: Signature verified successfully! I (37648) esp_image: segment 0: paddr=001f0020 vaddr=420e0020 size=2ecc0h (191680) map I (37678) esp_image: segment 1: paddr=0021ece8 vaddr=40811000 size=01330h ( 4912) I (37678) esp_image: segment 2: paddr=00220020 vaddr=42020020 size=b88b0h (755888) map I (37828) esp_image: segment 3: paddr=002d88d8 vaddr=40812330 size=14488h ( 83080) I (37848) esp_image: segment 4: paddr=002ecd68 vaddr=408267c0 size=032c0h ( 12992) I (37848) esp_image: segment 5: paddr=002f0030 vaddr=00000000 size=0ffa0h ( 65440) I (37868) esp_image: Verifying image signature... I (37878) secure_boot_v2: Take trusted digest key(s) from eFuse block(s) I (37878) secure_boot_v2: #0 app key digest == #0 trusted key digest I (37888) secure_boot_v2: Verifying with RSA-PSS... I (37948) secure_boot_v2_rsa: Signature verified successfully! I (37998) ota_with_tee: OTA Succeed, Rebooting... ``` </details> #### Local HTTPS server for hosting OTA images - The script `https_server.py` is a helper script for the OTA service. Executing it with the `python https_server.py` command starts a local HTTPS server with the test certificates from the `test_certs` directory and serves files from the `build` directory that holds the generated binaries for the TEE and REE. Following is the script help - ``` python https_server.py --help usage: https_server.py [-h] [--certfile CERTFILE] [--keyfile KEYFILE] [--port PORT] [--path PATH] Start a local HTTPS server. options: -h, --help show this help message and exit --certfile CERTFILE Path to the SSL certificate file (default: test_certs/server_cert.pem) --keyfile KEYFILE Path to the SSL key file (default: test_certs/server_key.pem) --port PORT Port number to bind the server to (default: 4443) --path PATH Path to the directory to serve files from (default: build directory) E.g., python https_server.py --certfile test_certs/server_cert.pem --keyfile test_certs/server_key.pem --port 8070 --path build ```