Merge branch 'feature/esp_tee_cfg_srv' into 'master'

feat(esp_tee): Make the attestation service K-configurable

See merge request espressif/esp-idf!36123
This commit is contained in:
Mahavir Jain
2025-01-27 19:20:09 +08:00
29 changed files with 462 additions and 422 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -22,6 +22,10 @@
#include "esp_err.h" #include "esp_err.h"
#include "esp_attr.h" #include "esp_attr.h"
#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
#include "secure_service_num.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -452,9 +456,9 @@ FORCE_INLINE_ATTR void esp_cpu_intr_edge_ack(int intr_num)
#ifdef __XTENSA__ #ifdef __XTENSA__
xthal_set_intclear((unsigned) (1 << intr_num)); xthal_set_intclear((unsigned) (1 << intr_num));
#else #else
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb; extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb;
esp_tee_intr_sec_srv_cb(2, TEE_INTR_EDGE_ACK_SRV_ID, intr_num); esp_tee_intr_sec_srv_cb(2, SS_RV_UTILS_INTR_EDGE_ACK, intr_num);
#else #else
rv_utils_intr_edge_ack((unsigned) intr_num); rv_utils_intr_edge_ack((unsigned) intr_num);
#endif #endif

View File

@@ -82,57 +82,38 @@ else()
endif() endif()
endif() endif()
set(secure_service_hdr_py set(secure_service_tbl_parser_py
${COMPONENT_DIR}/scripts/secure_service_hdr.py ${CMAKE_CURRENT_BINARY_DIR}/secure_service.tbl ${COMPONENT_DIR}/scripts/secure_service_tbl_parser.py ${CMAKE_CURRENT_BINARY_DIR}/secure_service.tbl
) )
set(secure_service_tbl_py set(secure_service_gen_headers
${COMPONENT_DIR}/scripts/secure_service_tbl.py ${CMAKE_CURRENT_BINARY_DIR}/secure_service.tbl ${CONFIG_DIR}/secure_service_num.h ${CONFIG_DIR}/secure_service_dec.h
) ${CONFIG_DIR}/secure_service_int.h ${CONFIG_DIR}/secure_service_ext.h
)
set(secure_service_wrap_py if(CONFIG_SECURE_ENABLE_TEE AND NOT esp_tee_build)
${COMPONENT_DIR}/scripts/secure_service_wrap.py ${CMAKE_CURRENT_BINARY_DIR}/secure_service.tbl execute_process(
) COMMAND cat ${COMPONENT_DIR}/scripts/${target}/secure_service.tbl ${custom_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 OUTPUT_FILE secure_service.tbl
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
) )
execute_process(COMMAND python ${secure_service_hdr_py} ${secure_service_num_h} ${secure_service_dec_h} execute_process(
COMMAND python ${secure_service_tbl_parser_py} ${secure_service_gen_headers}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
) )
execute_process(COMMAND python ${secure_service_tbl_py} ${secure_service_h} set_property(DIRECTORY ${COMPONENT_DIR} APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES ${secure_service_gen_headers}
)
execute_process(
COMMAND python ${secure_service_tbl_parser_py} "--wrap"
OUTPUT_VARIABLE wrap_list
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
) OUTPUT_STRIP_TRAILING_WHITESPACE
)
set_property(DIRECTORY "${COMPONENT_DIR}" APPEND PROPERTY string(STRIP "${wrap_list}" wrap_list)
ADDITIONAL_MAKE_CLEAN_FILES ${secure_service_num_h} ${secure_service_dec_h} ${secure_service_h}) target_link_libraries(${COMPONENT_LIB} INTERFACE "${wrap_list}")
# 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() endif()

View File

@@ -59,44 +59,56 @@ menu "ESP-TEE (Trusted Execution Environment)"
endmenu endmenu
choice SECURE_TEE_SEC_STG_MODE menu "Secure Services"
prompt "Secure Storage: Mode"
depends on SECURE_ENABLE_TEE 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 choice SECURE_TEE_SEC_STG_MODE
bool "Development" prompt "Secure Storage: Mode"
depends on SECURE_ENABLE_TEE
default SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
help help
Secure storage will be encrypted by the data stored in eFuse BLK2 Select the TEE secure storage mode
config SECURE_TEE_SEC_STG_MODE_RELEASE config SECURE_TEE_SEC_STG_MODE_DEVELOPMENT
depends on IDF_TARGET_ESP32C6 bool "Development"
bool "Release" 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 help
Secure storage will be encrypted by the data stored in eFuse block eFuse block ID storing the TEE secure storage encryption key
configured through the SECURE_TEE_SEC_STG_KEY_EFUSE_BLK option
endchoice config SECURE_TEE_ATTESTATION
bool "Enable Attestation"
default y
help
This configuration enables the support for the Attestation service.
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 config SECURE_TEE_ATT_KEY_SLOT_ID
depends on SECURE_ENABLE_TEE depends on SECURE_TEE_ATTESTATION
int "Attestation: Secure Storage slot ID for EAT signing" int "Attestation: Secure Storage slot ID for EAT signing"
default 0 default 0
range 0 14 range 0 14
help help
This configuration sets the slot ID from the TEE secure storage This configuration sets the slot ID from the TEE secure storage
storing the ECDSA keypair for executing sign/verify operations storing the ECDSA keypair for executing sign/verify operations
from the TEE side (E.g. Attestation) from the TEE side for attestation.
endmenu
config SECURE_TEE_DEBUG_MODE config SECURE_TEE_DEBUG_MODE
bool "Enable Debug Mode" bool "Enable Debug Mode"

View File

@@ -1,46 +1,56 @@
# SS no. API type Function Args # SS no. API type Function Args
0 custom invalid_secure_service 0 0 custom invalid_secure_service 0
1 IDF esp_rom_route_intr_matrix 3 # ID: 1-47 (47) - External memory (Flash) protection
2 IDF rv_utils_intr_enable 1 1 IDF mmu_hal_map_region 6
3 IDF rv_utils_intr_disable 1 2 IDF mmu_hal_unmap_region 3
4 IDF rv_utils_intr_set_priority 2 3 IDF mmu_hal_vaddr_to_paddr 4
5 IDF rv_utils_intr_set_type 2 4 IDF mmu_hal_paddr_to_vaddr 5
6 IDF rv_utils_intr_set_threshold 1 # Services before the ID 48 will be placed in the internal memory table,
7 IDF rv_utils_intr_edge_ack 1 # while the rest will be placed in the external memory table.
8 IDF rv_utils_intr_global_enable 0 # ID: 48-71 (24) - Interrupt Handling
9 IDF efuse_hal_chip_revision 0 48 IDF esp_rom_route_intr_matrix 3
10 IDF efuse_hal_get_chip_ver_pkg 1 49 IDF rv_utils_intr_enable 1
11 IDF efuse_hal_get_disable_wafer_version_major 0 50 IDF rv_utils_intr_disable 1
12 IDF efuse_hal_get_mac 1 51 IDF rv_utils_intr_set_priority 2
13 IDF esp_efuse_check_secure_version 1 52 IDF rv_utils_intr_set_type 2
14 IDF esp_efuse_read_field_blob 3 53 IDF rv_utils_intr_set_threshold 1
15 IDF esp_flash_encryption_enabled 0 54 IDF rv_utils_intr_edge_ack 1
16 IDF wdt_hal_init 4 55 IDF rv_utils_intr_global_enable 0
17 IDF wdt_hal_deinit 1 # ID: 72-119 (48) - HAL
18 IDF esp_aes_intr_alloc 0 72 IDF efuse_hal_chip_revision 0
19 IDF esp_aes_crypt_cbc 6 73 IDF efuse_hal_get_chip_ver_pkg 1
20 IDF esp_aes_crypt_cfb8 6 74 IDF efuse_hal_get_disable_wafer_version_major 0
21 IDF esp_aes_crypt_cfb128 7 75 IDF efuse_hal_get_mac 1
22 IDF esp_aes_crypt_ctr 7 76 IDF wdt_hal_init 4
23 IDF esp_aes_crypt_ecb 4 77 IDF wdt_hal_deinit 1
24 IDF esp_aes_crypt_ofb 6 # ID: 120-167 (48) - Crypto
25 IDF esp_sha 4 120 IDF esp_aes_intr_alloc 0
26 IDF esp_sha_dma 6 121 IDF esp_aes_crypt_cbc 6
27 IDF esp_sha_read_digest_state 2 122 IDF esp_aes_crypt_cfb8 6
28 IDF esp_sha_write_digest_state 2 123 IDF esp_aes_crypt_cfb128 7
29 IDF mmu_hal_map_region 6 124 IDF esp_aes_crypt_ctr 7
30 IDF mmu_hal_unmap_region 3 125 IDF esp_aes_crypt_ecb 4
31 IDF mmu_hal_vaddr_to_paddr 4 126 IDF esp_aes_crypt_ofb 6
32 IDF mmu_hal_paddr_to_vaddr 5 127 IDF esp_sha 4
33 custom esp_tee_ota_begin 0 128 IDF esp_sha_dma 6
34 custom esp_tee_ota_write 3 129 IDF esp_sha_read_digest_state 2
35 custom esp_tee_ota_end 0 130 IDF esp_sha_write_digest_state 2
36 custom esp_tee_sec_storage_init 0 # ID: 168-183 (16) - eFuse
37 custom esp_tee_sec_storage_gen_key 1 168 IDF esp_efuse_check_secure_version 1
38 custom esp_tee_sec_storage_get_signature 4 169 IDF esp_efuse_read_field_blob 3
39 custom esp_tee_sec_storage_get_pubkey 2 170 IDF esp_flash_encryption_enabled 0
40 custom esp_tee_sec_storage_encrypt 8 # ID: 184-249 (66) - Reserved for future use
41 custom esp_tee_sec_storage_decrypt 8 # ID: 270-293 (24) - Secure Storage
42 custom esp_tee_sec_storage_is_slot_empty 1 270 custom esp_tee_sec_storage_init 0
43 custom esp_tee_sec_storage_clear_slot 1 271 custom esp_tee_sec_storage_gen_key 2
44 custom esp_tee_att_generate_token 6 272 custom esp_tee_sec_storage_get_signature 4
273 custom esp_tee_sec_storage_get_pubkey 2
274 custom esp_tee_sec_storage_encrypt 8
275 custom esp_tee_sec_storage_decrypt 8
276 custom esp_tee_sec_storage_is_slot_empty 1
277 custom esp_tee_sec_storage_clear_slot 1
# ID: 294-299 (6) - OTA
294 custom esp_tee_ota_begin 0
295 custom esp_tee_ota_write 3
296 custom esp_tee_ota_end 0
# ID: 300+ - User-defined

View File

@@ -1,76 +0,0 @@
#!/usr/bin/env python
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import argparse
import re
from typing import List
from typing import Tuple
def parse_services(secure_service_tbl: str) -> List[Tuple[str, str, str]]:
services: List[Tuple[str, str, str]] = []
pattern: re.Pattern = re.compile(r'^([0-9A-Fa-fXx]+)\s+\S+\s+(\S+)\s+(\d+)')
with open(secure_service_tbl, 'r') as f:
for line in f:
if match := pattern.match(line):
services.append((match.group(1), match.group(2), match.group(3)))
return sorted(services, key=lambda x: int(x[0]))
def generate_num_header(services: List[Tuple[str, str, str]], output_file: str) -> None:
header_text: str = '''/**
* This header file is used to generate secure service number macros.
*
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT!
*/
#pragma once
'''
with open(output_file, 'w') as f:
f.write(header_text)
for nr, name, _ in services:
f.write(f'#define SS_{name.upper()}\t{nr}\n')
total: int = int(services[-1][0]) + 1 if services else 0
f.write(f'\n#define MAX_SECURE_SERVICES\t{total}\n\n')
def generate_dec_header(services: List[Tuple[str, str, str]], output_file: str) -> None:
header_text: str = '''/**
* This header file is used to provide function declarations
* for compiling secure_service_table.c source file. Please do not
* use it in application.
*
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT!
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
'''
with open(output_file, 'w') as f:
f.write(header_text)
for _, name, _ in services:
f.write(f'void _ss_{name}(void);\n')
f.write('''
#ifdef __cplusplus
}
#endif
''')
def main() -> None:
parser = argparse.ArgumentParser(description='Generate secure service headers')
parser.add_argument('secure_service_tbl', type=str, help='Path to secure_service.tbl generated in build directory')
parser.add_argument('secure_service_num_h', type=str, help='Path to secure_service_num.h header file')
parser.add_argument('secure_service_dec_h', type=str, help='Path to secure_service_dec.h header file')
args = parser.parse_args()
services: List[Tuple[str, str, str]] = parse_services(args.secure_service_tbl)
generate_num_header(services, args.secure_service_num_h)
generate_dec_header(services, args.secure_service_dec_h)
if __name__ == '__main__':
main()

View File

@@ -1,50 +0,0 @@
#!/usr/bin/env python
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import argparse
import re
import sys
from typing import Dict
from typing import Tuple
def emit(nr: int, entry: str, nargs: str) -> str:
return f'__SECURE_SERVICE({nr}, {entry}, {nargs})'
def main() -> None:
parser = argparse.ArgumentParser(description='Generate secure service table')
parser.add_argument('input_file', type=str, help='Path to input file')
parser.add_argument('output_file', type=str, help='Path to output file')
args = parser.parse_args()
services: Dict[int, Tuple[str, str, str]] = {}
pattern: re.Pattern = re.compile(r'^([0-9A-Fa-fXx]+)\s+(\S+)\s+(\S+)\s+(\d+)')
# Single pass through file to collect services and check duplicates
with open(args.input_file, 'r') as f:
for line in f:
if match := pattern.match(line):
nr = int(match.group(1))
if nr in services:
print('ERROR: Found duplicate secure service numbers, exiting...')
sys.exit(1)
services[nr] = (match.group(2), match.group(3), match.group(4))
# Generate output
with open(args.output_file, 'w') as f:
f.write('''/**
* This header file is used to define secure services.
*
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT!
*/
#pragma once
''')
for nr in sorted(services):
_, name, nargs = services[nr]
f.write(emit(nr, name, nargs) + '\n')
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,113 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import argparse
import re
from typing import List
from typing import Tuple
SEC_SRV_TABLE_SPLIT_ID = 48
def parse_services(secure_service_tbl: str) -> List[Tuple[int, str, int]]:
services, service_ids = [], set()
pattern = re.compile(r'^([0-9A-Fa-fXx]+)\s+\S+\s+(\S+)\s+(\d+)')
with open(secure_service_tbl, 'r') as f:
for line in f:
if match := pattern.match(line):
service_id = int(match.group(1), 0)
if service_id in service_ids:
raise ValueError(f'Duplicate service call ID found: 0x{service_id:X}')
service_ids.add(service_id)
services.append((service_id, match.group(2), int(match.group(3))))
return sorted(services, key=lambda x: x[0])
def generate_num_header(services: List[Tuple[int, str, int]], output_file: str) -> None:
header = '''/**
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT!
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
'''
body = '\n'.join(f'#define SS_{name.upper()}\t{nr}' for nr, name, _ in services)
footer = f'\n#define MAX_SECURE_SERVICES_ID\t{services[-1][0] + 1 if services else 0}\n'
footer += f'#define SECURE_SERVICES_NUM\t{len(services)}\n\n'
footer += f'#define SECURE_SERVICES_SPLIT_ID\t{SEC_SRV_TABLE_SPLIT_ID}\n\n'
footer += '''typedef void (*secure_service_t)(void);
typedef struct { secure_service_t func; int nargs; } secure_service_entry_t;
'''
footer += '\n#ifdef __cplusplus\n}\n#endif\n'
with open(output_file, 'w') as f:
f.write(header + body + footer)
def generate_dec_header(services: List[Tuple[int, str, int]], output_file: str) -> None:
header = '''/**
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT!
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
'''
body = '\n'.join(f'void _ss_{name}(void);' for _, name, _ in services)
footer = '\n#ifdef __cplusplus\n}\n#endif\n'
with open(output_file, 'w') as f:
f.write(header + body + footer)
def generate_table_split(services: List[Tuple[int, str, int]], output_file_1: str, output_file_2: str) -> None:
header = '''/**
* THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT!
*/
#pragma once
'''
services_1 = [service for service in services if service[0] < SEC_SRV_TABLE_SPLIT_ID]
services_2 = [service for service in services if service[0] >= SEC_SRV_TABLE_SPLIT_ID]
body_1 = '\n'.join(f'__SECURE_SERVICE({nr}, {name}, {nargs})' for nr, name, nargs in services_1)
body_2 = '\n'.join(f'__SECURE_SERVICE({nr}, {name}, {nargs})' for nr, name, nargs in services_2)
with open(output_file_1, 'w') as f1, open(output_file_2, 'w') as f2:
f1.write(header + body_1)
f2.write(header + body_2)
def generate_wrap_list(secure_service_tbl: str) -> None:
pattern = re.compile(r'^[0-9A-Fa-fXx]+\s+IDF\s+(\S+)\s+\d+')
with open(secure_service_tbl, 'r') as f:
wrap_list = [f'-Wl,--wrap={match.group(1)}' for line in f if (match := pattern.match(line))]
print(' '.join(wrap_list), end='')
def main() -> None:
parser = argparse.ArgumentParser(description='Generate secure service outputs')
parser.add_argument('--wrap', action='store_true', help='Generate linker wrap options')
parser.add_argument('secure_service_tbl', type=str, help='Path to secure service table file')
parser.add_argument('output_files', nargs='*', help='Output files: [secure_service_num.h, secure_service_dec.h, secure_service_1.h, secure_service_2.h]')
args = parser.parse_args()
if args.wrap:
generate_wrap_list(args.secure_service_tbl)
else:
if len(args.output_files) != 4:
parser.error('Missing output header files!')
services = parse_services(args.secure_service_tbl)
generate_num_header(services, args.output_files[0])
generate_dec_header(services, args.output_files[1])
generate_table_split(services, args.output_files[2], args.output_files[3])
if __name__ == '__main__':
main()

View File

@@ -1,24 +0,0 @@
#!/usr/bin/env python
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import argparse
import re
from typing import List
def main() -> None:
parser = argparse.ArgumentParser(description='Generate secure service wrap list')
parser.add_argument('secure_service_tbl', type=str, help='Path to secure service table file')
args = parser.parse_args()
pattern: re.Pattern = re.compile(r'^[0-9A-Fa-fXx]+\s+IDF\s+(\S+)\s+\d+')
with open(args.secure_service_tbl, 'r') as f:
wrap_list: List[str] = [f'-Wl,--wrap={match.group(1)}'
for line in f if (match := pattern.match(line))]
print(' '.join(wrap_list), end='')
if __name__ == '__main__':
main()

View File

@@ -25,7 +25,7 @@ set(ESP_TEE_BUILD 1)
set(NON_OS_BUILD 1) set(NON_OS_BUILD 1)
# TEE-specific components # TEE-specific components
list(APPEND COMPONENTS tee_flash_mgr tee_ota_ops tee_sec_storage attestation) list(APPEND COMPONENTS tee_flash_mgr tee_ota_ops tee_sec_storage tee_attestation)
# Include sdkconfig.h derived from the parent build. # Include sdkconfig.h derived from the parent build.
include_directories(${CONFIG_DIR}) include_directories(${CONFIG_DIR})

View File

@@ -41,7 +41,7 @@ extern "C" {
#define ESP_ATT_TK_MIN_SIZE (ESP_ATT_HDR_JSON_MAX_SZ + ESP_ATT_EAT_JSON_MAX_SZ + ESP_ATT_PUBKEY_JSON_MAX_SZ + ESP_ATT_SIGN_JSON_MAX_SZ) #define ESP_ATT_TK_MIN_SIZE (ESP_ATT_HDR_JSON_MAX_SZ + ESP_ATT_EAT_JSON_MAX_SZ + ESP_ATT_PUBKEY_JSON_MAX_SZ + ESP_ATT_SIGN_JSON_MAX_SZ)
#if ESP_TEE_BUILD #if ESP_TEE_BUILD && CONFIG_SECURE_TEE_ATTESTATION
#define ESP_ATT_TK_KEY_ID (CONFIG_SECURE_TEE_ATT_KEY_SLOT_ID) #define ESP_ATT_TK_KEY_ID (CONFIG_SECURE_TEE_ATT_KEY_SLOT_ID)
#else #else
#define ESP_ATT_TK_KEY_ID (-1) #define ESP_ATT_TK_KEY_ID (-1)

View File

@@ -1,13 +1,17 @@
idf_build_get_property(esp_tee_build ESP_TEE_BUILD) idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
if(esp_tee_build) set(srcs)
return()
endif()
set(srcs "esp_tee_attestation.c")
set(include_dirs ".") set(include_dirs ".")
set(priv_requires esp_tee) set(priv_requires esp_tee)
if(esp_tee_build)
list(APPEND priv_requires attestation main)
endif()
if(CONFIG_SECURE_TEE_ATTESTATION)
list(APPEND srcs "esp_tee_attestation.c")
endif()
idf_component_register(SRCS ${srcs} idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs} INCLUDE_DIRS ${include_dirs}
PRIV_REQUIRES ${priv_requires}) PRIV_REQUIRES ${priv_requires})

View File

@@ -0,0 +1,5 @@
# 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
# Append secure service table consisting of secure services
idf_build_set_property(CUSTOM_SECURE_SERVICE_TBL ${CMAKE_CURRENT_LIST_DIR}/esp_tee_att.tbl APPEND)

View File

@@ -0,0 +1,2 @@
# SS no. API type Function Args
250 custom esp_tee_att_generate_token 6

View File

@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -12,6 +12,12 @@
#include "esp_log.h" #include "esp_log.h"
#include "esp_err.h" #include "esp_err.h"
#if ESP_TEE_BUILD
#include "esp_fault.h"
#include "esp_tee_memory_utils.h"
#include "esp_attestation.h"
#endif
#include "esp_tee.h" #include "esp_tee.h"
#include "secure_service_num.h" #include "secure_service_num.h"
@@ -19,9 +25,31 @@
static __attribute__((unused)) const char *TAG = "esp_tee_att"; static __attribute__((unused)) const char *TAG = "esp_tee_att";
#if ESP_TEE_BUILD
esp_err_t _ss_esp_tee_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref,
uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len)
{
bool valid_addr = (esp_tee_ptr_in_ree((void *)psa_cert_ref) &&
esp_tee_ptr_in_ree((void *)token_buf) &&
esp_tee_ptr_in_ree((void *)token_len));
valid_addr &= (esp_tee_ptr_in_ree((void *)((char *)psa_cert_ref + 20)) &&
esp_tee_ptr_in_ree((void *)((char *)token_buf + token_buf_size)));
if (!valid_addr) {
return ESP_ERR_INVALID_ARG;
}
ESP_FAULT_ASSERT(valid_addr);
return esp_att_generate_token(nonce, client_id, psa_cert_ref, token_buf, token_buf_size, token_len);
}
#else
esp_err_t esp_tee_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref, esp_err_t esp_tee_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref,
uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len) uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len)
{ {
return (esp_err_t)esp_tee_service_call_with_noniram_intr_disabled(7, SS_ESP_TEE_ATT_GENERATE_TOKEN, nonce, client_id, return (esp_err_t)esp_tee_service_call_with_noniram_intr_disabled(7, SS_ESP_TEE_ATT_GENERATE_TOKEN, nonce, client_id,
psa_cert_ref, token_buf, token_buf_size, token_len); psa_cert_ref, token_buf, token_buf_size, token_len);
} }
#endif

View File

@@ -13,6 +13,26 @@
static const char *TAG = "esp_tee_sec_disp"; static const char *TAG = "esp_tee_sec_disp";
extern const secure_service_entry_t tee_sec_srv_tbl_int_mem[];
extern const secure_service_entry_t tee_sec_srv_tbl_ext_mem[];
/* ---------------------------------------------- Secure Service Dispatcher ------------------------------------------------- */
static const secure_service_entry_t *find_service_by_id(uint32_t id)
{
if (id >= MAX_SECURE_SERVICES_ID) {
return NULL;
}
if (id < SECURE_SERVICES_SPLIT_ID) {
return &tee_sec_srv_tbl_int_mem[id];
} else {
return &tee_sec_srv_tbl_ext_mem[id];
}
return NULL;
}
/** /**
* @brief Entry point to the TEE binary during secure service call. It decipher the call and dispatch it * @brief Entry point to the TEE binary during secure service call. It decipher the call and dispatch it
* to corresponding Secure Service API in secure world. * to corresponding Secure Service API in secure world.
@@ -30,19 +50,25 @@ int esp_tee_service_dispatcher(int argc, va_list ap)
} }
int ret = -1; int ret = -1;
void *fp_secure_service;
uint32_t argv[ESP_TEE_MAX_INPUT_ARG], *argp; uint32_t argv[ESP_TEE_MAX_INPUT_ARG], *argp;
uint32_t sid = va_arg(ap, uint32_t); uint32_t sid = va_arg(ap, uint32_t);
argc--; argc--;
if (sid >= MAX_SECURE_SERVICES) { const secure_service_entry_t *service = find_service_by_id(sid);
ESP_LOGE(TAG, "Invalid Service ID!"); if (service == NULL) {
ESP_LOGE(TAG, "Invalid service ID!");
va_end(ap); va_end(ap);
return -1; return ret;
} }
fp_secure_service = (void *)tee_secure_service_table[sid]; if (argc != service->nargs) {
ESP_LOGE(TAG, "Invalid number of arguments for service %d!", sid);
va_end(ap);
return ret;
}
void *fp_secure_service = (void *)service->func;
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
argv[i] = va_arg(ap, uint32_t); argv[i] = va_arg(ap, uint32_t);
@@ -107,4 +133,5 @@ int esp_tee_service_dispatcher(int argc, va_list ap)
return ret; return ret;
} }
#pragma GCC pop_options #pragma GCC pop_options

View File

@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -8,19 +8,25 @@
#include "secure_service_num.h" #include "secure_service_num.h"
#include "secure_service_dec.h" #include "secure_service_dec.h"
typedef void (*secure_service_t)(void);
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Woverride-init" #pragma GCC diagnostic ignored "-Woverride-init"
#endif #endif
const DRAM_ATTR secure_service_t tee_secure_service_table[] = { const DRAM_ATTR secure_service_entry_t tee_sec_srv_tbl_int_mem[] = {
[0 ... MAX_SECURE_SERVICES - 1] = (secure_service_t)NULL, [0 ... SECURE_SERVICES_SPLIT_ID - 1] = { .func = NULL, .nargs = 0 },
#define __SECURE_SERVICE(NR, SYM, ARGC) [NR] = { .func = _ss_##SYM, .nargs = ARGC },
#define __SECURE_SERVICE(nr, symbol, nargs) [nr] = (secure_service_t)_ss_##symbol, #include "secure_service_int.h"
#include "secure_service.h" #undef __SECURE_SERVICE
}; };
const secure_service_entry_t tee_sec_srv_tbl_ext_mem[] = {
[0 ... MAX_SECURE_SERVICES_ID] = { .func = NULL, .nargs = 0 },
#define __SECURE_SERVICE(NR, SYM, ARGC) [NR] = { .func = _ss_##SYM, .nargs = ARGC },
#include "secure_service_ext.h"
#undef __SECURE_SERVICE
};
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif

View File

@@ -24,6 +24,7 @@
#include "sha/sha_dma.h" #include "sha/sha_dma.h"
#include "esp_tee.h" #include "esp_tee.h"
#include "esp_tee_memory_utils.h"
#include "esp_tee_intr.h" #include "esp_tee_intr.h"
#include "esp_tee_aes_intr.h" #include "esp_tee_aes_intr.h"
#include "esp_tee_rv_utils.h" #include "esp_tee_rv_utils.h"
@@ -33,20 +34,6 @@
#include "esp_tee_ota_ops.h" #include "esp_tee_ota_ops.h"
#include "esp_attestation.h" #include "esp_attestation.h"
FORCE_INLINE_ATTR bool is_valid_ree_address(const void *ree_addr)
{
return ((((size_t)ree_addr >= SOC_NS_IDRAM_START) &&
((size_t)ree_addr < SOC_NS_IDRAM_END)
) ||
((ree_addr >= esp_tee_app_config.ns_drom_start) &&
((size_t)ree_addr < SOC_S_MMU_MMAP_RESV_START_VADDR)
) ||
(((size_t)ree_addr >= SOC_RTC_DATA_LOW) &&
((size_t)ree_addr < SOC_RTC_DATA_HIGH)
)
);
}
void _ss_invalid_secure_service(void) void _ss_invalid_secure_service(void)
{ {
assert(0); assert(0);
@@ -113,13 +100,12 @@ bool _ss_efuse_hal_get_disable_wafer_version_major(void)
void _ss_efuse_hal_get_mac(uint8_t *mac) void _ss_efuse_hal_get_mac(uint8_t *mac)
{ {
bool valid_addr = ((is_valid_ree_address((void *)mac)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)mac)) &
(is_valid_ree_address((void *)(mac + 6)))); (esp_tee_ptr_in_ree((void *)(mac + 6))));
if (!valid_addr) { if (!valid_addr) {
return; return;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
efuse_hal_get_mac(mac); efuse_hal_get_mac(mac);
@@ -184,13 +170,12 @@ int _ss_esp_aes_crypt_cbc(esp_aes_context *ctx,
const unsigned char *input, const unsigned char *input,
unsigned char *output) unsigned char *output)
{ {
bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)input) && esp_tee_ptr_in_ree((void *)output)) &
(is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); (esp_tee_ptr_in_ree((void *)(input + length)) && esp_tee_ptr_in_ree((void *)(output + length))));
if (!valid_addr) { if (!valid_addr) {
return -1; return -1;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_aes_crypt_cbc(ctx, mode, length, iv, input, output); return esp_aes_crypt_cbc(ctx, mode, length, iv, input, output);
@@ -204,13 +189,12 @@ int _ss_esp_aes_crypt_cfb128(esp_aes_context *ctx,
const unsigned char *input, const unsigned char *input,
unsigned char *output) unsigned char *output)
{ {
bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)input) && esp_tee_ptr_in_ree((void *)output)) &
(is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); (esp_tee_ptr_in_ree((void *)(input + length)) && esp_tee_ptr_in_ree((void *)(output + length))));
if (!valid_addr) { if (!valid_addr) {
return -1; return -1;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_aes_crypt_cfb128(ctx, mode, length, iv_off, iv, input, output); return esp_aes_crypt_cfb128(ctx, mode, length, iv_off, iv, input, output);
@@ -223,13 +207,12 @@ int _ss_esp_aes_crypt_cfb8(esp_aes_context *ctx,
const unsigned char *input, const unsigned char *input,
unsigned char *output) unsigned char *output)
{ {
bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)input) && esp_tee_ptr_in_ree((void *)output)) &
(is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); (esp_tee_ptr_in_ree((void *)(input + length)) && esp_tee_ptr_in_ree((void *)(output + length))));
if (!valid_addr) { if (!valid_addr) {
return -1; return -1;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_aes_crypt_cfb8(ctx, mode, length, iv, input, output); return esp_aes_crypt_cfb8(ctx, mode, length, iv, input, output);
@@ -243,13 +226,12 @@ int _ss_esp_aes_crypt_ctr(esp_aes_context *ctx,
const unsigned char *input, const unsigned char *input,
unsigned char *output) unsigned char *output)
{ {
bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)input) && esp_tee_ptr_in_ree((void *)output)) &
(is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); (esp_tee_ptr_in_ree((void *)(input + length)) && esp_tee_ptr_in_ree((void *)(output + length))));
if (!valid_addr) { if (!valid_addr) {
return -1; return -1;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_aes_crypt_ctr(ctx, length, nc_off, nonce_counter, stream_block, input, output); return esp_aes_crypt_ctr(ctx, length, nc_off, nonce_counter, stream_block, input, output);
@@ -260,13 +242,12 @@ int _ss_esp_aes_crypt_ecb(esp_aes_context *ctx,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16]) unsigned char output[16])
{ {
bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)input) && esp_tee_ptr_in_ree((void *)output)) &
(is_valid_ree_address((void *)(input + 16)) && is_valid_ree_address((void *)(output + 16)))); (esp_tee_ptr_in_ree((void *)(input + 16)) && esp_tee_ptr_in_ree((void *)(output + 16))));
if (!valid_addr) { if (!valid_addr) {
return -1; return -1;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_aes_crypt_ecb(ctx, mode, input, output); return esp_aes_crypt_ecb(ctx, mode, input, output);
@@ -279,13 +260,12 @@ int _ss_esp_aes_crypt_ofb(esp_aes_context *ctx,
const unsigned char *input, const unsigned char *input,
unsigned char *output) unsigned char *output)
{ {
bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)input) && esp_tee_ptr_in_ree((void *)output)) &
(is_valid_ree_address((void *)(input + length)) && is_valid_ree_address((void *)(output + length)))); (esp_tee_ptr_in_ree((void *)(input + length)) && esp_tee_ptr_in_ree((void *)(output + length))));
if (!valid_addr) { if (!valid_addr) {
return -1; return -1;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_aes_crypt_ofb(ctx, length, iv_off, iv, input, output); return esp_aes_crypt_ofb(ctx, length, iv_off, iv, input, output);
@@ -295,13 +275,12 @@ int _ss_esp_aes_crypt_ofb(esp_aes_context *ctx,
void _ss_esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output) void _ss_esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output)
{ {
bool valid_addr = ((is_valid_ree_address((void *)input) && is_valid_ree_address((void *)output)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)input) && esp_tee_ptr_in_ree((void *)output)) &
(is_valid_ree_address((void *)(input + ilen)))); (esp_tee_ptr_in_ree((void *)(input + ilen))));
if (!valid_addr) { if (!valid_addr) {
return; return;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
esp_sha(sha_type, input, ilen, output); esp_sha(sha_type, input, ilen, output);
@@ -310,13 +289,11 @@ void _ss_esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen,
int _ss_esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen, int _ss_esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
const void *buf, uint32_t buf_len, bool is_first_block) const void *buf, uint32_t buf_len, bool is_first_block)
{ {
bool valid_addr = (is_valid_ree_address((void *)input) && bool valid_addr = (esp_tee_ptr_in_ree((void *)input) &&
is_valid_ree_address((void *)((char *)input + ilen)) esp_tee_ptr_in_ree((void *)((char *)input + ilen)));
);
if (buf_len) { if (buf_len) {
valid_addr &= (is_valid_ree_address((void *)buf) && valid_addr &= (esp_tee_ptr_in_ree((void *)buf) &&
is_valid_ree_address((void *)((char *)buf + buf_len)) esp_tee_ptr_in_ree((void *)((char *)buf + buf_len)));
);
} }
if (!valid_addr) { if (!valid_addr) {
@@ -346,13 +323,12 @@ int _ss_esp_tee_ota_begin(void)
int _ss_esp_tee_ota_write(uint32_t rel_offset, void *data, size_t size) int _ss_esp_tee_ota_write(uint32_t rel_offset, void *data, size_t size)
{ {
bool valid_addr = ((is_valid_ree_address((void *)data)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)data)) &
(is_valid_ree_address((void *)((char *)data + size)))); (esp_tee_ptr_in_ree((void *)((char *)data + size))));
if (!valid_addr) { if (!valid_addr) {
return -1; return -1;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_tee_ota_write(rel_offset, data, size); return esp_tee_ota_write(rel_offset, data, size);
@@ -377,14 +353,13 @@ esp_err_t _ss_esp_tee_sec_storage_gen_key(uint16_t slot_id, uint8_t key_type)
esp_err_t _ss_esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign) esp_err_t _ss_esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash, size_t hlen, esp_tee_sec_storage_sign_t *out_sign)
{ {
bool valid_addr = ((is_valid_ree_address((void *)hash) && is_valid_ree_address((void *)out_sign)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)hash) && esp_tee_ptr_in_ree((void *)out_sign)) &
(is_valid_ree_address((void *)(hash + hlen)) && (esp_tee_ptr_in_ree((void *)(hash + hlen)) &&
is_valid_ree_address((void *)((char *)out_sign + sizeof(esp_tee_sec_storage_sign_t))))); esp_tee_ptr_in_ree((void *)((char *)out_sign + sizeof(esp_tee_sec_storage_sign_t)))));
if (!valid_addr) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_get_signature(slot_id, hash, hlen, out_sign); return esp_tee_sec_storage_get_signature(slot_id, hash, hlen, out_sign);
@@ -392,13 +367,12 @@ esp_err_t _ss_esp_tee_sec_storage_get_signature(uint16_t slot_id, uint8_t *hash,
esp_err_t _ss_esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_pubkey_t *pubkey) esp_err_t _ss_esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_storage_pubkey_t *pubkey)
{ {
bool valid_addr = ((is_valid_ree_address((void *)pubkey)) & bool valid_addr = ((esp_tee_ptr_in_ree((void *)pubkey)) &
(is_valid_ree_address((void *)((char *)pubkey + sizeof(esp_tee_sec_storage_pubkey_t))))); (esp_tee_ptr_in_ree((void *)((char *)pubkey + sizeof(esp_tee_sec_storage_pubkey_t)))));
if (!valid_addr) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_get_pubkey(slot_id, pubkey); return esp_tee_sec_storage_get_pubkey(slot_id, pubkey);
@@ -407,21 +381,21 @@ esp_err_t _ss_esp_tee_sec_storage_get_pubkey(uint16_t slot_id, esp_tee_sec_stora
esp_err_t _ss_esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad, esp_err_t _ss_esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output) uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output)
{ {
bool valid_addr = (is_valid_ree_address((void *)input) && is_valid_ree_address((void *)tag) && bool valid_addr = (esp_tee_ptr_in_ree((void *)input) &&
is_valid_ree_address((void *)output)); esp_tee_ptr_in_ree((void *)tag) &&
esp_tee_ptr_in_ree((void *)output));
valid_addr &= (is_valid_ree_address((void *)(input + len)) && is_valid_ree_address((void *)(tag + tag_len)) && valid_addr &= (esp_tee_ptr_in_ree((void *)(input + len)) &&
is_valid_ree_address((void *)(output + len)) esp_tee_ptr_in_ree((void *)(tag + tag_len)) &&
); esp_tee_ptr_in_ree((void *)(output + len)));
if (aad) { if (aad) {
valid_addr &= (is_valid_ree_address((void *)aad) && is_valid_ree_address((void *)(aad + aad_len))); valid_addr &= (esp_tee_ptr_in_ree((void *)aad) && esp_tee_ptr_in_ree((void *)(aad + aad_len)));
} }
if (!valid_addr) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_encrypt(slot_id, input, len, aad, aad_len, tag, tag_len, output); return esp_tee_sec_storage_encrypt(slot_id, input, len, aad, aad_len, tag, tag_len, output);
@@ -430,21 +404,21 @@ esp_err_t _ss_esp_tee_sec_storage_encrypt(uint16_t slot_id, uint8_t *input, uint
esp_err_t _ss_esp_tee_sec_storage_decrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad, esp_err_t _ss_esp_tee_sec_storage_decrypt(uint16_t slot_id, uint8_t *input, uint8_t len, uint8_t *aad,
uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output) uint16_t aad_len, uint8_t *tag, uint16_t tag_len, uint8_t *output)
{ {
bool valid_addr = (is_valid_ree_address((void *)input) && is_valid_ree_address((void *)tag) && bool valid_addr = (esp_tee_ptr_in_ree((void *)input) &&
is_valid_ree_address((void *)output)); esp_tee_ptr_in_ree((void *)tag) &&
esp_tee_ptr_in_ree((void *)output));
valid_addr &= (is_valid_ree_address((void *)(input + len)) && is_valid_ree_address((void *)(tag + tag_len)) && valid_addr &= (esp_tee_ptr_in_ree((void *)(input + len)) &&
is_valid_ree_address((void *)(output + len)) esp_tee_ptr_in_ree((void *)(tag + tag_len)) &&
); esp_tee_ptr_in_ree((void *)(output + len)));
if (aad) { if (aad) {
valid_addr &= (is_valid_ree_address((void *)aad) && is_valid_ree_address((void *)(aad + aad_len))); valid_addr &= (esp_tee_ptr_in_ree((void *)aad) && esp_tee_ptr_in_ree((void *)(aad + aad_len)));
} }
if (!valid_addr) { if (!valid_addr) {
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
ESP_FAULT_ASSERT(valid_addr); ESP_FAULT_ASSERT(valid_addr);
return esp_tee_sec_storage_decrypt(slot_id, input, len, aad, aad_len, tag, tag_len, output); return esp_tee_sec_storage_decrypt(slot_id, input, len, aad, aad_len, tag, tag_len, output);
@@ -460,26 +434,8 @@ esp_err_t _ss_esp_tee_sec_storage_clear_slot(uint16_t slot_id)
return esp_tee_sec_storage_clear_slot(slot_id); return esp_tee_sec_storage_clear_slot(slot_id);
} }
/* ---------------------------------------------- Attestation ------------------------------------------------- */
esp_err_t _ss_esp_tee_att_generate_token(const uint32_t nonce, const uint32_t client_id, const char *psa_cert_ref,
uint8_t *token_buf, const size_t token_buf_size, uint32_t *token_len)
{
bool valid_addr = (is_valid_ree_address((void *)psa_cert_ref) && is_valid_ree_address((void *)token_buf) &&
is_valid_ree_address((void *)token_len));
valid_addr &= (is_valid_ree_address((void *)((char *)psa_cert_ref + 32)) && is_valid_ree_address((void *)((char *)token_buf + token_buf_size)));
if (!valid_addr) {
return ESP_ERR_INVALID_ARG;
}
ESP_FAULT_ASSERT(valid_addr);
return esp_att_generate_token(nonce, client_id, psa_cert_ref, token_buf, token_buf_size, token_len);
}
/* ---------------------------------------------- MMU HAL ------------------------------------------------- */ /* ---------------------------------------------- MMU HAL ------------------------------------------------- */
void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr, void _ss_mmu_hal_map_region(uint32_t mmu_id, mmu_target_t mem_type, uint32_t vaddr,
uint32_t paddr, uint32_t len, uint32_t *out_len) uint32_t paddr, uint32_t len, uint32_t *out_len)
{ {

View File

@@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_attr.h"
#include "soc/soc.h"
#include "soc/ext_mem_defs.h"
#include "esp_tee.h"
#ifdef __cplusplus
extern "C" {
#endif
FORCE_INLINE_ATTR bool esp_tee_ptr_in_ree(const void *p)
{
return (((intptr_t)p >= SOC_NS_IDRAM_START && (intptr_t)p < SOC_NS_IDRAM_END) ||
((intptr_t)p >= (size_t)esp_tee_app_config.ns_drom_start && (intptr_t)p < SOC_S_MMU_MMAP_RESV_START_VADDR) ||
((intptr_t)p >= SOC_RTC_DATA_LOW && (intptr_t)p < SOC_RTC_DATA_HIGH));
}
#ifdef __cplusplus
}
#endif

View File

@@ -13,4 +13,8 @@ list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/components/esp_tee/subproject/co
$ENV{IDF_PATH}/components/esp_tee/subproject/components/tee_sec_storage) $ENV{IDF_PATH}/components/esp_tee/subproject/components/tee_sec_storage)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# Including the attestation service calls
include($ENV{IDF_PATH}/components/esp_tee/subproject/components/tee_attestation/esp_tee_att.cmake)
project(tee_cli) project(tee_cli)

View File

@@ -14,5 +14,6 @@ list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/tools/unit-test-app/components
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/components/test_sec_srv/test_tee_project.cmake) include(${CMAKE_CURRENT_LIST_DIR}/components/test_sec_srv/test_tee_project.cmake)
include($ENV{IDF_PATH}/components/esp_tee/subproject/components/tee_attestation/esp_tee_att.cmake)
project(esp_tee_test) project(esp_tee_test)

View File

@@ -1,18 +1,18 @@
# SS no. API type Function Args # SS no. API type Function Args
101 custom esp_tee_service_add 6 300 custom esp_tee_service_add 2
102 custom esp_tee_service_sub 6 301 custom esp_tee_service_sub 2
103 custom esp_tee_service_mul 6 302 custom esp_tee_service_mul 2
104 custom esp_tee_service_div 6 303 custom esp_tee_service_div 2
105 custom esp_tee_test_timer_init 6 304 custom esp_tee_test_timer_init 1
106 custom esp_tee_secure_int_test 6 305 custom esp_tee_secure_int_test 0
107 custom esp_tee_non_secure_int_test 6 306 custom esp_tee_non_secure_int_test 1
108 custom esp_tee_test_int_count 6 307 custom esp_tee_test_int_count 1
109 custom esp_tee_test_resv_reg1_write_violation 0 308 custom esp_tee_test_resv_reg1_write_violation 0
110 custom esp_tee_test_resv_reg1_exec_violation 0 309 custom esp_tee_test_resv_reg1_exec_violation 0
111 custom esp_tee_test_iram_reg1_write_violation 0 310 custom esp_tee_test_iram_reg1_write_violation 0
112 custom esp_tee_test_iram_reg2_write_violation 0 311 custom esp_tee_test_iram_reg2_write_violation 0
113 custom esp_tee_test_dram_reg1_exec_violation 0 312 custom esp_tee_test_dram_reg1_exec_violation 0
114 custom esp_tee_test_dram_reg2_exec_violation 0 313 custom esp_tee_test_dram_reg2_exec_violation 0
115 custom esp_tee_test_illegal_instruction 0 314 custom esp_tee_test_illegal_instruction 0
201 custom dummy_secure_service 6 315 custom dummy_secure_service 0
202 custom add_in_loop 6 316 custom add_in_loop 3

View File

@@ -13,9 +13,12 @@ list(APPEND srcs "test_esp_tee_ctx_switch.c"
"test_esp_tee_panic.c" "test_esp_tee_panic.c"
"test_esp_tee_sec_stg.c" "test_esp_tee_sec_stg.c"
"test_esp_tee_ota.c" "test_esp_tee_ota.c"
"test_esp_tee_att.c"
"test_esp_tee_flash_prot.c") "test_esp_tee_flash_prot.c")
if(CONFIG_SECURE_TEE_ATTESTATION)
list(APPEND srcs "test_esp_tee_att.c")
endif()
set(mbedtls_test_srcs_dir "${idf_path}/components/mbedtls/test_apps/main") set(mbedtls_test_srcs_dir "${idf_path}/components/mbedtls/test_apps/main")
# AES # AES

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -17,6 +17,10 @@
#include "riscv/csr_pie.h" #include "riscv/csr_pie.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
#include "secure_service_num.h"
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -28,15 +32,7 @@ extern "C" {
#define IS_PRV_M_MODE() (1UL) #define IS_PRV_M_MODE() (1UL)
#endif #endif
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
/* [ESP-TEE] Secure service call IDs for interrupt management */
#define TEE_INTR_ENABLE_SRV_ID (2)
#define TEE_INTR_DISABLE_SRV_ID (3)
#define TEE_INTR_SET_PRIORITY_SRV_ID (4)
#define TEE_INTR_SET_TYPE_SRV_ID (5)
#define TEE_INTR_SET_THRESHOLD_SRV_ID (6)
#define TEE_INTR_EDGE_ACK_SRV_ID (7)
#define TEE_INTR_GLOBAL_EN_SRV_ID (8)
/* [ESP-TEE] Callback function for accessing interrupt management services through REE */ /* [ESP-TEE] Callback function for accessing interrupt management services through REE */
extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb; extern esprv_int_mgmt_t esp_tee_intr_sec_srv_cb;
#endif #endif
@@ -157,8 +153,8 @@ FORCE_INLINE_ATTR void rv_utils_set_xtvec(uint32_t xtvec_val)
FORCE_INLINE_ATTR void rv_utils_intr_enable(uint32_t intr_mask) FORCE_INLINE_ATTR void rv_utils_intr_enable(uint32_t intr_mask)
{ {
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
esp_tee_intr_sec_srv_cb(2, TEE_INTR_ENABLE_SRV_ID, intr_mask); esp_tee_intr_sec_srv_cb(2, SS_RV_UTILS_INTR_ENABLE, intr_mask);
#else #else
// Disable all interrupts to make updating of the interrupt mask atomic. // Disable all interrupts to make updating of the interrupt mask atomic.
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
@@ -169,8 +165,8 @@ FORCE_INLINE_ATTR void rv_utils_intr_enable(uint32_t intr_mask)
FORCE_INLINE_ATTR void rv_utils_intr_disable(uint32_t intr_mask) FORCE_INLINE_ATTR void rv_utils_intr_disable(uint32_t intr_mask)
{ {
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
esp_tee_intr_sec_srv_cb(2, TEE_INTR_DISABLE_SRV_ID, intr_mask); esp_tee_intr_sec_srv_cb(2, SS_RV_UTILS_INTR_DISABLE, intr_mask);
#else #else
// Disable all interrupts to make updating of the interrupt mask atomic. // Disable all interrupts to make updating of the interrupt mask atomic.
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
@@ -181,8 +177,8 @@ FORCE_INLINE_ATTR void rv_utils_intr_disable(uint32_t intr_mask)
FORCE_INLINE_ATTR void rv_utils_intr_global_enable(void) FORCE_INLINE_ATTR void rv_utils_intr_global_enable(void)
{ {
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
esp_tee_intr_sec_srv_cb(1, TEE_INTR_GLOBAL_EN_SRV_ID); esp_tee_intr_sec_srv_cb(1, SS_RV_UTILS_INTR_GLOBAL_ENABLE);
#else #else
RV_SET_CSR(mstatus, MSTATUS_MIE); RV_SET_CSR(mstatus, MSTATUS_MIE);
#endif #endif
@@ -203,8 +199,8 @@ FORCE_INLINE_ATTR void rv_utils_intr_global_disable(void)
FORCE_INLINE_ATTR void rv_utils_intr_set_type(int intr_num, enum intr_type type) FORCE_INLINE_ATTR void rv_utils_intr_set_type(int intr_num, enum intr_type type)
{ {
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
esp_tee_intr_sec_srv_cb(3, TEE_INTR_SET_TYPE_SRV_ID, intr_num, type); esp_tee_intr_sec_srv_cb(3, SS_RV_UTILS_INTR_SET_TYPE, intr_num, type);
#else #else
esprv_int_set_type(intr_num, type); esprv_int_set_type(intr_num, type);
#endif #endif
@@ -212,8 +208,8 @@ FORCE_INLINE_ATTR void rv_utils_intr_set_type(int intr_num, enum intr_type type)
FORCE_INLINE_ATTR void rv_utils_intr_set_priority(int rv_int_num, int priority) FORCE_INLINE_ATTR void rv_utils_intr_set_priority(int rv_int_num, int priority)
{ {
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
esp_tee_intr_sec_srv_cb(3, TEE_INTR_SET_PRIORITY_SRV_ID, rv_int_num, priority); esp_tee_intr_sec_srv_cb(3, SS_RV_UTILS_INTR_SET_PRIORITY, rv_int_num, priority);
#else #else
esprv_int_set_priority(rv_int_num, priority); esprv_int_set_priority(rv_int_num, priority);
#endif #endif
@@ -221,8 +217,8 @@ FORCE_INLINE_ATTR void rv_utils_intr_set_priority(int rv_int_num, int priority)
FORCE_INLINE_ATTR void rv_utils_intr_set_threshold(int priority_threshold) FORCE_INLINE_ATTR void rv_utils_intr_set_threshold(int priority_threshold)
{ {
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
esp_tee_intr_sec_srv_cb(2, TEE_INTR_SET_THRESHOLD_SRV_ID, priority_threshold); esp_tee_intr_sec_srv_cb(2, SS_RV_UTILS_INTR_SET_THRESHOLD, priority_threshold);
#else #else
esprv_int_set_threshold(priority_threshold); esprv_int_set_threshold(priority_threshold);
#endif #endif

View File

@@ -59,7 +59,7 @@ bool esprv_int_is_vectored(int rv_int_num)
} }
#if CONFIG_SECURE_ENABLE_TEE && !ESP_TEE_BUILD #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD
DRAM_ATTR esprv_int_mgmt_t esp_tee_intr_sec_srv_cb = NULL; DRAM_ATTR esprv_int_mgmt_t esp_tee_intr_sec_srv_cb = NULL;
void esprv_int_setup_mgmt_cb(void *fptr) void esprv_int_setup_mgmt_cb(void *fptr)

View File

@@ -10,6 +10,10 @@ Thus, the attestation service is employed by the device to communicate evidence
To ensure security, the EAT is cryptographically protected. The remote relying party can then verify the authenticity of the EAT and make decisions about engaging with the device based on its contents. To ensure security, the EAT is cryptographically protected. The remote relying party can then verify the authenticity of the EAT and make decisions about engaging with the device based on its contents.
.. note::
- Support for Attestation can be toggled using the option :ref:`CONFIG_SECURE_TEE_ATTESTATION` (enabled by default).
Attestation Flow Attestation Flow
---------------- ----------------
@@ -251,6 +255,8 @@ API Reference
.. note:: .. note::
To use the TEE Attestation APIs into your project, ensure the :component:`tee_attestation <esp_tee/subproject/components/tee_attestation>` component is included by setting ``EXTRA_COMPONENT_DIRS`` in your project's ``CMakeLists.txt`` file, as shown in the :example:`tee_attestation <security/tee/tee_attestation>` example. For more information, refer to the :ref:`optional_project_variable` section from the :doc:`Build System </api-guides/build-system>` documentation. - To use the TEE Attestation APIs into your project, ensure the :component:`tee_attestation <esp_tee/subproject/components/tee_attestation>` component is included by setting ``EXTRA_COMPONENT_DIRS`` in your project's ``CMakeLists.txt`` file, as shown in the :example:`tee_attestation <security/tee/tee_attestation>` example. For more information, refer to the :ref:`optional_project_variable` section from the :doc:`Build System </api-guides/build-system>` documentation.
- Additionally, the component-specific :component_file:`CMake <esp_tee/subproject/components/tee_attestation/esp_tee_att.cmake>` file needs to be included in the top-level ``CMakeLists.txt`` of your project before calling the ``project()`` command to integrate the corresponding service calls into the project.
.. include-build-file:: inc/esp_tee_attestation.inc .. include-build-file:: inc/esp_tee_attestation.inc

View File

@@ -8,4 +8,8 @@ cmake_minimum_required(VERSION 3.16)
list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/components/esp_tee/subproject/components/tee_attestation) list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/components/esp_tee/subproject/components/tee_attestation)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# Including the attestation service calls
include($ENV{IDF_PATH}/components/esp_tee/subproject/components/tee_attestation/esp_tee_att.cmake)
project(tee_attestation) project(tee_attestation)

View File

@@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
# Including the example service calls
include(${CMAKE_CURRENT_LIST_DIR}/components/example_secure_service/tee_project.cmake) include(${CMAKE_CURRENT_LIST_DIR}/components/example_secure_service/tee_project.cmake)
project(tee_basic) project(tee_basic)

View File

@@ -1,2 +1,2 @@
# SS no. API type Function Args # SS no. API type Function Args
201 custom example_sec_serv_aes_op 6 300 custom example_sec_serv_aes_op 5

View File

@@ -1,3 +1,4 @@
# Enabling TEE # Enabling TEE
CONFIG_SECURE_ENABLE_TEE=y CONFIG_SECURE_ENABLE_TEE=y
CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y CONFIG_PARTITION_TABLE_SINGLE_APP_TEE=y
CONFIG_SECURE_TEE_ATTESTATION=n