diff --git a/components/esp_tee/CMakeLists.txt b/components/esp_tee/CMakeLists.txt index d66d84e447..3c4480e462 100644 --- a/components/esp_tee/CMakeLists.txt +++ b/components/esp_tee/CMakeLists.txt @@ -82,57 +82,38 @@ else() 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_parser_py + ${COMPONENT_DIR}/scripts/secure_service_tbl_parser.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 +set(secure_service_gen_headers + ${CONFIG_DIR}/secure_service_num.h ${CONFIG_DIR}/secure_service_dec.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} +if(CONFIG_SECURE_ENABLE_TEE AND NOT esp_tee_build) + 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} + execute_process( + COMMAND python ${secure_service_tbl_parser_py} ${secure_service_gen_headers} 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} - ) + OUTPUT_STRIP_TRAILING_WHITESPACE + ) - 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() + string(STRIP "${wrap_list}" wrap_list) + target_link_libraries(${COMPONENT_LIB} INTERFACE "${wrap_list}") endif() diff --git a/components/esp_tee/scripts/secure_service_hdr.py b/components/esp_tee/scripts/secure_service_hdr.py deleted file mode 100644 index 3a2bb2be4c..0000000000 --- a/components/esp_tee/scripts/secure_service_hdr.py +++ /dev/null @@ -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() diff --git a/components/esp_tee/scripts/secure_service_tbl.py b/components/esp_tee/scripts/secure_service_tbl.py deleted file mode 100644 index f16b8d8703..0000000000 --- a/components/esp_tee/scripts/secure_service_tbl.py +++ /dev/null @@ -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() diff --git a/components/esp_tee/scripts/secure_service_tbl_parser.py b/components/esp_tee/scripts/secure_service_tbl_parser.py new file mode 100644 index 0000000000..4617660f81 --- /dev/null +++ b/components/esp_tee/scripts/secure_service_tbl_parser.py @@ -0,0 +1,104 @@ +# 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 + + +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 += '''typedef void (*secure_service_t)(void); +typedef struct { int id; 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(services: List[Tuple[int, str, int]], output_file: str) -> None: + header = '''/** + * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT! + */ + +#pragma once +''' + body = '\n'.join(f'__SECURE_SERVICE({nr}, {name}, {nargs})' for nr, name, nargs in services) + with open(output_file, 'w') as f: + f.write(header + body) + + +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.h]') + + args = parser.parse_args() + + if args.wrap: + generate_wrap_list(args.secure_service_tbl) + else: + if len(args.output_files) != 3: + 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(services, args.output_files[2]) + + +if __name__ == '__main__': + main() diff --git a/components/esp_tee/scripts/secure_service_wrap.py b/components/esp_tee/scripts/secure_service_wrap.py deleted file mode 100644 index 6deb5c9c3c..0000000000 --- a/components/esp_tee/scripts/secure_service_wrap.py +++ /dev/null @@ -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() diff --git a/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c b/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c index 51df15a5d9..5c6f308430 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c +++ b/components/esp_tee/subproject/main/core/esp_secure_dispatcher.c @@ -13,6 +13,34 @@ static const char *TAG = "esp_tee_sec_disp"; +extern const secure_service_entry_t tee_secure_service_table[]; + +/* ---------------------------------------------- Secure Service Dispatcher ------------------------------------------------- */ + +const secure_service_entry_t *find_service_by_id(uint32_t id) +{ + if (id >= MAX_SECURE_SERVICES_ID) { + return NULL; + } + + size_t left = 0; + size_t right = SECURE_SERVICES_NUM; + + while (left < right) { + size_t mid = left + (right - left) / 2; + + if (tee_secure_service_table[mid].id == id) { + return &tee_secure_service_table[mid]; + } else if (tee_secure_service_table[mid].id < id) { + left = mid + 1; + } else { + right = mid; + } + } + + return NULL; +} + /** * @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. @@ -30,19 +58,25 @@ int esp_tee_service_dispatcher(int argc, va_list ap) } int ret = -1; - void *fp_secure_service; uint32_t argv[ESP_TEE_MAX_INPUT_ARG], *argp; uint32_t sid = va_arg(ap, uint32_t); argc--; - if (sid >= MAX_SECURE_SERVICES) { - ESP_LOGE(TAG, "Invalid Service ID!"); + const secure_service_entry_t *service = find_service_by_id(sid); + if (service == NULL) { + ESP_LOGE(TAG, "Invalid service ID!"); 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++) { argv[i] = va_arg(ap, uint32_t); @@ -107,4 +141,5 @@ int esp_tee_service_dispatcher(int argc, va_list ap) return ret; } + #pragma GCC pop_options diff --git a/components/esp_tee/subproject/main/core/esp_secure_service_table.c b/components/esp_tee/subproject/main/core/esp_secure_service_table.c index c1993d4b4f..587072a2e1 100644 --- a/components/esp_tee/subproject/main/core/esp_secure_service_table.c +++ b/components/esp_tee/subproject/main/core/esp_secure_service_table.c @@ -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 */ @@ -8,17 +8,13 @@ #include "secure_service_num.h" #include "secure_service_dec.h" -typedef void (*secure_service_t)(void); - #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverride-init" #endif -const DRAM_ATTR secure_service_t tee_secure_service_table[] = { - [0 ... MAX_SECURE_SERVICES - 1] = (secure_service_t)NULL, - -#define __SECURE_SERVICE(nr, symbol, nargs) [nr] = (secure_service_t)_ss_##symbol, +const DRAM_ATTR secure_service_entry_t tee_secure_service_table[] = { +#define __SECURE_SERVICE(NR, SYM, ARGC) { .id = NR, .func = _ss_##SYM, .nargs = ARGC }, #include "secure_service.h" }; #ifdef __GNUC__