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 <chip_name>.

  • 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.
      # 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:
# Replace PORT with the name of the serial port to use
idf.py -p <PORT> 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.

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=<t>] <ssid> [<pass>]
  Join WiFi AP as a station
  --timeout=<t>  Connection timeout, ms
        <ssid>  SSID of AP
        <pass>  PSK of AP

tee_ota  <url>
  Initiate TEE app OTA
         <url>  URL for fetching the update

user_ota  <url>
  Initiate User app OTA
         <url>  URL for fetching the update

tee_att_info
  Dump the TEE-generated entity attestation token

get_msg_sha256  "<msg>"
  Get the SHA256 digest for the given message
       "<msg>"  Message for SHA256 digest calculation

tee_sec_stg_gen_key  <slot_id> <key_type>
  Generate and store a new key of the specified type in the given TEE secure
  storage slot
     <slot_id>  TEE Secure storage slot for storing the key
    <key_type>  Key type (0: ECDSA_SECP256R1, 1: AES256)

tee_sec_stg_sign  <slot_id> <msg_sha256>
  Sign a message using the ECDSA keypair stored in the given slot ID and verify
  the signature
     <slot_id>  TEE Secure storage slot storing the ecdsa-secp256r1 keypair
  <msg_sha256>  SHA256 digest of the message to be signed and verified

tee_sec_stg_encrypt  <slot_id> <plaintext>
  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.
Sample output: tee_att_info
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"}}'

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.
Sample output: tee_sec_stg_gen_key + get_msg_sha256 + tee_sec_stg_sign
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!
Sample output: tee_sec_stg_gen_key + tee_sec_stg_encrypt + tee_sec_stg_decrypt
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

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)
Sample output: wifi_connect
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
Sample output: tee_ota
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!
Sample output: user_ota
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...

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