chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:04:25 +08:00
commit 548b49ebc0
20937 changed files with 5455372 additions and 0 deletions
@@ -0,0 +1,12 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.22)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# For registering custom secure services for the example
include(${CMAKE_CURRENT_LIST_DIR}/components/example_secure_service/tee_project.cmake)
# "Trim" the build. Include the minimal set of components, main, and anything it depends on.
idf_build_set_property(MINIMAL_BUILD ON)
project(tee_basic)
+57
View File
@@ -0,0 +1,57 @@
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 |
| ----------------- | -------- | -------- | --------- | -------- |
# Basic TEE example
## Overview
- This example illustrates the ESP-TEE (Trusted Execution Environment) framework to encrypt/decrypt data using AES within a secure environment.
- The non-secure world i.e. the Rich Execution Environment (REE) raises a request for AES operation in TEE through the secure service call interface. The TEE performs encrypts/decrypts the given buffer with the AES-256-GCM mode using the key protected by TEE. If the operation is successful, the result of the AES operation is returned in the output buffer provided in the secure service call by the REE.
- This example also demonstrates how to add custom service calls to TEE. You can refer to `components/example_service` for more information - see the structure below.
```
└── example_secure_service # Component parent directory
├── CMakeLists.txt
├── example_service.c # Custom secure service APIs
├── sec_srv_tbl_example.yml # Custom secure service table, which is parsed alongwith the default one provided by TEE
├── include
│   └── example_service.h
└── tee_project.cmake # To be manually included in the project's top level CMakeLists.txt before project(...)
# Processes the custom service table
```
## How to use the example
### 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).
### Build and Flash
Before building the example, be sure to set the correct chip target using idf.py set-target <chip_name>.
Build the project and flash it to the board, then run the monitor tool to view the serial output:
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type `Ctrl-]`.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
### Example Output
```log
I (353) main_task: Calling app_main()
I (353) example_tee_basic: AES-256-GCM operations in TEE
I (364) example_tee_service: Secure service call: PROTECTED M-mode
I (370) example_tee_service: AES-256-GCM encryption
I (373) ciphertext: 23 32 a6 1f ff 27 15 d7 35 70 db f5 e3 0c 13 41
I (373) ciphertext: eb 80 d7 2c 9c f5 68 5a b4 2c 43 b0 64 68 13 36
I (383) tag: f8 85 ab 3b 47 a6 65 0d 0a 42 bd 3d
I (391) example_tee_service: Secure service call: PROTECTED M-mode
I (397) example_tee_service: AES-256-GCM decryption
I (393) example_tee_basic: AES-GCM decryption successful!
I (403) main_task: Returned from app_main()
```
@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.22)
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
set(srcs)
set(include_dirs include)
if(esp_tee_build)
list(APPEND srcs "example_service.c")
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs}
PRIV_REQUIRES main)
@@ -0,0 +1,125 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "esp_cpu.h"
#include "esp_err.h"
#include "esp_log.h"
#include "psa/crypto.h"
#include "esp_tee.h"
#include "secure_service_num.h"
#include "example_service.h"
#define AES256_KEY_LEN 32
#define AES256_KEY_BITS (AES256_KEY_LEN * 8)
#define AES256_NONCE_LEN 12
static const char *TAG = "tee_secure_service";
/* Fixed key (only for example purposes) */
static const uint8_t key[AES256_KEY_LEN] = {[0 ... AES256_KEY_LEN - 1] = 0xA5};
/* Fixed nonce (only for example purposes) */
static const uint8_t nonce[AES256_NONCE_LEN] = {[0 ... AES256_NONCE_LEN - 1] = 0x5A};
static esp_err_t aes_gcm_crypt_common(example_aes_gcm_ctx_t *ctx, uint8_t *tag, size_t tag_len,
uint8_t *output, bool is_encrypt)
{
if (esp_cpu_get_curr_privilege_level() != ESP_CPU_S_MODE) {
ESP_LOGE(TAG, "Operation executing from illegal privilege level!");
return ESP_ERR_INVALID_STATE;
}
if (ctx == NULL || ctx->input == NULL || output == NULL || tag == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (ctx->input_len == 0 || tag_len == 0) {
return ESP_ERR_INVALID_ARG;
}
ESP_LOGI(TAG, "Secure service call: PROTECTED M-mode");
ESP_LOGI(TAG, "AES-256-GCM %s", is_encrypt ? "encryption" : "decryption");
esp_err_t err = ESP_FAIL;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
psa_status_t status;
psa_key_id_t key_id;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_algorithm_t alg = PSA_ALG_GCM;
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&key_attributes, alg);
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&key_attributes, AES256_KEY_BITS);
status = psa_import_key(&key_attributes, key, sizeof(key), &key_id);
psa_reset_key_attributes(&key_attributes);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in importing key: %d", status);
return ESP_ERR_INVALID_STATE;
}
if (is_encrypt) {
status = psa_aead_encrypt_setup(&operation, key_id, alg);
} else {
status = psa_aead_decrypt_setup(&operation, key_id, alg);
}
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in AEAD setup: %d", status);
goto cleanup;
}
status = psa_aead_set_lengths(&operation, ctx->aad_len, ctx->input_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in setting lengths: %d", status);
goto cleanup;
}
psa_aead_set_nonce(&operation, nonce, AES256_NONCE_LEN);
if (ctx->aad_len > 0) {
status = psa_aead_update_ad(&operation, ctx->aad, ctx->aad_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in updating AAD: %d", status);
goto cleanup;
}
}
size_t output_len = 0;
status = psa_aead_update(&operation, ctx->input, ctx->input_len, output, ctx->input_len, &output_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in updating aead: %d", status);
goto cleanup;
}
if (is_encrypt) {
size_t output_tag_len = 0;
status = psa_aead_finish(&operation, output + output_len, ctx->input_len + tag_len - output_len, &output_len, tag, tag_len, &output_tag_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in finishing encryption: %d", status);
goto cleanup;
}
} else {
size_t plaintext_len = 0;
status = psa_aead_verify(&operation, output, ctx->input_len, &plaintext_len, tag, tag_len);
if (status != PSA_SUCCESS) {
ESP_LOGE(TAG, "Error in verifying decryption: %d", status);
goto cleanup;
}
}
err = ESP_OK;
cleanup:
psa_aead_abort(&operation);
psa_destroy_key(key_id);
return err;
}
esp_err_t _ss_example_sec_serv_aes_gcm_encrypt(example_aes_gcm_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output)
{
return aes_gcm_crypt_common(ctx, tag, tag_len, output, true);
}
esp_err_t _ss_example_sec_serv_aes_gcm_decrypt(example_aes_gcm_ctx_t *ctx, const uint8_t *tag, size_t tag_len, uint8_t *output)
{
return aes_gcm_crypt_common(ctx, (uint8_t *)tag, tag_len, output, false);
}
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "esp_err.h"
typedef struct {
const uint8_t *aad; /*!< Additional authenticated data */
size_t aad_len; /*!< Length of additional authenticated data */
const uint8_t *input; /*!< Input data buffer */
size_t input_len; /*!< Length of input data */
} example_aes_gcm_ctx_t;
esp_err_t example_sec_serv_aes_gcm_encrypt(example_aes_gcm_ctx_t *ctx, uint8_t *tag, size_t tag_len, uint8_t *output);
esp_err_t example_sec_serv_aes_gcm_decrypt(example_aes_gcm_ctx_t *ctx, const uint8_t *tag, size_t tag_len, uint8_t *output);
@@ -0,0 +1,11 @@
secure_services:
- family: example
entries:
- id: 200
type: custom
function: example_sec_serv_aes_gcm_encrypt
args: 4
- id: 201
type: custom
function: example_sec_serv_aes_gcm_decrypt
args: 4
@@ -0,0 +1,15 @@
# This file must be manually included in the project's top level CMakeLists.txt before project()
# This ensures that the variables are set before TEE starts building
get_filename_component(directory "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE DIRECTORY)
get_filename_component(name ${CMAKE_CURRENT_LIST_DIR} NAME)
# Append secure service table consisting of secure services
idf_build_set_property(CUSTOM_SECURE_SERVICE_YAML ${CMAKE_CURRENT_LIST_DIR}/sec_srv_tbl_example.yml APPEND)
# Append the directory of this component which is used by esp_tee component as
# EXTRA_COMPONENT_DIRS
idf_build_set_property(CUSTOM_SECURE_SERVICE_COMPONENT_DIR ${directory} APPEND)
# Append the name of the component so that esp_tee can include it in its COMPONENTS list
idf_build_set_property(CUSTOM_SECURE_SERVICE_COMPONENT ${name} APPEND)
@@ -0,0 +1,3 @@
idf_component_register(SRCS "tee_main.c"
INCLUDE_DIRS ""
PRIV_REQUIRES esp_tee mbedtls example_secure_service)
@@ -0,0 +1,81 @@
/* ESP-TEE (Trusted Execution Environment) Example
*
* SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "esp_log.h"
#include "esp_err.h"
#include "esp_random.h"
#include "esp_tee.h"
#include "secure_service_num.h"
#include "example_service.h"
#define EXAMPLE_BUF_SZ (32)
#define AES256_GCM_TAG_LEN (16)
#define AES256_GCM_AAD_LEN (16)
static const char *TAG = "example_tee_basic";
/*
* Example workflow:
* 1. The REE generates random plaintext and AAD (Additional Authenticated Data)
* 2. The REE initiates an AES-256-GCM encryption request and provides output buffers
* for ciphertext and authentication tag
* 3. The TEE receives the request and performs encryption using a protected key and
* nonce that are only accessible within the secure environment
* 4. The encrypted ciphertext and authentication tag are returned to the REE
* 5. The REE initiates a decryption request with the ciphertext and authentication tag
* 6. The TEE performs authenticated decryption, verifying the tag and returning the plaintext
* 7. The REE verifies that the decrypted data matches the original plaintext
*/
void app_main(void)
{
ESP_LOGI(TAG, "AES-256-GCM operations in TEE");
uint8_t plain_text[EXAMPLE_BUF_SZ];
uint8_t cipher_text[EXAMPLE_BUF_SZ] = {0};
uint8_t decrypted_text[EXAMPLE_BUF_SZ] = {0};
uint8_t tag[AES256_GCM_TAG_LEN] = {0};
uint8_t aad_buf[AES256_GCM_AAD_LEN];
/* Generate random plaintext and AAD */
esp_fill_random(plain_text, sizeof(EXAMPLE_BUF_SZ));
esp_fill_random(aad_buf, AES256_GCM_AAD_LEN);
/* Encryption operation */
example_aes_gcm_ctx_t enc_ctx = {
.aad = aad_buf,
.aad_len = sizeof(aad_buf),
.input = plain_text,
.input_len = sizeof(plain_text),
};
uint32_t ret = esp_tee_service_call(5, SS_EXAMPLE_SEC_SERV_AES_GCM_ENCRYPT, &enc_ctx, tag, AES256_GCM_TAG_LEN, cipher_text);
ESP_ERROR_CHECK((esp_err_t)ret);
ESP_LOG_BUFFER_HEX_LEVEL("ciphertext", cipher_text, sizeof(cipher_text), ESP_LOG_INFO);
ESP_LOG_BUFFER_HEX_LEVEL("tag", tag, AES256_GCM_TAG_LEN, ESP_LOG_INFO);
/* Decryption operation */
example_aes_gcm_ctx_t dec_ctx = {
.aad = aad_buf,
.aad_len = sizeof(aad_buf),
.input = cipher_text,
.input_len = sizeof(cipher_text),
};
ret = esp_tee_service_call(5, SS_EXAMPLE_SEC_SERV_AES_GCM_DECRYPT, &dec_ctx, tag, AES256_GCM_TAG_LEN, decrypted_text);
ESP_ERROR_CHECK((esp_err_t)ret);
if (memcmp(decrypted_text, plain_text, sizeof(plain_text)) != 0) {
ESP_LOGE(TAG, "Decrypted data mismatch!");
} else {
ESP_LOGI(TAG, "AES-GCM decryption successful!");
}
}
@@ -0,0 +1,32 @@
# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Unlicense OR CC0-1.0
import logging
import os
import pytest
from pytest_embedded import Dut
from pytest_embedded_idf.utils import idf_parametrize
TESTING_TARGETS = ['esp32c6', 'esp32h2', 'esp32c5', 'esp32c61']
@pytest.mark.generic
@idf_parametrize('target', TESTING_TARGETS, indirect=['target'])
def test_example_tee_basic(dut: Dut) -> None:
# Logging example binary details
binary_files = [
('tee_basic.bin', '[REE] tee_basic_bin_size'),
('esp_tee/esp_tee.bin', '[TEE] tee_basic_bin_size'),
]
for file_name, log_label in binary_files:
binary_file = os.path.join(dut.app.binary_path, file_name)
bin_size = os.path.getsize(binary_file)
logging.info(f'{log_label}: {bin_size // 1024}KB')
# Start test
dut.expect('AES-256-GCM operations in TEE', timeout=10)
dut.expect('Secure service call: PROTECTED M-mode', timeout=10)
dut.expect('AES-256-GCM encryption', timeout=10)
dut.expect('Secure service call: PROTECTED M-mode', timeout=10)
dut.expect('AES-256-GCM decryption', timeout=10)
dut.expect('Returned from app_main()', timeout=10)
@@ -0,0 +1,7 @@
# Enabling TEE
CONFIG_SECURE_ENABLE_TEE=y
CONFIG_SECURE_TEE_LOG_LEVEL_INFO=y
CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y
CONFIG_SECURE_TEE_ATTESTATION=n
CONFIG_MBEDTLS_TEE_SEC_STG_ECDSA_SIGN=n
CONFIG_SECURE_TEE_IRAM_SIZE=0xC000