From 6f87cf9efcf29d859257dd3661752aa7ad7de213 Mon Sep 17 00:00:00 2001 From: ajksunkang Date: Mon, 11 Jul 2022 11:18:31 +0800 Subject: [PATCH] support quoting TA for remote attestation --- test/TA/qta/CMakeLists.txt | 35 +++++ test/TA/qta/Makefile | 28 ++++ test/TA/qta/ReadMe.txt | 5 + test/TA/qta/config.cmake | 23 +++ test/TA/qta/config.mk | 23 +++ test/TA/qta/config.sh | 34 +++++ test/TA/qta/manifest.txt | 7 + test/TA/qta/src/tee_qta.c | 284 +++++++++++++++++++++++++++++++++++++ test/TA/qta/src/tee_qta.h | 64 +++++++++ 9 files changed, 503 insertions(+) create mode 100644 test/TA/qta/CMakeLists.txt create mode 100644 test/TA/qta/Makefile create mode 100644 test/TA/qta/ReadMe.txt create mode 100644 test/TA/qta/config.cmake create mode 100644 test/TA/qta/config.mk create mode 100644 test/TA/qta/config.sh create mode 100644 test/TA/qta/manifest.txt create mode 100644 test/TA/qta/src/tee_qta.c create mode 100644 test/TA/qta/src/tee_qta.h diff --git a/test/TA/qta/CMakeLists.txt b/test/TA/qta/CMakeLists.txt new file mode 100644 index 0000000..4073450 --- /dev/null +++ b/test/TA/qta/CMakeLists.txt @@ -0,0 +1,35 @@ +# sdk cmake. +# Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. +cmake_minimum_required(VERSION 3.16 FATAL_ERROR) +project(tee_sdk C) + +if (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR) + message(FATAL_ERROR "Forbid compiling in the source tree") +endif() + +include(${CMAKE_CURRENT_SOURCE_DIR}/config.cmake) +include($ENV{ITRUSTEE_BUILD_PATH}/build/cmake/common.cmake) + +set(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) +set(CURRENT_TARGET_SO "combine") + +set(SDK_C_SOURCES + ${SDK_C_SOURCES} + src/tee_qta.c +) + +set(COMMON_INCLUDES + ${COMMON_INCLUDES} + ${CMAKE_CURRENT_SOURCE_DIR}/src/. +) + +add_library(${CURRENT_TARGET_SO} SHARED ${SDK_C_SOURCES}) +target_include_directories(${CURRENT_TARGET_SO} PUBLIC ${COMMON_INCLUDES}) +target_compile_options(${CURRENT_TARGET_SO} PRIVATE ${COMMON_CFLAGS}) +target_link_options(${CURRENT_TARGET_SO} PRIVATE ${COMMON_LDFLAGS}) + +add_custom_command( + TARGET ${CURRENT_TARGET_SO} POST_BUILD + COMMAND ${CMAKE_OBJCOPY} ${CMAKE_CURRENT_SOURCE_DIR}/libcombine.so + COMMAND python3 -B $ENV{ITRUSTEE_BUILD_PATH}/build/signtools/signtool_v3.py ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} --privateCfg $ENV{ITRUSTEE_BUILD_PATH}/build/signtools/config_cloud.ini +) diff --git a/test/TA/qta/Makefile b/test/TA/qta/Makefile new file mode 100644 index 0000000..64158f3 --- /dev/null +++ b/test/TA/qta/Makefile @@ -0,0 +1,28 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2018-2021. All rights reserved. +include ./config.mk +include ../../../build/mk/common.mk + +SRC += $(wildcard ./src/*.c) + +# set header directory +INCLUDEDIR += -I./src + +# set target +COBJS := $(SRC:%.c=%.o) +TARGET = $(COBJS) + +sec_binary:combine + python3 -B ${SIGNTOOL_DIR}/signtool_v3.py ${CUR_DIR} ${CUR_DIR} --privateCfg ${SIGNTOOL_DIR}/config_cloud.ini + +combine: $(TARGET) + $(LD) $(LDFLAGS) $(TARGET) $(EXTRAO) -o libcombine.so + objcopy libcombine.so + +src/%.o: ./src/%.c + $(CC) $(CFLAGS) $(INCLUDEDIR) -c $< -o $@ + +%.o: %.c + $(CC) $(CFLAGS) $(INCLUDEDIR) -c $< -o $@ + +clean: + rm -f $(COBJS) *.so *.sec diff --git a/test/TA/qta/ReadMe.txt b/test/TA/qta/ReadMe.txt new file mode 100644 index 0000000..0802d8b --- /dev/null +++ b/test/TA/qta/ReadMe.txt @@ -0,0 +1,5 @@ +You need to install the pycryptodome library of python and run the make command to compile the binary of ta. + +If TA wants to regist driver's permission, you must have dynamic permission file and driver's excel +The name of the dynamic permission file must be 'dyn_perm.xml', the driver's excel's name can be 'driver name'.xlsx, and you can get it from driver's developer. +You must install the xlrd-1.2.0 and defusedxml-0.7.1 library of python and run the make command to sign the binary of ta. \ No newline at end of file diff --git a/test/TA/qta/config.cmake b/test/TA/qta/config.cmake new file mode 100644 index 0000000..b7323b6 --- /dev/null +++ b/test/TA/qta/config.cmake @@ -0,0 +1,23 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. +# +# API_LEVEL which indicates the GP API version of TA +# API_LEVEL=1 indicates GP 1.0 which is the current version of itrustee +# API_LEVEL=2 indicates GP 1.1.1 which is the current version of the partner +# API_LEVEL=3 indicates GP 1.2 which is the version we both going to support +# If no API_LEVEL is specified, API of GP 1.0 will be taken +# +# USE_SMEE which indicates the feature of sram memory encryption +# set(USE_SMEE y) indicates the feature of sram memory encryption will be enabled +# If no USE_SMEE is specified, smee feature will be disabled +# If USE_SMEE is specified and a section is custimized, +# explicitly specify the segment to which the section belongs in the link script(ta_link_64.smee.ld) + +# TEE flags +set(COMMON_CFLAGS -DAPI_LEVEL=1) +set(USE_SMEE n) +if ("${TARGET_IS_ARM64}" STREQUAL "") + set(TARGET_IS_ARM64 y) +endif() +if ("${USE_SMEE}" STREQUAL "") + set(USE_SMEE n) +endif() diff --git a/test/TA/qta/config.mk b/test/TA/qta/config.mk new file mode 100644 index 0000000..7a405a3 --- /dev/null +++ b/test/TA/qta/config.mk @@ -0,0 +1,23 @@ +# +# Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. +# +# API_LEVEL which indicates the GP API version of TA +# API_LEVEL=1 indicates GP 1.0 which is the current version of itrustee +# API_LEVEL=2 indicates GP 1.1.1 which is the current version of the partner +# API_LEVEL=3 indicates GP 1.2 which is the version we both going to support +# If no API_LEVEL is specified, API of GP 1.0 will be taken +# +# USE_SMEE which indicates the feature of sram memory encryption +# USE_SMEE=y indicates the feature of sram memory encryption will be enabled +# If no USE_SMEE is specified, smee feature will not be disabled +# If USE_SMEE is specified and a section is custimized, +# explicitly specify the segment to which the section belongs in the link script(ta_link_64.smee.ld) + +CFLAGS += -DAPI_LEVEL=1 +USE_SMEE = n +ifeq ($(TARGET_IS_ARM64),) + TARGET_IS_ARM64 = y +endif +ifeq ($(USE_SMEE),) + USE_SMEE = n +endif diff --git a/test/TA/qta/config.sh b/test/TA/qta/config.sh new file mode 100644 index 0000000..f1170b9 --- /dev/null +++ b/test/TA/qta/config.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# Copyright Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. +# This script is used to compile the demo sdk. +set -e + +export SOURCE_PATH=$(dirname $0) +export ABS_SOURCE_PATH=$(cd ${SOURCE_PATH};pwd) +export ITRUSTEE_BUILD_PATH=${ABS_SOURCE_PATH}/../../.. + +#clean +if [ "$#" -eq 1 ] && [ "$1"x = "clean"x ]; then + rm -f *.o *.so *.sec + if [ -d "cmake_build" ]; then + rm -rf cmake_build + echo "rm -rf cmake_build" + fi + exit 0 +fi + +echo "Cmake compile TA begin" +if [ -d "cmake_build" ]; then + rm -rf cmake_build + echo "rm -rf cmake_build" +fi +mkdir -p cmake_build +echo "mkdir cmake_build" +cd cmake_build/ + +cmake -DCMAKE_TOOLCHAIN_FILE=${ITRUSTEE_BUILD_PATH}/build/cmake/aarch64_toolchain.cmake .. + +make VERBOSE=1 + +cd .. +rm -rf cmake_build diff --git a/test/TA/qta/manifest.txt b/test/TA/qta/manifest.txt new file mode 100644 index 0000000..975c5f1 --- /dev/null +++ b/test/TA/qta/manifest.txt @@ -0,0 +1,7 @@ +gpd.ta.appID: e08f7eca-e875-440e-9ab0-5f381136c600 +gpd.ta.service_name: tee_qta +gpd.ta.singleInstance: true +gpd.ta.multiSession: true +gpd.ta.instanceKeepAlive: false +gpd.ta.dataSize: 304857 +gpd.ta.stackSize: 64768 diff --git a/test/TA/qta/src/tee_qta.c b/test/TA/qta/src/tee_qta.c new file mode 100644 index 0000000..a147fe1 --- /dev/null +++ b/test/TA/qta/src/tee_qta.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * iTrustee licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ + #include "tee_qta.h" + #include + #include + #include "tee_ra_api.h" + #include "securec.h" + +TEE_Result TA_CreateEntryPoint(void) +{ + TEE_Result ret; + /* TA auth CA */ + ret = addcaller_ca_exec("/vendor/bin/ra_client_test", "root"); + if (ret != TEE_SUCCESS) + return ret; + ret = AddCaller_TA_all(); + if (ret != TEE_SUCCESS) + return ret; + tlogi("tee_qta: CreateEntryPoint success.\n"); + return ret; +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types, TEE_Param params[4], void **session_context) +{ + (void)param_types; + (void)params; + (void)session_context; + tlogi("tee_qta: OpenSessionEntryPoint success.\n"); + return TEE_SUCCESS; +} + +static bool check_provision_input_params(struct provision_input_params *ra_input, uint32_t out_size) +{ + if (out_size < PROVISION_RESERVED_SIZE || out_size > SHAREMEM_LIMIT) + return false; + if (ra_input->scenario > RA_SCENARIO_AS_NO_DAA) + return false; + uint32_t param_count = ra_input->param_count; + if (param_count > PARAMS_RESERVED_COUNT) + return false; + uint32_t param_set_size = param_count * sizeof(struct ra_params) + sizeof(uint32_t); + if (param_set_size > out_size || param_set_size > SHAREMEM_LIMIT) + return false; + return true; +} + +static TEE_Result qta_provision(uint32_t param_types, TEE_Param *params) +{ + TEE_Result ret; + bool check_ret = check_param_type(param_types, TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + if (!check_ret || params == NULL) { + tloge("qta provision: qta provision bad params\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + + uint32_t out_size = params[0].memref.size; + if (params[0].memref.buffer == NULL || out_size == 0 || out_size < sizeof(struct provision_input_params)) { + tloge("qta provision: invalid memref buffer and size\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + struct provision_input_params *ra_input = (struct provision_input_params *)params[0].memref.buffer; + if (check_provision_input_params(ra_input, out_size) == false) { + tloge("qta provision: bad params\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + uint8_t *output = TEE_Malloc(out_size, 0); + if (output == NULL) { + tloge("qta provision: malloc provision buffer failed\n"); + return TEE_ERROR_OUT_OF_MEMORY; + } + + struct qsi_provision_params provision_params; + (void)memset_s(&provision_params, sizeof(provision_params), 0, sizeof(provision_params)); + provision_params.scenario = ra_input->scenario; + provision_params.param_set_size = ra_input->param_count * sizeof(struct ra_params) + sizeof(uint32_t); + provision_params.param_set = (uint8_t *)&(ra_input->param_count); + provision_params.out_data = output; + provision_params.out_size = out_size; + + tlogi("qta provision: provision begin\n"); + ret = ra_qsi_provision(&provision_params); + if (ret != TEE_SUCCESS) { + tloge("qta provision: provision failed, ret 0x%x\n", ret); + goto clear; + } + out_size = provision_params.out_size; + if (memcpy_s((void *)params[0].memref.buffer, params[0].memref.size, output, out_size) != EOK) { + tloge("qta provision: copy out data failed\n"); + TEE_Free(output); + return TEE_ERROR_GENERIC; + } + params[1].value.a = out_size; + tlogi("qta provision: provision end, out size = %u\n", out_size); +clear: + TEE_Free(output); + return ret; +} + +static bool check_report_input_params(struct report_input_params *ra_input, uint32_t out_size) +{ + if (out_size < REPORT_RESERVED_SIZE || out_size > SHAREMEM_LIMIT) + return false; + if (ra_input->user_size > USER_DATA_SIZE || ra_input->user_size == 0) + return false; + uint32_t param_count = ra_input->param_count; + if (param_count > PARAMS_RESERVED_COUNT) + return false; + uint32_t param_set_size = param_count * sizeof(struct ra_params) + sizeof(uint32_t); + if (param_set_size > out_size || param_set_size > SHAREMEM_LIMIT) + return false; + return true; +} + +static TEE_Result qta_report(uint32_t param_types, TEE_Param *params) +{ + TEE_Result ret; + bool check_ret = check_param_type(param_types, TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + if (!check_ret || params == NULL) { + tloge("qta report: bad params\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + + uint32_t out_size = params[0].memref.size; + if (params[0].memref.buffer == NULL || out_size == 0 || out_size < sizeof(struct report_input_params)) { + tloge("qta report: invalid memref buffer and size\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + struct report_input_params *ra_input = (struct report_input_params *)params[0].memref.buffer; + if (check_report_input_params(ra_input, out_size) == false) { + tloge("qta report: bad memref size params\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + + void *output = (void *)TEE_Malloc(out_size, 0); + if (output == NULL) { + tloge("qta report: malloc report buffer failed.\n"); + return TEE_ERROR_OUT_OF_MEMORY; + } + struct qsi_report_params ra_params; + (void)memset_s(&ra_params, sizeof(ra_params), 0, sizeof(ra_params)); + ra_params.uuid = ra_input->uuid; + ra_params.user_data = ra_input->user_data; + ra_params.user_size = ra_input->user_size; + ra_params.report = output; + ra_params.report_size = out_size; + ra_params.with_tcb = ra_input->with_tcb; + ra_params.param_set = (uint8_t *)&(ra_input->param_count); + ra_params.param_set_size = ra_input->param_count * sizeof(struct ra_params) + sizeof(uint32_t); + + ret = ra_qsi_report(&ra_params); + if (ret != TEE_SUCCESS) { + tloge("qta report: ra failed, ret 0x%x\n", ret); + goto err; + } + tlogi("qta report end, msg from qsi length = %u\n", ra_params.report_size); + out_size = ra_params.report_size; + + if(memcpy_s((void *)params[0].memref.buffer, params[0].memref.size, output, out_size) != EOK) { + tloge("qta report: memcpy buffer failed\n"); + TEE_Free(output); + return TEE_ERROR_GENERIC; + } + params[1].value.a = out_size; +err: + TEE_Free(output); + return ret; +} + +static bool check_save_akcert_params(struct qsi_save_akcert_params *akcert_params) +{ + if (akcert_params->buffer == NULL || akcert_params->length == 0 || + akcert_params->length > SAVE_AKCERT_RESERVED_SIZE) + return false; + return true; +} + +static TEE_Result qta_save_akcert(uint32_t param_types, TEE_Param *params) +{ + TEE_Result ret; + bool check_ret = check_param_type(param_types, TEE_PARAM_TYPE_MEMREF_INOUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, TEE_PARAM_TYPE_NONE, TEE_PARAM_TYPE_NONE); + if (!check_ret || params == NULL) { + tloge("qta save akcert: bad params\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + if (params[0].memref.buffer == NULL || params[0].memref.size == 0 || params[0].memref.size > SHAREMEM_LIMIT) { + tloge("qta save akcert: null param memref buffer and size\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + uint32_t *out_size = &(params[1].value.a); + struct qsi_save_akcert_params akcert_params; + (void)memset_s(&akcert_params, sizeof(akcert_params), 0, sizeof(akcert_params)); + akcert_params.buffer = (void *)params[0].memref.buffer; + akcert_params.length = params[0].memref.size; + if (check_save_akcert_params(&akcert_params) == false) { + tloge("qta save akcert: bad akcert params\n"); + return TEE_ERROR_BAD_PARAMETERS; + } + tlogi("qta save akcert: save akcert into tee begin\n"); + + ret = ra_qsi_save_akcert(&akcert_params); + if (ret != TEE_SUCCESS) { + tloge("qta save akcert: save ak cert failed, ret 0x%x\n", ret); + return ret; + } + *out_size = akcert_params.length; + tlogi("qta save akcert end\n"); + return TEE_SUCCESS; +} + +static bool check_caller_perm(uint32_t cmd_id) +{ + TEE_Result ret; + caller_info cinfo = { 0 }; + ret = TEE_EXT_GetCallerInfo(&cinfo, sizeof(cinfo)); + if (ret != TEE_SUCCESS) + return false; + if (cinfo.session_type == SESSION_FROM_TA) { + if (cmd_id == CMD_REQUEST_REPORT) + return true; + else + return false; + } + + return true; +} + +TEE_Result TA_InvokeCommandEntryPoint(void *session_context, uint32_t cmd_id, + uint32_t param_types, TEE_Param params[4]) +{ + tlogi("Enter TA_InvokeCommandEntryPoint\n"); + (void)session_context; + TEE_Result ret; + bool ckprm_ret = false; + + ckprm_ret = check_caller_perm(cmd_id); + if (!ckprm_ret) { + tloge("pls check permission!\n"); + return TEE_ERROR_ACCESS_DENIED; + } + + tlogi("cmd_id is 0x%x start\n", cmd_id); + switch (cmd_id) { + case CMD_INIT_PROVISION: + ret = qta_provision(param_types, params); + break; + case CMD_REQUEST_REPORT: + ret = qta_report(param_types, params); + break; + case CMD_SAVE_AKCERT: + ret = qta_save_akcert(param_types, params); + break; + default: + ret = TEE_ERROR_INVALID_CMD; + break; + } + if (ret != TEE_SUCCESS) + tloge("tee_qta: InvokeCommandEntryPoint failed, cmd: 0x%x, ret: 0x%x\n", cmd_id, ret); + else + tlogi("tee_qta: InvokeCommandEntryPoint success\n"); + return ret; +} + +void TA_CloseSessionEntryPoint(void *session_context) +{ + (void)session_context; + tlogi("tee_qta: CloseSessionEntryPoint success.\n"); +} + +void TA_DestroyEntryPoint(void) +{ + tlogi("tee_qta: DestroyEntryPoint success.\n"); +} diff --git a/test/TA/qta/src/tee_qta.h b/test/TA/qta/src/tee_qta.h new file mode 100644 index 0000000..e036cb4 --- /dev/null +++ b/test/TA/qta/src/tee_qta.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * iTrustee licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#ifndef TEE_QTA_H +#define TEE_QTA_H +#include +#include + +#define PARAMS_RESERVED_COUNT 1 +#define SHAREMEM_LIMIT 0x100000 /* maximum param size 1M */ +#define PROVISION_RESERVED_SIZE (0x1000) /* minimum provision size is 4K */ +#define REPORT_RESERVED_SIZE (0x3000) /* minimum report size is 12K */ +#define SAVE_AKCERT_RESERVED_SIZE (0x2000) /* maximum akcert size is 8K */ + +enum qta_cmd_id { + CMD_INIT_PROVISION = 0x1001, + CMD_REQUEST_REPORT = 0x1002, + CMD_SAVE_AKCERT = 0x1003, +}; + +#define USER_DATA_SIZE 64 +/* scenario number */ +#define RA_SCENARIO_NO_AS 0 +#define RA_SCENARIO_AS_NO_DAA 1 +#define RA_SCENARIO_AS_WITH_DAA 2 + +struct ra_data_offset { + uint32_t data_len; + uint32_t data_offset; +}; + +struct ra_params { + uint32_t tags; + union { + uint32_t integer; + struct ra_data_offset blob; + } data; +} __attribute__((__packed__)); + +struct report_input_params { + TEE_UUID uuid; + uint8_t user_data[USER_DATA_SIZE]; + uint32_t user_size; + bool with_tcb; + uint32_t param_count; + struct ra_params params[0]; +} __attribute__((__packed__)); + +struct provision_input_params { + uint32_t scenario; + uint32_t param_count; + struct ra_params params[0]; +} __attribute__((__packed__)); + + +#endif \ No newline at end of file -- Gitee