refactor(esp_tee): Add argument count checks for secure services in the dispatcher

Also:
- Unified the TEE build system-related scripts into a single script
This commit is contained in:
Laukik Hase
2025-01-15 18:27:07 +05:30
parent a91f89026c
commit a745100bef
7 changed files with 171 additions and 205 deletions

View File

@@ -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()

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,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()

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

@@ -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

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
*/
@@ -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__