Skip to content

Commit

Permalink
feat(esp_tee): Support for ESP-TEE - the main component
Browse files Browse the repository at this point in the history
  • Loading branch information
laukik-hase committed Dec 2, 2024
1 parent 420810e commit 3739306
Show file tree
Hide file tree
Showing 111 changed files with 12,291 additions and 0 deletions.
138 changes: 138 additions & 0 deletions components/esp_tee/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
idf_build_get_property(custom_secure_service_tbl CUSTOM_SECURE_SERVICE_TBL)
idf_build_get_property(custom_secure_service_dir CUSTOM_SECURE_SERVICE_COMPONENT_DIR)
idf_build_get_property(custom_secure_service_component CUSTOM_SECURE_SERVICE_COMPONENT)
idf_build_get_property(target IDF_TARGET)
# headers & sources here are compiled into the app, not the esp_tee binary
# (see subproject/ for the esp_tee binary build files)

# ESP-TEE is currently supported only on the ESP32-C6 SoC
if(NOT ${target} STREQUAL "esp32c6")
return()
endif()

if(BOOTLOADER_BUILD)
idf_component_register()
return()
elseif(esp_tee_build)
# TEE build currently only uses the shared headers.
idf_component_register(INCLUDE_DIRS include)
else()
if(CONFIG_SECURE_ENABLE_TEE)
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
# Add custom flash target for TEE binary
partition_table_get_partition_info(partition "--partition-type app --partition-subtype tee_0" "name")
if(NOT partition)
message(FATAL_ERROR "Partition table missing TEE partition entry!")
endif()
add_dependencies(esp_tee partition_table_bin)
add_dependencies(flash esp_tee)
set(image_file ${TEE_BUILD_DIR}/esp_tee.bin)
partition_table_get_partition_info(offset "--partition-name ${partition}" "offset")
esptool_py_flash_target_image(flash "${partition}" "${offset}" "${image_file}")
endif()

partition_table_get_partition_info(tee_otadata_offset
"--partition-type data --partition-subtype tee_ota" "offset")
partition_table_get_partition_info(tee_otadata_size
"--partition-type data --partition-subtype tee_ota" "size")

# Add custom target for generating empty otadata partition for flashing
if(tee_otadata_offset AND tee_otadata_size)
idf_build_get_property(build_dir BUILD_DIR)
set(blank_tee_otadata_file ${build_dir}/tee_ota_data_initial.bin)

idf_build_get_property(python PYTHON)
idf_component_get_property(partition_table_dir partition_table COMPONENT_DIR)
add_custom_command(OUTPUT ${blank_tee_otadata_file}
COMMAND ${python} ${partition_table_dir}/gen_empty_partition.py
${tee_otadata_size} ${blank_tee_otadata_file})
add_custom_target(blank_tee_ota_data ALL DEPENDS ${blank_tee_otadata_file})

add_dependencies(flash blank_tee_ota_data)
add_dependencies(encrypted-flash blank_tee_ota_data)

partition_table_get_partition_info(tee_otadata_part
"--partition-type data --partition-subtype tee_ota" "name")

idf_component_get_property(main_args esptool_py FLASH_ARGS)
idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
esptool_py_flash_target(tee_otadata-flash "${main_args}" "${sub_args}")

esptool_py_flash_target_image(tee_otadata-flash
"${tee_otadata_part}" "${tee_otadata_offset}" "${blank_tee_otadata_file}")
esptool_py_flash_target_image(flash
"${tee_otadata_part}" "${tee_otadata_offset}" "${blank_tee_otadata_file}")
endif()

set(srcs "src/esp_tee.c"
"src/esp_tee_config.c"
"src/esp_secure_service_wrapper.c"
"src/esp_tee_u2m_switch.S")
endif()

idf_component_register(INCLUDE_DIRS include
SRCS ${srcs}
PRIV_REQUIRES efuse esp_system spi_flash)

if(CONFIG_SECURE_ENABLE_TEE)
set(EXTRA_LINK_FLAGS)
list(APPEND EXTRA_LINK_FLAGS "-u esp_tee_app_config")
target_link_libraries(${COMPONENT_LIB} INTERFACE "${EXTRA_LINK_FLAGS}")
endif()
endif()

set(secure_service_hdr_py
${COMPONENT_DIR}/scripts/secure_service_hdr.py ${CMAKE_CURRENT_BINARY_DIR}/secure_service.tbl
)

set(secure_service_tbl_py
${COMPONENT_DIR}/scripts/secure_service_tbl.py ${CMAKE_CURRENT_BINARY_DIR}/secure_service.tbl
)

set(secure_service_wrap_py
${COMPONENT_DIR}/scripts/secure_service_wrap.py ${CMAKE_CURRENT_BINARY_DIR}/secure_service.tbl
)

set(secure_service_num_h
${CONFIG_DIR}/secure_service_num.h
)
set(secure_service_dec_h
${CONFIG_DIR}/secure_service_dec.h)

set(secure_service_h
${CONFIG_DIR}/secure_service.h
)

if(CONFIG_SECURE_ENABLE_TEE)
execute_process(COMMAND cat ${COMPONENT_DIR}/scripts/${target}/secure_service.tbl ${custom_secure_service_tbl}
OUTPUT_FILE secure_service.tbl
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)

execute_process(COMMAND python ${secure_service_hdr_py} ${secure_service_num_h} ${secure_service_dec_h}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)

execute_process(COMMAND python ${secure_service_tbl_py} ${secure_service_h}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)

set_property(DIRECTORY "${COMPONENT_DIR}" APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES ${secure_service_num_h} ${secure_service_dec_h} ${secure_service_h})

# For TEE implementation, we don't wrap the APIs since the TEE would also internally use the same API and
# it shouldn't route to secure service API.
# Instead of wrapping, we append _ss_* to the API name and then it must be defined in esp_secure_services.c
if(NOT esp_tee_build)
execute_process(COMMAND python ${secure_service_wrap_py}
OUTPUT_VARIABLE wrap_list
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
OUTPUT_STRIP_TRAILING_WHITESPACE
)

string(STRIP ${wrap_list} wrap_list)

target_link_libraries(${COMPONENT_LIB} INTERFACE "${wrap_list}")
endif()
endif()
144 changes: 144 additions & 0 deletions components/esp_tee/Kconfig.projbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
menu "ESP-TEE (Trusted Execution Environment)"
depends on IDF_TARGET_ESP32C6

config SECURE_ENABLE_TEE
bool "Enable the ESP-TEE framework"
depends on IDF_TARGET_ESP32C6
select ESP_SYSTEM_MEMPROT_FEATURE_VIA_TEE
help
This configuration enables the Trusted Execution Environment (TEE) feature.

menu "Memory Configuration"
depends on SECURE_ENABLE_TEE

config SECURE_TEE_IRAM_SIZE
hex "IRAM region size"
default 0x8000
range 0x8000 0x10000
help
This configuration sets the IRAM size for the TEE module.
This should be a multiple of 0x1000.

config SECURE_TEE_DRAM_SIZE
hex "DRAM region size"
default 0x8000
range 0x8000 0x10000
help
This configuration sets the DRAM size for the TEE module.
This should be a multiple of 0x1000.

config SECURE_TEE_STACK_SIZE
hex "Stack size"
default 0xc00
range 0x800 0x1000
help
This configuration sets the stack size for the TEE module.
The TEE stack will be allocated from the TEE DRAM region.
This should be a multiple of 0x100.

config SECURE_TEE_INTR_STACK_SIZE
hex "Interrupt Stack size"
default 0x400
range 0x400 0x800
help
This configuration sets the interrupt stack size for the TEE module.
The TEE interrupt stack will be allocated from the TEE DRAM region.
This should be a multiple of 0x100.

config SECURE_TEE_IROM_SIZE
hex
default 0x10000
help
This should be a multiple of MMU_PAGE_SIZE.

config SECURE_TEE_DROM_SIZE
hex
default 0x10000
help
This should be a multiple of MMU_PAGE_SIZE.

endmenu

choice SECURE_TEE_SEC_STG_MODE
prompt "Secure Storage: Mode"
depends on SECURE_ENABLE_TEE
default SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
help
Select the TEE secure storage mode

config SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
bool "Development"
help
Secure storage will be encrypted by the data stored in eFuse BLK2

config SECURE_TEE_SEC_STG_MODE_RELEASE
depends on IDF_TARGET_ESP32C6
bool "Release"
help
Secure storage will be encrypted by the data stored in eFuse block
configured through the SECURE_TEE_SEC_STG_KEY_EFUSE_BLK option

endchoice

config SECURE_TEE_SEC_STG_KEY_EFUSE_BLK
int "Secure Storage: Encryption key eFuse block"
depends on SECURE_TEE_SEC_STG_MODE_RELEASE
range 4 10
default 10
help
eFuse block ID storing the TEE secure storage encryption key

config SECURE_TEE_ATT_KEY_SLOT_ID
depends on SECURE_ENABLE_TEE
int "Attestation: Secure Storage slot ID for EAT signing"
default 0
range 0 14
help
This configuration sets the slot ID from the TEE secure storage
storing the ECDSA keypair for executing sign/verify operations
from the TEE side (E.g. Attestation)

config SECURE_TEE_DEBUG_MODE
bool "Enable Debug Mode"
default y
depends on SECURE_ENABLE_TEE
help
This configuration enables the logging from the TEE module.

choice SECURE_TEE_LOG_LEVEL
bool "Log verbosity"
default SECURE_TEE_LOG_LEVEL_WARN
depends on SECURE_TEE_DEBUG_MODE
help
Specify how much output to see in TEE logs.

config SECURE_TEE_LOG_LEVEL_NONE
bool "No output"
config SECURE_TEE_LOG_LEVEL_ERROR
bool "Error"
config SECURE_TEE_LOG_LEVEL_WARN
bool "Warning"
config SECURE_TEE_LOG_LEVEL_INFO
bool "Info"
config SECURE_TEE_LOG_LEVEL_DEBUG
bool "Debug"
config SECURE_TEE_LOG_LEVEL_VERBOSE
bool "Verbose"
endchoice

config SECURE_TEE_LOG_LEVEL
int
default 0 if SECURE_TEE_LOG_LEVEL_NONE || !SECURE_TEE_DEBUG_MODE
default 1 if SECURE_TEE_LOG_LEVEL_ERROR
default 2 if SECURE_TEE_LOG_LEVEL_WARN
default 3 if SECURE_TEE_LOG_LEVEL_INFO
default 4 if SECURE_TEE_LOG_LEVEL_DEBUG
default 5 if SECURE_TEE_LOG_LEVEL_VERBOSE

config SECURE_TEE_TEST_MODE
bool "Enable Test Mode"
depends on SECURE_ENABLE_TEE
help
This configuration sets up the TEE framework as required for executing the test suite.

endmenu
90 changes: 90 additions & 0 deletions components/esp_tee/include/esp_tee.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#ifndef __ASSEMBLER__
#include <stdint.h>
#include <stdio.h>
#include <stddef.h>
#include "soc/soc.h"
#include "sdkconfig.h"
#include "esp_cpu.h"
#include "esp_attr.h"

#include "riscv/rv_utils.h"

#define ESP_TEE_APP_CFG_MAGIC 0x3348AAED

#define ESP_TEE_API_MAJOR_VER 1
#define ESP_TEE_API_MINOR_VER 0
#define ESP_TEE_API_PATCH_VER 0

/**
* @brief CPU privilege mode
*/
typedef enum {
ESP_CPU_NS_MODE = 0, /* Corresponds to the RISC-V User (U) mode */
ESP_CPU_S_MODE = 3, /* Corresponds to the RISC-V Machine (M) mode */
} esp_cpu_priv_mode_t;

/**
* @brief Configuration structure defining the interface between TEE and REE (user) app
*
* This configuration structure is embedded in the REE (user) app's IRAM section.
* The TEE reads and updates this structure before switching to the REE, and then
* write-protects it.
*
* @note All accesses to this structure must be 32-bit aligned since it resides in
* the (user app) IRAM section.
*/
typedef struct {
uint32_t magic_word;
uint32_t api_major_version;
uint32_t api_minor_version;
uint32_t reserved[2];
/* TEE-related fields */
void *s_entry_addr;
void *s_int_handler;
/* REE-related fields */
void *ns_entry_addr;
void *ns_int_handler;
void *ns_iram_end;
void *ns_irom_end;
void *ns_drom_end;
} __attribute__((aligned(4))) __attribute__((__packed__)) esp_tee_config_t;

extern esp_tee_config_t esp_tee_app_config;

#endif // ifndef __ASSEMBLER__

#if !ESP_TEE_BUILD
#include "private/esp_tee_app.h"
#else
#include "private/esp_tee_binary.h"
#endif

/* Offsets of some values in esp_tee_config_t that are used by assembly code */
#define ESP_TEE_CFG_OFFS_S_ENTRY_ADDR 0x14
#define ESP_TEE_CFG_OFFS_S_INTR_HANDLER 0x18
#define ESP_TEE_CFG_OFFS_NS_ENTRY_ADDR 0x1C
#define ESP_TEE_CFG_OFFS_NS_INTR_HANDLER 0x20

#ifndef __ASSEMBLER__
/* Check the offsets are correct using the C compiler */
ESP_STATIC_ASSERT(offsetof(esp_tee_config_t, s_entry_addr) == ESP_TEE_CFG_OFFS_S_ENTRY_ADDR, "offset macro is wrong");
ESP_STATIC_ASSERT(offsetof(esp_tee_config_t, s_int_handler) == ESP_TEE_CFG_OFFS_S_INTR_HANDLER, "offset macro is wrong");
ESP_STATIC_ASSERT(offsetof(esp_tee_config_t, ns_entry_addr) == ESP_TEE_CFG_OFFS_NS_ENTRY_ADDR, "offset macro is wrong");
ESP_STATIC_ASSERT(offsetof(esp_tee_config_t, ns_int_handler) == ESP_TEE_CFG_OFFS_NS_INTR_HANDLER, "offset macro is wrong");
#endif // ifndef __ASSEMBLER__

#ifdef __cplusplus
}
#endif
Loading

0 comments on commit 3739306

Please sign in to comment.