Projects
Eulaceura:Factory
secGear
_service:obs_scm:0049-support-switchless-featur...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:0049-support-switchless-feature.patch of Package secGear
From 7fffcb9aab60237a46540835731f03ddcad5fad9 Mon Sep 17 00:00:00 2001 From: houmingyong <houmingyong@huawei.com> Date: Fri, 9 Sep 2022 19:37:51 +0800 Subject: [PATCH] support switchless feature --- CMakeLists.txt | 63 +- README.md | 588 +++++++----------- examples/CMakeLists.txt | 2 + examples/switchless/CMakeLists.txt | 38 ++ examples/switchless/README.md | 118 ++++ examples/switchless/enclave/CMakeLists.txt | 181 ++++++ .../switchless/enclave/Enclave.config.xml | 13 + examples/switchless/enclave/Enclave.lds | 12 + examples/switchless/enclave/config_cloud.ini | 50 ++ examples/switchless/enclave/enclave.c | 30 + examples/switchless/enclave/manifest.txt | 7 + examples/switchless/host/CMakeLists.txt | 108 ++++ examples/switchless/host/main.c | 102 +++ examples/switchless/switchless.edl | 22 + .../switchless_performance/CMakeLists.txt | 89 +++ examples/switchless_performance/README.md | 118 ++++ .../enclave/CMakeLists.txt | 169 +++++ .../enclave/Enclave.config.xml | 13 + .../enclave/Enclave.lds | 12 + .../enclave/config_cloud.ini | 50 ++ .../switchless_performance/enclave/enclave.c | 37 ++ .../enclave/manifest.txt | 8 + .../host/CMakeLists.txt | 94 +++ examples/switchless_performance/host/main.c | 132 ++++ .../switchless_performance/switchless.edl | 24 + inc/common_inc/bit_operation.h | 86 +++ inc/common_inc/gp/gp_shared_memory_defs.h | 59 ++ inc/common_inc/secgear_list.h | 91 +++ inc/common_inc/switchless_defs.h | 88 +++ inc/enclave_inc/gp/gp.h | 1 + inc/enclave_inc/gp/itrustee/random_internal.h | 1 - inc/host_inc/enclave.h | 37 +- inc/host_inc/enclave_internal.h | 28 + inc/host_inc/enclave_log.h | 1 - inc/host_inc/secgear_defs.h | 44 ++ inc/host_inc/secgear_shared_memory.h | 48 ++ inc/host_inc/secgear_uswitchless.h | 83 +++ inc/host_inc/sgx/secgear_tswitchless.edl | 2 + inc/host_inc/status.h | 13 + src/enclave_src/CMakeLists.txt | 3 +- src/enclave_src/gp/gp.c | 5 +- src/enclave_src/gp/itrustee/CMakeLists.txt | 38 +- .../gp/itrustee/itrustee_shared_memory.c | 236 +++++++ .../gp/itrustee/itrustee_tswitchless.c | 258 ++++++++ .../gp/itrustee/itrustee_tswitchless.h | 46 ++ src/host_src/CMakeLists.txt | 15 +- src/host_src/enclave_internal.c | 7 +- src/host_src/gp/CMakeLists.txt | 15 +- src/host_src/gp/gp_enclave.c | 299 ++++++++- src/host_src/gp/gp_enclave.h | 4 +- src/host_src/gp/gp_shared_memory.c | 264 ++++++++ src/host_src/gp/gp_shared_memory.h | 66 ++ src/host_src/gp/gp_uswitchless.c | 200 ++++++ src/host_src/gp/gp_uswitchless.h | 132 ++++ src/host_src/secgear_shared_memory.c | 86 +++ src/host_src/sgx/CMakeLists.txt | 12 +- src/host_src/sgx/sgx_enclave.c | 43 +- src/host_src/sgx/sgx_shared_memory.c | 48 ++ src/host_src/sgx/sgx_shared_memory.h | 59 ++ tools/codegener/CMakeLists.txt | 15 +- tools/codegener/Codegener.ml | 6 +- tools/codegener/Commonfunc.ml | 41 ++ tools/codegener/Genheader.ml | 17 +- tools/codegener/Gentrust.ml | 74 ++- tools/codegener/Genuntrust.ml | 85 ++- tools/codegener/intel/Ast.ml | 2 +- tools/codegener/intel/CodeGen.ml | 209 ++++++- tools/codegener/intel/Edger8r.ml | 2 +- tools/codegener/intel/Lexer.mll | 2 +- tools/codegener/intel/Makefile | 2 +- tools/codegener/intel/Parser.mly | 2 +- tools/codegener/intel/Plugin.ml | 2 +- tools/codegener/intel/Preprocessor.ml | 8 +- tools/codegener/intel/SimpleStack.ml | 2 +- tools/codegener/intel/Util.ml | 12 +- 75 files changed, 4476 insertions(+), 503 deletions(-) create mode 100644 examples/switchless/CMakeLists.txt create mode 100644 examples/switchless/README.md create mode 100644 examples/switchless/enclave/CMakeLists.txt create mode 100644 examples/switchless/enclave/Enclave.config.xml create mode 100644 examples/switchless/enclave/Enclave.lds create mode 100644 examples/switchless/enclave/config_cloud.ini create mode 100644 examples/switchless/enclave/enclave.c create mode 100644 examples/switchless/enclave/manifest.txt create mode 100644 examples/switchless/host/CMakeLists.txt create mode 100644 examples/switchless/host/main.c create mode 100644 examples/switchless/switchless.edl create mode 100644 examples/switchless_performance/CMakeLists.txt create mode 100644 examples/switchless_performance/README.md create mode 100644 examples/switchless_performance/enclave/CMakeLists.txt create mode 100644 examples/switchless_performance/enclave/Enclave.config.xml create mode 100644 examples/switchless_performance/enclave/Enclave.lds create mode 100644 examples/switchless_performance/enclave/config_cloud.ini create mode 100644 examples/switchless_performance/enclave/enclave.c create mode 100644 examples/switchless_performance/enclave/manifest.txt create mode 100644 examples/switchless_performance/host/CMakeLists.txt create mode 100644 examples/switchless_performance/host/main.c create mode 100644 examples/switchless_performance/switchless.edl create mode 100644 inc/common_inc/bit_operation.h create mode 100644 inc/common_inc/gp/gp_shared_memory_defs.h create mode 100644 inc/common_inc/secgear_list.h create mode 100644 inc/common_inc/switchless_defs.h create mode 100644 inc/host_inc/secgear_defs.h create mode 100644 inc/host_inc/secgear_shared_memory.h create mode 100644 inc/host_inc/secgear_uswitchless.h create mode 100644 src/enclave_src/gp/itrustee/itrustee_shared_memory.c create mode 100644 src/enclave_src/gp/itrustee/itrustee_tswitchless.c create mode 100644 src/enclave_src/gp/itrustee/itrustee_tswitchless.h create mode 100644 src/host_src/gp/gp_shared_memory.c create mode 100644 src/host_src/gp/gp_shared_memory.h create mode 100644 src/host_src/gp/gp_uswitchless.c create mode 100644 src/host_src/gp/gp_uswitchless.h create mode 100644 src/host_src/secgear_shared_memory.c create mode 100644 src/host_src/sgx/sgx_shared_memory.c create mode 100644 src/host_src/sgx/sgx_shared_memory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b373328..2977702 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,9 +20,27 @@ set(LOCAL_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) set(SECGEAR_DEBUG_LEVEL SECGEAR_LOG_LEVEL_DEBUG) add_definitions(-DSECGEAR_DEBUG_LEVEL=${SECGEAR_DEBUG_LEVEL}) - -option(CC_GP "default off" OFF) -option(CC_SGX "default off" OFF) +message("=============cmake help info=======================") +message("Example default cmd: cmake ..") +message("same with default: cmake -DENCLAVE=SGX -DSDK_PATH=/opt/intel/sgxsdk -DSSL_PATH=/opt/intel/sgxssl ..") +message("cmake [-DCMAKE_BUILD_TYPE=val] [-DENCLAVE=val] [-DCC_SIM=ON] [-DSDK_PATH=path] [-DSSL_PATH=path] ..") +message("CMAKE_BUILD_TYPE:[optional] pass Debug if you need file line info in log, default log without file line") +message("ENCLAVE:[optional] valid val: SGX --default, GP --trustzone, PL --Penglai") +message("CC_SIM:[optional] only support by SGX") +message("SDK_PATH:[optional] default SGX:/opt/intel/sgxsdk, GP:/opt/itrustee_sdk, PL:/root/dev/sdk; + pass SDK_PATH if you installed sdk in custom path") +message("SSL_PATH:[optional] pass security ssl installed path when your application use ssl") +message("=============cmake help info=======================") +if (NOT DEFINED ENCLAVE) + set(ENCLAVE "SGX") +endif() +set(SGX_SDK_DEFAULT_PATH /opt/intel/sgxsdk) +set(GP_SDK_DEFAULT_PATH /opt/itrustee_sdk) +set(PL_SDK_DEFAULT_PATH /root/dev/sdk) + +set(SGX_SSL_DEFAULT_PATH /opt/intel/sgxssl) +set(GP_SSL_DEFAULT_PATH /opt/itrustee_sdk/itrustee_sdk_ssl) + if(CMAKE_BUILD_TYPE MATCHES "Debug") add_definitions(-DDEBUG_FILE_LINE) endif() @@ -31,30 +49,59 @@ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack") -if(CC_GP) +if(${ENCLAVE} STREQUAL "GP") + if (NOT DEFINED SDK_PATH) + set(iTrusteeSDK ${GP_SDK_DEFAULT_PATH}) + else() + set(iTrusteeSDK ${SDK_PATH}) + endif() + message("Current Platform: ARM Trustzone, iTrustee SDK PATH:${iTrusteeSDK}") if(NOT IS_DIRECTORY ${iTrusteeSDK}) message(FATAL_ERROR "Please provide the correct iTrusteeSDK path") endif() + set(CC_GP ON) endif() -if(CC_SGX) +if(${ENCLAVE} STREQUAL "SGX") + if (NOT DEFINED SDK_PATH) + set(SGXSDK ${SGX_SDK_DEFAULT_PATH}) + else() + set(SGXSDK ${SDK_PATH}) + endif() + message("Current Platform: Intel SGX, SGX SDK PATH:${SGXSDK}") if(NOT IS_DIRECTORY ${SGXSDK}) message(FATAL_ERROR "Please provide the correct SGXSDK path") endif() + set(CC_SGX ON) +endif() + +if(${ENCLAVE} STREQUAL "PL") + if (NOT DEFINED SDK_PATH) + set(PLSDK ${PL_SDK_DEFAULT_PATH}) + else() + set(PLSDK ${SDK_PATH}) + endif() + message("Current Platform: RISC-V, Penglai SDK PATH:${PLSDK}") + if(NOT IS_DIRECTORY ${PLSDK}) + message(FATAL_ERROR "Please provide the correct Penglai SDK path") + endif() + set(CC_PL ON) endif() add_subdirectory(tools/codegener) add_subdirectory(src) -execute_process(COMMAND mkdir ${LOCAL_ROOT_PATH}/bin) +if(NOT IS_DIRECTORY ${LOCAL_ROOT_PATH}/bin) + execute_process(COMMAND mkdir ${LOCAL_ROOT_PATH}/bin) +endif() add_subdirectory(examples) install(FILES ${LOCAL_ROOT_PATH}/conf/logrotate.d/secgear - DESTINATION /etc/logrotate.d/) + DESTINATION ${LOCAL_ROOT_PATH_INSTALL}/etc/logrotate.d/) install(FILES ${LOCAL_ROOT_PATH}/conf/rsyslog.d/secgear.conf - DESTINATION /etc/rsyslog.d/) + DESTINATION ${LOCAL_ROOT_PATH_INSTALL}/etc/rsyslog.d/) diff --git a/README.md b/README.md index 4c91875..6fd6848 100644 --- a/README.md +++ b/README.md @@ -6,444 +6,294 @@ secGear 介绍 ----------- -SecGear则是面向计算产业的机密计算安全应用开发套件。旨在方便开发者在不同的硬件设备上提供统一开发框架。目前secGear支持intel SGX硬件和Trustzone itrustee。 +secGear是面向计算产业的机密计算安全应用开发套件,旨在方便开发者在不同的硬件设备上提供统一开发框架。目前secGear支持intel SGX硬件,Trustzone itrustee,以及RISC-V 蓬莱TEE。 -构建、安装 + +HelloWorld运行样例 ---------------- -- [详见 构建、安装](./docs/build_install.md) +### Quick start with Intel SGX +#### 环境要求 +- 处理器:需要支持 Intel SGX (Intel Software Guard Extensions)功能 +- 操作系统:openEuler 21.03、openEuler 20.03 LTS SP2或更高版本 -开发应用和编译 ------------------------------- +#### Build and Run +``` +// intall build require +sudo yum install -y cmake ocaml-dune linux-sgx-driver sgxsdk libsgx-launch libsgx-urts -开发目录 .../secGear/examples/test/ +// clone secGear repository +git clone https://gitee.com/openeuler/secGear.git -### 1 编写edl接口文件 +// build secGear and examples +cd secGear +source /opt/intel/sgxsdk/environment && source environment +mkdir debug && cd debug && cmake .. && make && sudo make install - enclave { - include "secgear_urts.h" - from "secgear_tstdc.edl" import *; - trusted { - public int get_string([out, size=32]char *buf); - }; - }; -'include "secgear_urts.h" from "secgear_tstdc.edl" import *'是为了屏蔽SGX和iTrustee在调用libc库之间的差异。所以为了开发代码的一致性,默认导入这两个文件。 -有关edl语法的详细信息,请参阅SGX开发文档定义的EDL(Enclave Definition Language)语法部分。 -目前SGX和iTrustee在基本类型、指针类型和深拷贝方面是相互兼容的。对于user_check、private ecalls、switchless特性仅支持sgx硬件。 +// run helloworld +./examples/helloworld/host/secgear_helloworld -保存文件名为test.edl - -### 2 编写最外层CMakeLists.txt文件 - - cmake_minimum_required(VERSION 3.10 FATAL_ERROR) - project(TEST C) - set(CMAKE_C_STANDARD 99) - set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) - set(EDL_FILE test.edl) - set(LOCAL_ROOT_PATH "$ENV{CC_SDK}") - set(SECGEAR_INSTALL_PATH /usr/lib64/) - set(CODEGEN codegen) - if(CC_GP) - set(CODETYPE trustzone) - execute_process(COMMAND uuidgen -r OUTPUT_VARIABLE UUID) - string(REPLACE "\n" "" UUID ${UUID}) - add_definitions(-DPATH="/data/${UUID}.sec") - endif() - if(CC_SGX) - set(CODETYPE sgx) - add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so") - endif() - add_subdirectory(${CURRENT_ROOT_PATH}/enclave) - add_subdirectory(${CURRENT_ROOT_PATH}/host) - -EDL_FILE、CODETYPE:稍后自动构建的时候会用到这些属性。 -UUID:在iTrustee中,构建安全enclave动态库需要使用UUID命名,这里由uuidgen命令自动生成。 -DPATH:用于定义非安全侧使用安全侧动态库的绝对路径 - -### 3 编写非安全侧代码和CMakeLists.txt文件 - -#### 3.1 创建host目录和main.c文件 - - #include <stdio.h> - #include "enclave.h" - #include "test_u.h" - - #define BUF_LEN 32 - - int main() - { - int retval = 0; - char *path = PATH; - char buf[BUF_LEN]; - cc_enclave_t *context = NULL; - cc_enclave_result_t res; - - res = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &context); - ... - - res = get_string(context, &retval, buf); - if (res != CC_SUCCESS || retval != (int)CC_SUCCESS) { - printf("Ecall enclave error\n"); - } else { - printf("%s\n", buf); - } - - if (context != NULL) { - res = cc_enclave_destroy(context); - ... - } - return res; - } - -enclave.h: secGear库头文件 -test_u.h: 根据edl文件自动生成的非安全侧头文件。 -cc_enclave_create: 用于创建enclave安全上下文。 -get_string: 根据edl中trusted定义的安全侧代理函数,该代理函数用于进入到安全侧执行安全代码。 -cc_enclave_destroy: 用于销毁enclave安全上下文。 - -注意:这里调用的get_string函数与在edl中定义的get_string函数有些不同,这里的参数比edl中定义的多了前两个参数,分别是enclave安全上下文 -和retval参数。这是因为codegen(自动生成代码工具)通过edl生成的非安全侧代理函数,其声明在test_u.h中。 -如果在edl中定义的函数无返回值时,例如"public void get_string([out,size=32] char *buf);"则非安全侧代理函数为 -"res=get_string(context, buf)"(这里就不在有retval参数) - -#### 3.2 编写非安全侧CMakeLists.txt - - #set auto code prefix - set(PREFIX test) - #set host exec name - set(OUTPUT secgear_test) - #set host src code - set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.c) - -设置预备的基础变量 - - #set auto code - if(CC_GP) - set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) - add_custom_command(OUTPUT ${AUTO_FILES} - DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} - COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) - endif() +``` - if(CC_SGX) - set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) - add_custom_command(OUTPUT ${AUTO_FILES} - DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} - COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) - endif() +### Quick start with ARM TrustZone +#### 环境搭建 +- 参考[鲲鹏官网](https://support.huaweicloud.com/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0005.html#:~:text=%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA-,TA/CA%E5%BA%94%E7%94%A8%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA,-%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4%EF%BC%9A2022) +- 操作系统:openEuler 21.03、openEuler 20.03 LTS SP2或更高版本 -设置使用代码辅助生成工具根据edl文件生成辅助代码。CODEGEN和CODETYPE等变量定义在CMakeList.txt文件.--search-path用于搜索在edl文件中导入依赖的其他edl文件。 -当使用SGX时,需要导入sgx提供的基础edl,因此这里指定了SGXSDK的patch "--search-path ${SGXSDK}/include)"。 - - set(CMAKE_C_FLAGS "-fstack-protector-all -W -Wall -Werror -Wextra -Werror=array-bounds -D_FORTIFY_SOURCE=2 -O2 -ftrapv -fPIE") - set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack") - -设置编译选项和链接选项 - - if(CC_GP) - if(${CMAKE_VERSION} VERSION_LESS "3.13.0") - link_directories(${SECGEAR_INSTALL_PATH}) - endif() - add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) - target_include_directories(${OUTPUT} PRIVATE - ${LOCAL_ROOT_PATH}/inc/host_inc - ${LOCAL_ROOT_PATH}/inc/host_inc/gp - ${CMAKE_CURRENT_BINARY_DIR}) - if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") - target_link_directories(${OUTPUT} PRIVATE ${SECGEAR_INSTALL_PATH}) - endif() - endif() +#### Build and Run +``` +// intall build require +sudo yum install -y cmake ocaml-dune itrustee_sdk -在iTrustee硬件环境上,设置头文件的搜索路径及编译生成非安全侧二进制文件。 +// clone secGear repository +git clone https://gitee.com/openeuler/secGear.git - if(CC_SGX) - if(${CMAKE_VERSION} VERSION_LESS "3.13.0") - link_directories(${SECGEAR_INSTALL_PATH}) - endif() - add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) - target_include_directories(${OUTPUT} PRIVATE - ${LOCAL_ROOT_PATH}/inc/host_inc - ${LOCAL_ROOT_PATH}/inc/host_inc/sgx - ${CMAKE_CURRENT_BINARY_DIR}) - if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") - target_link_directories(${OUTPUT} PRIVATE ${SECGEAR_INSTALL_PATH}) - endif() - endif() +// build secGear and examples +cd secGear +source environment +mkdir debug && cd debug && cmake -DENCLAVE=GP .. && make && sudo make install -在SGX硬件环境上,设置头文件的搜索路径及编译生成非安全侧二进制文件。 - - if(CC_SIM) - target_link_libraries(${OUTPUT} secgearsim) - else() - target_link_libraries(${OUTPUT} secgear) - endif() - set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) - if(CC_GP) - install(TARGETS ${OUTPUT} - RUNTIME - DESTINATION /vendor/bin/ - PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) - endif() - if(CC_SGX) - install(TARGETS ${OUTPUT} - RUNTIME - DESTINATION ${CMAKE_BINARY_DIR}/bin/ - PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) - endif() +// run helloworld +/vendor/bin/secgear_helloworld +``` +HelloWorld开发流程 +------------------------------ -设置secGear链接库,当指定模拟模式CC_SIM时链接libsecgearsim.so,否则链接libsecgear.so。 -在iTrustee硬件环境上需指定安装固定的安全白名单。 +基于secGear API开发应用主要分为五个部分: +- EDL(Enclave Definition Language)接口文件 +- 非安全侧的代码 +- 调用codegen工具,根据EDL文件生成非安全侧与安全侧交互代码 +- 安全侧的代码的编写 +- 调用sign_tool.sh对安全侧编译出的so做签名 -### 4 编写安全侧代码、CMakeList.txt及基础配置文件 +以[HelloWorld](./examples/helloworld)样例源码为例详细介绍开发步骤。 -#### 4.1 创建enclave目录 编写hello.c +### 1 编写edl接口文件 +edl文件定义了非安全侧与安全侧交互的接口声明,类似于传统的头文件接口声明,由codegen辅助代码生成工具根据edl文件编译生成非安全侧与安全侧交互代码,从而帮助用户降低开发成本,聚焦业务逻辑。目前ocall仅在sgx平台支持,itrustee尚不支持。 - #include <stdio.h> - #include <string.h> - #include "test_t.h" +如下定义了ecall函数get_string。 - #define TA_HELLO_WORLD "secGear hello world!" - #define BUF_MAX 32 - int get_string(char *buf) - { - strncpy(buf, TA_HELLO_WORLD, strlen(TA_HELLO_WORLD) + 1); - return 0; - } +[参考 HelloWorld edl文件](./examples/helloworld/helloworld.edl) -test_t.h:该头文件为自动生成代码工具codegen通过edl文件生成的头文件。该头文件命名为edl文件名加"_t"。 +``` + enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + trusted { + public int get_string([out, size=32]char *buf); + }; + }; +``` -#### 4.2 编写CMakeList.txt文件 +'include "secgear_urts.h" from "secgear_tstdc.edl" import *'是为了屏蔽SGX和iTrustee在调用libc库之间的差异,为了开发代码的一致性,默认导入这两个文件。 - #set auto code prefix - set(PREFIX test) - #set sign key - set(PEM Enclave_private.pem) +有关edl语法的详细信息,请参阅SGX开发文档定义的EDL(Enclave Definition Language)语法部分。 -设置enclave签名私钥 +目前SGX和iTrustee在基本类型、指针类型和深拷贝方面是相互兼容的。对于user_check、private ecalls、switchless特性仅支持sgx硬件。 - #set sign tool - set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh) - #set enclave src code - set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/hello.c) - #set log level - set(PRINT_LEVEL 3) - add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) +### 2 编写非安全侧代码 +开发者在非安全侧需要完成如下步骤: +- 调用cc_enclave_create创建enclave +- 调用ecall函数 +- 调用cc_enclave_destroy销毁enclave -设置签名工具已经安全侧打印日志level +[参考 HelloWorld main.c文件](./examples/helloworld/host/main.c) +``` + // 创建enclave + res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, context); + ... - if(CC_GP) - #set signed output - set(OUTPUT ${UUID}.sec) + // 调用ecall函数,对应安全侧函数在enclave/hello.c中 + res = get_string(context, &retval, buf); + ... - set(WHITE_LIST_0 /vendor/bin/helloworld) - set(WHITE_LIST_1 /vendor/bin/secgear_test) - set(WHITE_LIST_OWNER root) - set(WHITELIST WHITE_LIST_0 WHITE_LIST_1) + // 销毁enclave + res = cc_enclave_destroy(context); +``` - set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) - add_custom_command(OUTPUT ${AUTO_FILES} - DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} - COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) - endif() +### 3 调用codegen工具 +[参考 HelloWorld host/CMakeLists.txt文件](./examples/helloworld/host/CMakeLists.txt) -WHITE_LIST_x:为设置iTrustee的二进制白名单,只有这里定义的白名单,在非安全侧的二进制才可以调用安全侧的动态库。上限为8个。 -WHITE_LIST_OWNER:为设置运行二进制的用户,只有该用户才可以调用安全侧动态库。 -AUTO_FILES:由edl文件生成的安全侧二进制文件 +Helloworld样例的编译工程已经集成codegen的调用,如下。 - if(CC_SGX) - set(OUTPUT enclave.signed.so) - set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c) - add_custom_command(OUTPUT ${AUTO_FILES} - DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} - COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) +``` + if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include) endif() - -设置自动生成代码及签名动态库。 - - set(COMMON_C_FLAGS "-W -Wall -Werror -fno-short-enums -fno-omit-frame-pointer -fstack-protector \ - -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \ - -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter \ - -Wno-error=unused-but-set-variable -Wno-error=format-truncation=") - - set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") - -设置安全侧便编译选项和链接选项。由于安全侧和非安全侧不同,非安全侧的标准动态库不能被安全侧链接。例如:"-nostdlib -nodefaultlibs -nostartfiles" +``` - if(CC_GP) - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt.in" "${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt") +### 4 编写安全侧代码 +开发者在安全侧需要完成: +- edl文件中定义的ecall函数的实现,edl文件相当于头文件 - set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC") - set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") +[参考 HelloWorld hello.c文件](./examples/helloworld/enclave/hello.c) - set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) - set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) +test_t.h:该头文件为自动生成代码工具codegen通过edl文件生成的头文件,该头文件命名为edl文件名加"_t"。 - if(${CMAKE_VERSION} VERSION_LESS "3.13.0") - link_directories(${SECGEAR_INSTALL_PATH}) - endif() +### 5 调用签名工具 - add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) +[参考 HelloWorld enclave/CMakeLists.txt文件](./examples/helloworld/enclave/CMakeLists.txt) - target_include_directories( ${PREFIX} PRIVATE - ${CMAKE_CURRENT_BINARY_DIR} - ${LOCAL_ROOT_PATH}/inc/host_inc - ${LOCAL_ROOT_PATH}/inc/host_inc/gp - ${LOCAL_ROOT_PATH}/inc/enclave_inc - ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp - ${ITRUSTEE_TEEDIR}/include/TA - ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext - ${ITRUSTEE_LIBC}/arch/aarch64 - ${ITRUSTEE_LIBC}/ - ${ITRUSTEE_LIBC}/arch/arm/bits - ${ITRUSTEE_LIBC}/arch/generic - ${ITRUSTEE_LIBC}/arch/arm - ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) +使用SIGN_TOOL对编译出的.so文件进行签名。 - if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") - target_link_directories(${PREFIX} PRIVATE ${SECGEAR_INSTALL_PATH}) - endif() - foreach(WHITE_LIST ${WHITELIST}) - add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}") - endforeach(WHITE_LIST) - add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") +switchless特性 +------------------------- - target_link_libraries(${PREFIX} -lsecgear_tee) +### 1 switchless特性介绍 +**技术定义:** switchless是一种通过共享内存减少REE与TEE上下文切换及数据拷贝次数,优化REE与TEE交互性能的技术。 - add_custom_command(TARGET ${PREFIX} - POST_BUILD - COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -i lib${PREFIX}.so -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini - -o ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT}) + **典型应用场景:** 传统应用做机密计算改造拆分成非安全侧CA与安全侧TA后 - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT} - DESTINATION /data - PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +- 当CA业务逻辑中存在频繁调用TA接口时,调用中间过程耗时占比较大,严重影响业务性能。 +- 当CA与TA存在频繁大块数据交换时,普通ECALL调用底层会有多次内存拷贝,导致性能低下。 + 针对以上两种典型场景,可以通过switchless优化交互性能,降低机密计算拆分带来的性能损耗,最佳效果可达到与拆分前同等数量级。 - endif() - -manifest.txt:itrustee安全侧配置文件,后面对该文件进行详解 -指定itrustee特性编译选项,设置引用头文件和动态库的路径。 -前面声明的白名单在这里定义。 -itrustee需要链接secgear_tee动态库,提供seal接口等。 + **支持硬件平台:** - if(CC_SGX) - set(SGX_DIR ${SGXSDK}) - set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden") - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") - set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64) - - if(CC_SIM) - set(Trts_Library_Name sgx_trts_sim) - set(Service_Library_Name sgx_tservice_sim) - else() - set(Trts_Library_Name sgx_trts) - set(Service_Library_Name sgx_tservice) - endif() - - set(Crypto_Library_Name sgx_tcrypto) - - set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \ - -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds") - - if(${CMAKE_VERSION} VERSION_LESS "3.13.0") - link_directories(${LINK_LIBRARY_PATH}) - endif() - - add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) - - target_include_directories(${PREFIX} PRIVATE - ${CMAKE_CURRENT_BINARY_DIR} - ${SGX_DIR}/include/tlibc - ${SGX_DIR}/include/libcxx - ${SGX_DIR}/include - ${LOCAL_ROOT_PATH}/inc/host_inc - ${LOCAL_ROOT_PATH}/inc/host_inc/sgx) - - if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") - target_link_directories(${PREFIX} PRIVATE - ${LINK_LIBRARY_PATH}) - endif() - - target_link_libraries(${PREFIX} -Wl,--whole-archive ${Trts_Library_Name} -Wl,--no-whole-archive - -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group) - add_custom_command(TARGET ${PREFIX} - POST_BUILD - COMMAND openssl genrsa -3 -out ${PEM} 3072 - COMMAND bash ${SIGN_TOOL} -d sign -x sgx -i lib${PREFIX}.so -k ${PEM} -o ${OUTPUT} -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml) - endif() +- Intel SGX +- ARM TrustZone 鲲鹏920 +### 2 约束限制 +虽然开启switchless节省了一定时间,但它们需要额外的线程来为调用提供服务。如果工作线程忙于等待消息,将会消耗大量CPU,另外更多的工作线程通常意味着更多的CPU资源竞争和更多的线程上下文切换,反而可能损害性能,所以switchless的最佳配置是经过实际业务模型与性能测试,在资源占用与性能要求中选出平衡点。 -在SGX硬件环境上,指定一些与sgx相关的编译选项、链接选项。链接动态库时有所不同,因为itrustee是一个具有更多功能的安全操作系统。提供如muslibc和openssl。在编译和链接itrustee时不用链接一些基本库,但是sgx没有OS概念。所以要在安全侧调用这些基本库的接口都要以静态的形式在sgxsdk中给出。例如"sgx_trts" +### 3 特性配置项规格 +用户调用cc_enclave_create创建Enclave时,需在feature参数中传入switchless的特性配置,配置项如下: +``` +typedef struct _cc_sl_config_t { + uint32_t num_uworkers; + uint32_t num_tworkers; + uint32_t switchless_calls_pool_size; + uint32_t retries_before_fallback; + uint32_t retries_before_sleep; + uint32_t parameter_num; +} cc_sl_config_t; +``` +各配置项规格如下表: -有关更多详细信息,请参阅sgx示例的Makefile。最后用enclave配置文件完成签名,稍后将进行介绍。secGear尚不支持远程身份验证。 +| 配置项 | 说明 | +| ------------ | ---- | +| num_uworkers | 非安全侧代理工作线程数,用于执行switchless OCALL,当前该字段仅在SGX平台生效,ARM平台可以配置,但是因ARM平台暂不支持OCALL,所以配置后不会生效。<br>规格: <br>ARM:最大值:512;最小值:1;默认值:8(配置为0时) <br>SGX:最大值:4294967295;最小值:1| +| num_tworkers | 安全侧代理工作线程数,用于执行switchless ECALL。<br>规格: <br>ARM:最大值:512;最小值:1;默认值:8(配置为0时) <br>SGX:最大值:4294967295;最小值:1| +| switchless_calls_pool_size | switchless调用任务池的大小,实际可容纳switchless_calls_pool_size * 64个switchless调用任务(例:switchless_calls_pool_size=1,可容纳64个switchless调用任务)。<br>规格:<br>ARM:最大值:8;最小值:1;默认值:1(配置为0时)<br>SGX:最大值:8;最小值:1;默认值:1(配置为0时)| +| retries_before_fallback | 执行retries_before_fallback次汇编pause指令后,若switchless调用仍没有被另一侧的代理工作线程执行,就回退到switch调用模式,该字段仅在SGX平台生效。<br>规格:br>SGX:最大值:4294967295;最小值:1;默认值:20000(配置为0时)| +| retries_before_sleep | 执行retries_before_sleep次汇编pause指令后,若代理工作线程一直没有等到有任务来,则进入休眠状态,该字段仅在SGX平台生效。<br>规格:<br>SGX:最大值:4294967295;最小值:1;默认值:20000(配置为0时)| +| parameter_num | switchless函数支持的最大参数个数,该字段仅在ARM平台生效,SGX平台无此限制。<br>规格:<br>ARM:最大值:16;最小值:0| -#### 4.3 编写安全侧配置文件 +### 4 switchless开发流程 +[参考 switchless README.md文件](./examples/switchless/README.md) -编写与sgx enclave相关的配置文件中Enclave.config.xml文件及enclave.lds文件与官方sgx配置相同。详情参阅官方开发文档。 +### 5 常见问题 +- sgx环境下开启switchless特性创建enclave后,直接销毁enclave会产生core dump -编写itrustee enclave相关配置文件 -mainfest.txt.in:其中gpd.ta.appID 为动态生成uuid。其他配置参见itrustee开发文档。 + sgx开启switchless需有一下两步: + + 1. cc_enclave_create时传入switchless feature参数 + 2. 在第一次ecall调用中初始化switchless线程调度 + + 如果没有调用ecall函数,就直接调用cc_enclave_destroy,会在sgx库中销毁switchless调度线程时异常。 + + 由于switchless的实际应用场景是存在频繁ecall调用,所以初始化switchless特性后,通常会有ecall调用,不会存在问题。 + +中间层组件使用指导 +------------------------- -#### 5 构建 安装 +secGear中间层提供了一些常用的安全组件,帮助用户快速构建安全应用。用户也可以基于secGear接口开发自己的组件,开发指导参考Helloworld样例,本节主要介绍基于secGear改造后的安全组件使用方法,以一个简单共享库为例说明。 -进入开发目录:cd .../secGear/example/test/ -创建debug目录:mkdir debug && cd debug -cmake构建:cmake -DCMAKE_BUILD_TYPE=Debug -DCC_SGX=ON -DSGXSDK=sgx_sdk path .. && make && sudo make install (sgx硬件环境) - cmake -DCMAKE_BUILD_TYPE=Debug -DCC_GP=ON -DiTrusteeSDK=gp_sdk path .. && make && sudo make install (itrustee硬件环境) +### 1 原始库 -Log ---- -非安全侧日志记录: +该库提供了compare_num函数,功能是比较两个数A和B的大小。该库的程序包含data_process.h和data_process.c文件,目录结构如下: -非安全侧是开发与普通开发环境一样,可使用通用打印日志接口。 +``` +. (编译生成data_process.so二进制) +├── data_process.c +└── data_process.h +``` -安全侧日志记录: +data_process.h为对外提供的接口文件,data_process.c为源码文件,两个文件的具体内容如下: -由于各架构安全能力不同的限制,为了像非安全侧一样开发使用日志打印功能,因为我们提供了PrintInfo接口将安全端日志记录到syslog系统中。 -相关配置文件为 conf/logrotate.d/secgear和conf/rsyslog.d/secgear.conf文件,安装时将安装在系统目录/etc/中。 +data_process.h文件: -注意:在itrustee上,需要include secgear_log.h头文件,但是sgx不需要,sgx通过ocall功能实现的,所以相关代码生成在辅助代码中。 -当文件安装成功后需要运行"systemctl restart rsyslog"使日志功能生效。 +```c +int compare_num(const int A); +``` -日志等级: +data_process.c文件: - PRINT_ERROR 0 - PRINT_WARNING 1 - PRINT_STRACE 2 - PRINT_DEBUG 3 +```c +static int B = 20; -使用ocall ---------- +int compare_num(const int A) { + return A >= B; +} +``` -目前ocall仅在sgx平台支持,itrustee尚不支持。 +在编译完成后源码文件会生成一个data_process.so动态库(或者静态库),data_process.h为用户提供函数声明。 -seal, generate_random接口 --------------------------------------- +### 2 基于secGear改造的secgear_data_process.so -接口定义在secgear_dataseal.h、secgear_random.h中。 -注意:由于itrustee派生密钥的功能仍然不完善,因此目前还没有与密封相关的接口在itrustee平台上支持。 +当数据B为用户隐私数据时,不希望计算平台或其他用户获取到该隐私数据,可以利用secGear将数据B及数据B的处理程序(compare_num函数)分离出来,放入enclave中执行,保护用户隐私不泄露。以下demo为了简化过程,数据B被硬编码在处理程序中(一般情况下B被加密后传入enclave中,在enclave中解密后与A比较,返回比较结果)。 -远程证明(尚不支持) --------------------------------------- +改造后代码由四部分组成:edl文件、安全侧程序(enclave)、非安全侧程序(host)和对外提供的头文件,改造后的目录结构为: -了解更多关于codegener --------------------------------------- +``` +. +├── data_process.edl +├── data_process.h +├── enclave (编译生成enclave.signed.so二进制) +│ └── sec_data_process.c // 实现ecall_compare_num +└── host (编译生成data_process.so二进制) + └── data_process.c // compare_num函数调用ecall_compare_num +``` -secGear引入EDL(Enclave Description Language)和中间代码辅助生成工具codegener。edl与intel sgx定义兼容。 +在编译后得到secgear_data_process.so文件,对外接口依然是compare_num。 +### 3 用户APP +用户APP在调用原始库与安全改造后的库函数时无变化,仅链接so时,链接secgear_data_process.so即可。 +用户APP使用改造后的组件库,无需再做机密计算安全改造,即可享受机密计算带来的安全,大大降低了用户开发成本。 -- [了解更多关于codegener](./docs/codegener.md) -了解更多关于sign_tool ------------------------------ - - -- [了解更多关于签名工具](./docs/sign_tool.md) +API清单 +------------------------------ -里程碑 ---------- -<img src="docs/milestone.png" alt="secGear" style="zoom:80%;" /> \ No newline at end of file +### 函数接口 +- host侧接口 + +| 接口 | 接口说明 | +| ---- | ---- | +| cc_enclave_create() | 用于创建安全侧的安全进程,针对安全区进程进行内存和相关上下文的初始化 | +| cc_enclave_destroy() | 用于销毁相关安全进程,对安全内存进行释放 | +| cc_enclave_get_sealed_data_size() | 用于获取加密后 sealed_data 数据占用的总大小,主要用于解密后需要分配的内存空间,安全侧与非安全侧皆可调用 | +| cc_malloc_shared_memory() | 用于开启switchless特性后,创建共享内存 | +| cc_free_shared_memory() | 用于开启switchless特性后,释放共享内存 | + +- enclave侧接口 + +| 接口 | 接口说明 | +| ---- | ---- | +| cc_enclave_get_sealed_data_size() | 用于获取加密后 sealed_data 数据占用的总大小,主要用于解密后需要分配的内存空间,安全侧与非安全侧皆可调用 | +| cc_enclave_get_encrypted_text_size() | 获取加密数据中加密消息的长度 | +| cc_enclave_unseal_data() | 用于解密 enclave 密封过的数据,用于将外部持久化数据重新导回 enclave 环境中 | +| cc_enclave_get_add_text_size() | 获取加密数数据中附加消息的长度 | +| cc_enclave_seal_data() | 用于加密 enclave 内部数据,使数据可以在 enclave 外部持久化存储 | +| cc_enclave_memory_in_enclave() | 用于校验指定长度的内存地址是否都属于安全侧内存 | +| cc_enclave_memory_out_enclave() | 用于校验指定长度的内存地址是否都属于非安全侧内存 | +| cc_enclave_generate_random() | 用于在安全侧生成密码安全的随机数 | +| PrintInfo() | 用于调试的日志分级打印功能 | + +### 文件接口 +- edl文件:用户需要通过edl文件定义非安全侧与安全侧交互接口原型。 + +### 工具接口 +| 接口 | 接口说明 | +| ---- | ---- | +| sign_tool.sh | sign_tool 包含 sign 指令(对 enclave 进行签名)和 digest 指令(生成摘要值) | +| codegen | 代码生成工具,根据edl文件编译生成非安全侧与安全侧交互代码 | + +[sign_tool.sh](./docs/sign_tool.md) 和[codegen](./docs/codegener.md)可使用-h打印帮助信息。 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 07fc0fb..a5112f1 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -12,6 +12,7 @@ if(CC_GP) COMMAND cp ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee/*.h ${CMAKE_BINARY_DIR}/inc/secGear/) add_subdirectory(seal_data) add_subdirectory(helloworld) + add_subdirectory(switchless) #add_subdirectory(lrt) endif() @@ -23,6 +24,7 @@ if(CC_SGX) COMMAND cp ${LOCAL_ROOT_PATH}/inc/enclave_inc/sgx/*.h ${CMAKE_BINARY_DIR}/inc/secGear/) add_subdirectory(seal_data) add_subdirectory(helloworld) + add_subdirectory(switchless) #add_subdirectory(tls_enclave) #add_subdirectory(lrt) endif() diff --git a/examples/switchless/CMakeLists.txt b/examples/switchless/CMakeLists.txt new file mode 100644 index 0000000..a215764 --- /dev/null +++ b/examples/switchless/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is 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. + +project(Switchless C) + +set(CMAKE_C_STANDARD 99) + +set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +#set edl name +set(EDL_FILE switchless.edl) +set(CODEGEN codegen) + +if(CC_GP) + set(CODETYPE trustzone) + set(UUID 7763a15a-0a9e-4e86-90cd-e4262583948a) + add_definitions(-DPATH="/data/${UUID}.sec") +endif() + +if(CC_SGX) + set(CODETYPE sgx) + add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so") +endif() + +if(CC_PL) + message(FATAL_ERROR "The PL platform does not support switchless.") +endif() + +add_subdirectory(${CURRENT_ROOT_PATH}/enclave) +add_subdirectory(${CURRENT_ROOT_PATH}/host) + diff --git a/examples/switchless/README.md b/examples/switchless/README.md new file mode 100644 index 0000000..f42a54e --- /dev/null +++ b/examples/switchless/README.md @@ -0,0 +1,118 @@ +<img src="../../docs/logo.png" alt="secGear" style="zoom:100%;" /> + +switchless +============================ + +介绍 +----------- + + **技术定义:** switchless是一种通过共享内存减少REE与TEE上下文切换及数据拷贝次数,优化REE与TEE交互性能的技术。 + + **典型应用场景:** 传统应用做机密计算改造拆分成非安全侧CA与安全侧TA后 + +- 当CA业务逻辑中存在频繁调用TA接口时,调用中间过程耗时占比较大,严重影响业务性能。 +- 当CA与TA存在频繁大块数据交换时,普通ECALL调用底层会有多次内存拷贝,导致性能低下。 + 针对以上两种典型场景,可以通过switchless优化交互性能,降低机密计算拆分带来的性能损耗,最佳效果可达到与拆分前同等数量级。 + + **支持硬件平台:** + +- Intel SGX +- ARM TrustZone 鲲鹏920 + +switchless开发流程 +------------------------------ + +基于secGear API开发应用的具体流程请参考[HelloWorld开发流程](../../README.md) + +以[switchless](../switchless)样例源码为例详细介绍switchless开发步骤。 + +### 1 编写edl接口文件 + +如下定义了ecall函数get_string_switchless。 + +[参考 switchless edl文件](./switchless.edl) + +``` + enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + from "secgear_tswitchless.edl" import *; + trusted { + public int get_string_switchless([out, size=32]char *buf) transition_using_threads; + }; + }; +``` + +switchless函数需添加'transition_using_threads'标识。 + +### 2 编写非安全侧代码 +开发者在非安全侧需要完成如下步骤: +- 调用cc_enclave_create创建enclave +- 调用cc_malloc_shared_memory创建共享内存 +- 调用ecall函数 +- 调用cc_free_shared_memory释放共享内存 +- 调用cc_enclave_destroy销毁enclave + +[参考 switchless main.c文件](./host/main.c) +``` + // 创建enclave + res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, &features, 1, context); + ... + + // 创建共享内存 + char *shared_buf = (char *)cc_malloc_shared_memory(context, BUF_LEN); + ... + + // 调用ecall函数,对应安全侧函数在enclave/enclave.c中 + res = get_string_switchless(context, &retval, shared_buf); + ... + + // 释放共享内存 + res = cc_free_shared_memory(context, shared_buf); + ... + + // 销毁enclave + res = cc_enclave_destroy(context); +``` +调用cc_enclave_create时,需传入switcheless特性对应参数“ENCLAVE_FEATURE_SWITCHLESS”,才能正常使用使用switchless特性。 +### 3 调用codegen工具 +[参考 switchless host/CMakeLists.txt文件](./host/CMakeLists.txt) + +switchless样例的编译工程已经集成codegen的调用,如下。 + +``` + if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path /usr/include/secGear + --search-path ${SGXSDK}/include) + endif() +``` + + +### 4 编写安全侧代码 +开发者在安全侧需要完成: +- edl文件中定义的ecall函数的实现,edl文件相当于头文件 + +[参考 switchless enclave.c文件](./enclave/enclave.c) + +test_t.h:该头文件为自动生成代码工具codegen通过edl文件生成的头文件,该头文件命名为edl文件名加"_t"。 + +### 5 调用签名工具 + +[参考 switchless enclave/CMakeLists.txt文件](./enclave/CMakeLists.txt) + +使用SIGN_TOOL对编译出的.so文件进行签名。 + +switchless API清单 +------------------------------ +### 函数接口 +- host侧接口 + +| 接口 | 接口说明 | +| ---- | ---- | +| cc_malloc_shared_memory() | 创建安全环境与非安全环境可同时访问的共享内存。<br>参数:<br>enclave,安全环境上下文句柄。因不同平台共享内存模型不同,同时保持接口跨平台的一致性,该参数仅在ARM平台被使用,SGX平台该入参会被忽略。<br>size,共享内存大小。<br>返回值:<br>NULL:共享内存申请失败。<br>其他:共享内存首地址<br> | +| cc_free_shared_memory() | 释放共享内存。<br>参数:<br>enclave,安全环境上下文句柄。因不同平台共享内存模型不同,同时保持接口跨平台的一致性,该参数仅在ARM平台被使用(该参数必须与调用cc_malloc_shared_memory接口时传入的enclave保持一致),SGX平台该入参会被忽略。<br>ptr:cc_malloc_shared_memory接口返回的共享内存地址。<br>返回值:<br>CC_ERROR_BAD_PARAMETERS,入参非法。 <br>CC_ERROR_INVALID_HANDLE, 无效enclave或者传入的enclave与ptr所对应的enclave不匹配(仅在ARM平台生效,SGX平台会忽略enclave,故不会对enclave进行检查)。 <br>CC_ERROR_NOT_IMPLEMENTED,该接口未实现。 <br>CC_ERROR_SHARED_MEMORY_START_ADDR_INVALID, <br>ptr不是cc_malloc_shared_memory接口返回的共享内存地址(仅在ARM平台生效)。 <br>CC_ERROR_OUT_OF_MEMORY,内存不足(仅在ARM平台生效)。 <br>CC_FAIL,一般性错误。 <br>CC_SUCCESS,成功。| diff --git a/examples/switchless/enclave/CMakeLists.txt b/examples/switchless/enclave/CMakeLists.txt new file mode 100644 index 0000000..1490f94 --- /dev/null +++ b/examples/switchless/enclave/CMakeLists.txt @@ -0,0 +1,181 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is 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. + +#set auto code prefix +set(PREFIX switchless) + +#set sign key +set(PEM Enclave_private.pem) + +#set sign tool +set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh) + +#set enclave src code +set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/enclave.c) + +#set log level +set(PRINT_LEVEL 3) +add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) + +if(CC_GP) + #set signed output + set(OUTPUT ${UUID}.sec) + set(WHITE_LIST_0 /vendor/bin/secgear_switchless) + set(WHITE_LIST_OWNER root) + set(WHITELIST WHITE_LIST_0) + + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h + ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c + ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(OUTPUT enclave.signed.so) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + --search-path ${SGXSDK}/include) +endif() + +if(CC_PL) + message(FATAL_ERROR "The PL platform does not support switchless.") +endif() + +set(COMMON_C_FLAGS "-W -Wall -Werror -fno-short-enums -fno-omit-frame-pointer -fstack-protector-strong \ + -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \ + -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter -D_FORTIFY_SOURCE=2 -O2 \ + -Wno-error=unused-but-set-variable -Wno-error=format-truncation=") + +set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") + +if(CC_GP) + + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC") + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") + + set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) + set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_BINARY_DIR}/lib/) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories( ${PREFIX} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR}/inc + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${LOCAL_ROOT_PATH}/inc/enclave_inc + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp + ${ITRUSTEE_TEEDIR}/include/TA + ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext + ${ITRUSTEE_LIBC}/arch/aarch64 + ${ITRUSTEE_LIBC}/ + ${ITRUSTEE_LIBC}/arch/arm/bits + ${ITRUSTEE_LIBC}/arch/generic + ${ITRUSTEE_LIBC}/arch/arm + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE ${CMAKE_BINARY_DIR}/lib/) + endif() + + foreach(WHITE_LIST ${WHITELIST}) + add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}") + endforeach(WHITE_LIST) + add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") + + target_link_libraries(${PREFIX} -lsecgear_tee) + + # for trustzone compiling, you should connact us to get config and private_key.pem for test, so we will not sign and install binary in this example # + # add_custom_command(TARGET ${PREFIX} + # POST_BUILD + # COMMAND bash ${SIGN_TOOL} -d sign + # -x trustzone + # -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so + # -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt + # -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini + # -o ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT}) + + # install(FILES ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT} + # DESTINATION /data + # PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +endif() + +if(CC_SGX) + set(SGX_DIR ${SGXSDK}) + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64) + + if(CC_SIM) + set(Trts_Library_Name sgx_trts_sim) + set(Service_Library_Name sgx_tservice_sim) + else() + set(Trts_Library_Name sgx_trts) + set(Service_Library_Name sgx_tservice) + endif() + + set(Crypto_Library_Name sgx_tcrypto) + + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \ + -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections \ + -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${LINK_LIBRARY_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories(${PREFIX} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${SGX_DIR}/include/tlibc + ${SGX_DIR}/include/libcxx + ${SGX_DIR}/include + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE ${LINK_LIBRARY_PATH}) + endif() + + target_link_libraries(${PREFIX} -Wl,--whole-archive -lsgx_tswitchless ${Trts_Library_Name} -Wl,--no-whole-archive + -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group) + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND umask 0177 + COMMAND openssl genrsa -3 -out ${PEM} 3072 + COMMAND bash ${SIGN_TOOL} -d sign + -x sgx + -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so + -k ${PEM} + -o ${OUTPUT} + -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml) +endif() + +if(NOT DEFINED CC_PL) + set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE) +endif() + +if(CC_PL) + message(FATAL_ERROR "The PL platform does not support switchless.") +endif() + diff --git a/examples/switchless/enclave/Enclave.config.xml b/examples/switchless/enclave/Enclave.config.xml new file mode 100644 index 0000000..f8908e2 --- /dev/null +++ b/examples/switchless/enclave/Enclave.config.xml @@ -0,0 +1,13 @@ +<EnclaveConfiguration> + <ProdID>0</ProdID> + <ISVSVN>0</ISVSVN> + <StackMaxSize>0x40000</StackMaxSize> + <HeapMaxSize>0x100000</HeapMaxSize> + <TCSNum>10</TCSNum> + <TCSPolicy>1</TCSPolicy> + <!-- Recommend changing 'DisableDebug' to 1 to make the enclave undebuggable for enclave release --> + <DisableDebug>0</DisableDebug> + <MiscSelect>0</MiscSelect> + <MiscMask>0xFFFFFFFF</MiscMask> +</EnclaveConfiguration> + diff --git a/examples/switchless/enclave/Enclave.lds b/examples/switchless/enclave/Enclave.lds new file mode 100644 index 0000000..0076dfb --- /dev/null +++ b/examples/switchless/enclave/Enclave.lds @@ -0,0 +1,12 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + local: + *; +}; + + diff --git a/examples/switchless/enclave/config_cloud.ini b/examples/switchless/enclave/config_cloud.ini new file mode 100644 index 0000000..8b6c858 --- /dev/null +++ b/examples/switchless/enclave/config_cloud.ini @@ -0,0 +1,50 @@ +[config] +;0 means debug +;1 means release +;[fixed value] +releaseType = 1 +;;; +;0 means TA not installed by OTRP +;1 means TA installed by OTRP +otrpFlag = 0 +;;; +;server address for signing TA +serverIp= +;;; +;public key for encrypt TA +;[fixed value] +encryptKey = cloud/rsa_public_key_cloud.pem +;;; +;public key length +;[fixed value] +encryptKeyLen = 3072 +;;; +;0 means not sign +;1 means signed by local private +;2 means signed using native sign tool; +;3 means signed by CI +;[fixed value] +signType = 1 +;;; +;private key for signing TA +;[private key owned by yourself] +signKey = ../../examples/helloworld/enclave/cert/private_key.pem +;;; +;private key length for signing TA +;[key length should be 4096 for security enhance] +signKeyLen = 4096 +;;; +;0 means SHA256 hash type +;1 means SHA512 hash type +;[set value to 0 by default] +hashType = 0 +;;; +;0 means padding type is pkcs1v15 +;1 means padding type is PSS +;[set value to 0 by default] +paddingType = 0 +;;; +;config file +;[signed config file by Huawei] +configPath= ../../examples/helloworld/enclave/signed_config/config + diff --git a/examples/switchless/enclave/enclave.c b/examples/switchless/enclave/enclave.c new file mode 100644 index 0000000..7ec4c86 --- /dev/null +++ b/examples/switchless/enclave/enclave.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 <stdio.h> +#include <string.h> +#include "switchless_t.h" + +#define TA_HELLO_WORLD "secgear hello world!" +#define BUF_MAX 32 +int get_string(char *buf) +{ + strncpy(buf, TA_HELLO_WORLD, strlen(TA_HELLO_WORLD) + 1); + return 0; +} + +int get_string_switchless(char *shared_buf) +{ + strncpy(shared_buf, TA_HELLO_WORLD, strlen(TA_HELLO_WORLD) + 1); + return 0; +} + diff --git a/examples/switchless/enclave/manifest.txt b/examples/switchless/enclave/manifest.txt new file mode 100644 index 0000000..a5825f0 --- /dev/null +++ b/examples/switchless/enclave/manifest.txt @@ -0,0 +1,7 @@ +gpd.ta.appID: f68fd704-6eb1-4d14-b218-722850eb3ef0 +gpd.ta.service_name: rsa-demo +gpd.ta.singleInstance: true +gpd.ta.multiSession: true +gpd.ta.instanceKeepAlive: false +gpd.ta.dataSize: 819200 +gpd.ta.stackSize: 40960 \ No newline at end of file diff --git a/examples/switchless/host/CMakeLists.txt b/examples/switchless/host/CMakeLists.txt new file mode 100644 index 0000000..98c4e73 --- /dev/null +++ b/examples/switchless/host/CMakeLists.txt @@ -0,0 +1,108 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is 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. + +#set auto code prefix +set(PREFIX switchless) +#set host exec name +set(OUTPUT secgear_switchless) +#set host src code +set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.c) + +#set auto code +if(CC_GP) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h + ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c + ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp) +endif() + +if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + --search-path ${SGXSDK}/include) +endif() + +if(CC_PL) + message(FATAL_ERROR "The PL platform does not support switchless.") +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + +if(CC_GP) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE ${CMAKE_BINARY_DIR}/inc + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SGX) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + ${SGXSDK}/include + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${SGXSDK}/lib64) + endif() +endif() + +if(CC_PL) + message(FATAL_ERROR "The PL platform does not support switchless.") +endif() + +if(CC_SIM) + target_link_libraries(${OUTPUT} secgearsim pthread) +else() + if(CC_GP) + target_link_libraries(${OUTPUT} secgear pthread) + endif() + if(CC_SGX) + target_link_libraries(${OUTPUT} secgear pthread -Wl,--whole-archive -lsgx_uswitchless -Wl,--no-whole-archive -lsgx_urts) + endif() +endif() +set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +if(CC_GP) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION /vendor/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + +if(CC_SGX) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION ${CMAKE_BINARY_DIR}/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + +if(CC_PL) + message(FATAL_ERROR "The PL platform does not support switchless.") +endif() + diff --git a/examples/switchless/host/main.c b/examples/switchless/host/main.c new file mode 100644 index 0000000..b39e5b8 --- /dev/null +++ b/examples/switchless/host/main.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 <stdio.h> +#include <unistd.h> +#include <linux/limits.h> +#include <sys/time.h> +#include <string.h> +#include "enclave.h" +#include "secgear_uswitchless.h" +#include "secgear_shared_memory.h" + +#include "switchless_u.h" + +#define BUF_LEN 32 + +int main() +{ + int retval = 0; + char *path = PATH; + char buf[BUF_LEN]; + cc_enclave_t *context = NULL; + context = (cc_enclave_t *)malloc(sizeof(cc_enclave_t)); + if (!context) { + return CC_ERROR_OUT_OF_MEMORY; + } + cc_enclave_result_t res = CC_FAIL; + + printf("Create secgear enclave\n"); + + char real_p[PATH_MAX]; + /* check file exists, if not exist then use absolute path */ + if (realpath(path, real_p) == NULL) { + if (getcwd(real_p, sizeof(real_p)) == NULL) { + printf("Cannot find enclave.sign.so"); + goto end; + } + if (PATH_MAX - strlen(real_p) <= strlen("/enclave.signed.so")) { + printf("Failed to strcat enclave.sign.so path"); + goto end; + } + (void)strcat(real_p, "/enclave.signed.so"); + } + + /* switchless configuration */ + cc_sl_config_t sl_cfg = CC_USWITCHLESS_CONFIG_INITIALIZER; + sl_cfg.num_tworkers = 2; /* 2 tworkers */ + sl_cfg.sl_call_pool_size_qwords = 2; /* 2 * 64 tasks */ + enclave_features_t features = {ENCLAVE_FEATURE_SWITCHLESS, (void *)&sl_cfg}; + + res = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, &features, 1, context); + if (res != CC_SUCCESS) { + printf("Create enclave error\n"); + goto end; + } + + char *shared_buf = (char *)cc_malloc_shared_memory(context, BUF_LEN); + if (shared_buf == NULL) { + printf("Malloc shared memory failed.\n"); + goto error; + } + + /* normal ecall */ + res = get_string(context, &retval, buf); + if (res != CC_SUCCESS || retval != (int)CC_SUCCESS) { + printf("Normal ecall error\n"); + } else { + printf("buf: %s\n", buf); + } + + /* switchless ecall */ + res = get_string_switchless(context, &retval, shared_buf); + if (res != CC_SUCCESS || retval != (int)CC_SUCCESS) { + printf("Switchless ecall error\n"); + } else { + printf("shared_buf: %s\n", shared_buf); + } + + res = cc_free_shared_memory(context, shared_buf); + if (res != CC_SUCCESS) { + printf("Free shared memory failed:%x.\n", res); + } + +error: + res = cc_enclave_destroy(context); + if(res != CC_SUCCESS) { + printf("Destroy enclave error\n"); + } +end: + free(context); + return res; +} + diff --git a/examples/switchless/switchless.edl b/examples/switchless/switchless.edl new file mode 100644 index 0000000..56f09ec --- /dev/null +++ b/examples/switchless/switchless.edl @@ -0,0 +1,22 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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. + */ + +enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + from "secgear_tswitchless.edl" import *; + trusted { + public int get_string([out, size=32]char *buf); + public int get_string_switchless([out, size=32]char *buf) transition_using_threads; + }; +}; + diff --git a/examples/switchless_performance/CMakeLists.txt b/examples/switchless_performance/CMakeLists.txt new file mode 100644 index 0000000..bb5c1fc --- /dev/null +++ b/examples/switchless_performance/CMakeLists.txt @@ -0,0 +1,89 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is 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. + +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) + +project(switchless C) + +set(CMAKE_C_STANDARD 99) + +if (NOT DEFINED ENCLAVE) +set(ENCLAVE "SGX") +endif() +set(SGX_SDK_DEFAULT_PATH /opt/intel/sgxsdk) +set(GP_SDK_DEFAULT_PATH /opt/itrustee_sdk) +set(PL_SDK_DEFAULT_PATH /root/dev/sdk) + +set(SGX_SSL_DEFAULT_PATH /opt/intel/sgxssl) +set(GP_SSL_DEFAULT_PATH /opt/itrustee_sdk/itrustee_sdk_ssl) + +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + +if(${ENCLAVE} STREQUAL "GP") +if (NOT DEFINED SDK_PATH) +set(iTrusteeSDK ${GP_SDK_DEFAULT_PATH}) +else() +set(iTrusteeSDK ${SDK_PATH}) +endif() +message("Current Platform: ARM Trustzone, iTrustee SDK PATH:${iTrusteeSDK}") +if(NOT IS_DIRECTORY ${iTrusteeSDK}) +message(FATAL_ERROR "Please provide the correct iTrusteeSDK path") +endif() +set(CC_GP ON) +endif() + +if(${ENCLAVE} STREQUAL "SGX") +if (NOT DEFINED SDK_PATH) +set(SGXSDK ${SGX_SDK_DEFAULT_PATH}) +else() +set(SGXSDK ${SDK_PATH}) +endif() +message("Current Platform: Intel SGX, SGX SDK PATH:${SGXSDK}") +if(NOT IS_DIRECTORY ${SGXSDK}) +message(FATAL_ERROR "Please provide the correct SGXSDK path") +endif() +set(CC_SGX ON) +endif() + +if(${ENCLAVE} STREQUAL "PL") +if (NOT DEFINED SDK_PATH) +set(PLSDK ${PL_SDK_DEFAULT_PATH}) + else() +set(PLSDK ${SDK_PATH}) +endif() +message("Current Platform: RISC-V, Penglai SDK PATH:${PLSDK}") +if(NOT IS_DIRECTORY ${PLSDK}) +message(FATAL_ERROR "Please provide the correct Penglai SDK path") +endif() +set(CC_PL ON) +endif() + +set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +#set edl name +set(EDL_FILE switchless.edl) +set(CODEGEN codegen) + +if(CC_GP) + set(CODETYPE trustzone) + set(UUID ebc87fc2-05dc-41b3-85b9-f9f0ef481bad) + #add_definitions(-DPATH="/data/${UUID}.sec") + add_definitions(-DPATH="${LOCAL_ROOT_PATH_INSTALL}/data/${UUID}.sec") +endif() + +if(CC_SGX) + set(CODETYPE sgx) + add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so") +endif() + + +add_subdirectory(${CURRENT_ROOT_PATH}/enclave) +add_subdirectory(${CURRENT_ROOT_PATH}/host) + diff --git a/examples/switchless_performance/README.md b/examples/switchless_performance/README.md new file mode 100644 index 0000000..2c8e401 --- /dev/null +++ b/examples/switchless_performance/README.md @@ -0,0 +1,118 @@ +<img src="docs/logo.png" alt="secGear" style="zoom:100%;" /> + +switchless +============================ + +介绍 +----------- + +Switchless方案是通过共享内存减少安全侧与非安全侧交互中数据拷贝次数来实现,将调用的数据写入共享内存,安全侧去访问并监控共享内存,发现有变化了,线程就去处理,这样减少上下文切换和数据拷贝的开销,大幅提升性能。 + +switchless开发流程 +------------------------------ + +基于secGear API开发应用的具体流程请参考[HelloWorld开发流程](../../README.md) + +以[switchless](../switchless)样例源码为例详细介绍switchless开发步骤。 + +### 1 编写edl接口文件 + +如下定义了ecall函数test_toupper。 + +[参考 switchless edl文件](./switchless.edl) + +``` + enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + trusted { + public void test_toupper([in, out, size=len]char *buf, int len) transition_using_threads; + }; + }; +``` + +switchless函数需添加'transition_using_threads'标识。 + +### 2 编写非安全侧代码 +开发者在非安全侧需要完成如下步骤: +- 调用cc_enclave_create创建enclave +- 调用cc_malloc_shared_memory创建共享内存 +- 调用cc_register_shared_memory注册共享内存 +- 调用ecall函数 +- 调用cc_unregister_shared_memory去注册共享内存 +- 调用cc_free_shared_memory释放共享内存 +- 调用cc_enclave_destroy销毁enclave + +[参考 switchless main.c文件](./host/main.c) +``` + // 创建enclave + ret = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, features, 1, &g_enclave); + ... + + // 创建共享内存 + char *buf = (char *)cc_malloc_shared_memory(&g_enclave, len); + ... + + // 注册共享内存 + ret = cc_register_shared_memory(&g_enclave, buf); + ... + + // 调用ecall函数,对应安全侧函数在enclave/enclave.c中 + test_toupper(&g_enclave, buf, strlen(TEST_STR)); + ... + + // 去注册共享内存 + ret = cc_unregister_shared_memory(&g_enclave, buf); + ... + + // 释放共享内存 + ret = cc_free_shared_memory(&g_enclave, buf); + ... + + // 销毁enclave + res = cc_enclave_destroy(context); +``` + +### 3 调用codegen工具 +[参考 switchless host/CMakeLists.txt文件](./host/CMakeLists.txt) + +switchless样例的编译工程已经集成codegen的调用,如下。 + +``` + if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path /usr/include/secGear + --search-path ${SGXSDK}/include) + endif() +``` + + +### 4 编写安全侧代码 +开发者在安全侧需要完成: +- edl文件中定义的ecall函数的实现,edl文件相当于头文件 + +[参考 switchless enclave.c文件](./enclave/enclave.c) + +test_t.h:该头文件为自动生成代码工具codegen通过edl文件生成的头文件,该头文件命名为edl文件名加"_t"。 + +### 5 调用签名工具 + +[参考 switchless enclave/CMakeLists.txt文件](./enclave/CMakeLists.txt) + +使用SIGN_TOOL对编译出的.so文件进行签名。 + +switchless API清单 +------------------------------ +### 函数接口 +- host侧接口 + +| 接口 | 接口说明 | +| ---- | ---- | +| cc_malloc_shared_memory() | 创建共享内存 | +| cc_free_shared_memory() | 释放共享内存 | +| cc_register_shared_memory() | 注册共享内存 | +| cc_unregister_shared_memory() | 去注册共享内存 | diff --git a/examples/switchless_performance/enclave/CMakeLists.txt b/examples/switchless_performance/enclave/CMakeLists.txt new file mode 100644 index 0000000..69aab4c --- /dev/null +++ b/examples/switchless_performance/enclave/CMakeLists.txt @@ -0,0 +1,169 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is 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. + +#set auto code prefix +set(PREFIX switchless) + +#set sign key +set(PEM Enclave_private.pem) + +#set sign tool +set(SIGN_TOOL sign_tool.sh) + +#set enclave src code +set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/enclave.c) + +#set log level +set(PRINT_LEVEL 3) +add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) + +if(CC_GP) + #set signed output + set(OUTPUT ${UUID}.sec) + #set whilelist. default: ${LOCAL_ROOT_PATH_INSTALL}/vendor/bin/teec_hello + set(WHITE_LIST_0 ${LOCAL_ROOT_PATH_INSTALL}/vendor/bin/secgear_switchless) + set(WHITE_LIST_OWNER root) + set(WHITELIST WHITE_LIST_0) + + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h + ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c + ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path /usr/include/secGear) +endif() + +if(CC_SGX) + set(OUTPUT enclave.signed.so) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path /usr/include/secGear + --search-path ${SGXSDK}/include) +endif() + +set(COMMON_C_FLAGS "-W -Wall -Werror -fno-short-enums -fno-omit-frame-pointer -fstack-protector-strong \ + -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \ + -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter -D_FORTIFY_SOURCE=2 -O2 \ + -Wno-error=unused-but-set-variable -L/usr/lib64 -Wno-error=format-truncation=") + +set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") + +if(CC_GP) + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC") + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") + + set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) + set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_BINARY_DIR}/lib/) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories( ${PREFIX} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR}/enclave + /usr/include/secGear + ${ITRUSTEE_TEEDIR}/include/TA + ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext + ${ITRUSTEE_LIBC}/arch/aarch64 + ${ITRUSTEE_LIBC}/ + ${ITRUSTEE_LIBC}/arch/arm/bits + ${ITRUSTEE_LIBC}/arch/generic + ${ITRUSTEE_LIBC}/arch/arm) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PUBLIC /usr/lib64) + endif() + + foreach(WHITE_LIST ${WHITELIST}) + add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}") + endforeach(WHITE_LIST) + add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") + + target_link_libraries(${PREFIX} secgear_tee) + + #for trustzone compiling, you should connact us to get config and private_key.pem for test, so we will not sign and install binary in this example # + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND bash ${SIGN_TOOL} -d sign + -x trustzone + -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so + -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt + -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini + -o ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT}) + + install(FILES ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT} + #DESTINATION /data + DESTINATION ${LOCAL_ROOT_PATH_INSTALL}/data + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +endif() + +if(CC_SGX) + set(SGX_DIR ${SGXSDK}) + set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64) + + if(CC_SIM) + set(Trts_Library_Name sgx_trts_sim) + set(Service_Library_Name sgx_tservice_sim) + else() + set(Trts_Library_Name sgx_trts) + set(Service_Library_Name sgx_tservice) + endif() + + set(Crypto_Library_Name sgx_tcrypto) + + set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \ + -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections \ + -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${LINK_LIBRARY_PATH}) + endif() + + add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES}) + + target_include_directories(${PREFIX} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + /usr/include/secGear + ${SGX_DIR}/include/tlibc + ${SGX_DIR}/include/libcxx + ${SGX_DIR}/include) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${PREFIX} PRIVATE ${LINK_LIBRARY_PATH}) + endif() + + target_link_libraries(${PREFIX} -Wl,--whole-archive -lsgx_tswitchless ${Trts_Library_Name} -Wl,--no-whole-archive -Wl,--start-group + -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group) + add_custom_command(TARGET ${PREFIX} + POST_BUILD + COMMAND umask 0177 + COMMAND openssl genrsa -3 -out ${PEM} 3072 + COMMAND bash ${SIGN_TOOL} -d sign + -x sgx + -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so + -k ${PEM} + -o ${OUTPUT} + -c ${CMAKE_CURRENT_SOURCE_DIR}/Enclave.config.xml) +endif() + +if(NOT DEFINED CC_PL) + set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE) +endif() + diff --git a/examples/switchless_performance/enclave/Enclave.config.xml b/examples/switchless_performance/enclave/Enclave.config.xml new file mode 100644 index 0000000..5d836c9 --- /dev/null +++ b/examples/switchless_performance/enclave/Enclave.config.xml @@ -0,0 +1,13 @@ +<EnclaveConfiguration> + <ProdID>0</ProdID> + <ISVSVN>0</ISVSVN> + <StackMaxSize>0x40000</StackMaxSize> + <HeapMaxSize>0x100000</HeapMaxSize> + <TCSNum>10</TCSNum> + <TCSPolicy>1</TCSPolicy> + <!-- Recommend changing DisableDebug to 1 to make the enclave undebuggable for enclave release --> + <DisableDebug>0</DisableDebug> + <MiscSelect>0</MiscSelect> + <MiscMask>0xFFFFFFFF</MiscMask> +</EnclaveConfiguration> + diff --git a/examples/switchless_performance/enclave/Enclave.lds b/examples/switchless_performance/enclave/Enclave.lds new file mode 100644 index 0000000..0076dfb --- /dev/null +++ b/examples/switchless_performance/enclave/Enclave.lds @@ -0,0 +1,12 @@ +enclave.so +{ + global: + g_global_data_sim; + g_global_data; + enclave_entry; + g_peak_heap_used; + local: + *; +}; + + diff --git a/examples/switchless_performance/enclave/config_cloud.ini b/examples/switchless_performance/enclave/config_cloud.ini new file mode 100644 index 0000000..a77c0a6 --- /dev/null +++ b/examples/switchless_performance/enclave/config_cloud.ini @@ -0,0 +1,50 @@ +[config] +;0 means debug +;1 means release +;[fixed value] +releaseType = 1 +;;; +;0 means TA not installed by OTRP +;1 means TA installed by OTRP +otrpFlag = 0 +;;; +;server address for signing TA +serverIp= +;;; +;public key for encrypt TA +;[fixed value] +encryptKey = rsa_public_key_cloud.pem +;;; +;public key length +;[fixed value] +encryptKeyLen = 3072 +;;; +;0 means not sign +;1 means signed by local private +;2 means signed using native sign tool; +;3 means signed by CI +;[fixed value] +signType = 1 +;;; +;private key for signing TA +;[private key owned by yourself] +signKey = private_key.pem +;;; +;private key length for signing TA +;[key length should be 4096 for security enhance] +signKeyLen = 4096 +;;; +;0 means SHA256 hash type +;1 means SHA512 hash type +;[set value to 0 by default] +hashType = 0 +;;; +;0 means padding type is pkcs1v15 +;1 means padding type is PSS +;[set value to 0 by default] +paddingType = 0 +;;; +;config file +;[signed config file by Huawei] +configPath= config + diff --git a/examples/switchless_performance/enclave/enclave.c b/examples/switchless_performance/enclave/enclave.c new file mode 100644 index 0000000..1320e53 --- /dev/null +++ b/examples/switchless_performance/enclave/enclave.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 <stdio.h> +#include <string.h> +#include "switchless_t.h" + + +void test_toupper(char *buf, int len) +{ + if (buf == NULL || len < 0) { + return; + } + + for (int i = 0; i < len; ++i) { + if (buf[i] >= 'a' && buf[i] <= 'z') { + buf[i] = buf[i] - ('a' - 'A'); + } + } +} + +void ecall_empty(void) +{ +} + +void ecall_empty_switchless(void) +{ +} diff --git a/examples/switchless_performance/enclave/manifest.txt b/examples/switchless_performance/enclave/manifest.txt new file mode 100644 index 0000000..2a69073 --- /dev/null +++ b/examples/switchless_performance/enclave/manifest.txt @@ -0,0 +1,8 @@ +gpd.ta.appID: ebc87fc2-05dc-41b3-85b9-f9f0ef481bad +gpd.ta.service_name:multi-core-ta +gpd.ta.singleInstance: true +gpd.ta.multiSession: true +gpd.ta.instanceKeepAlive:false +gpd.ta.dataSize: 8192000 +gpd.ta.stackSize: 7340032 + diff --git a/examples/switchless_performance/host/CMakeLists.txt b/examples/switchless_performance/host/CMakeLists.txt new file mode 100644 index 0000000..9299893 --- /dev/null +++ b/examples/switchless_performance/host/CMakeLists.txt @@ -0,0 +1,94 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +# secGear is 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. + +#set auto code prefix +set(PREFIX switchless) +#set host exec name +set(OUTPUT secgear_switchless) +#set host src code +set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.c) + +#set auto code +if(CC_GP) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h + ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c + ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path /usr/include/secGear) +endif() + +if(CC_SGX) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c) + add_custom_command(OUTPUT ${AUTO_FILES} + DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE} + COMMAND ${CODEGEN} --${CODETYPE} + --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} + --search-path /usr/include/secGear + --search-path ${SGXSDK}/include) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIE -L/usr/lib64") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") + +if(CC_GP) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE ${CMAKE_BINARY_DIR}/host + /usr/include/secGear + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE /usr/lib64 ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +endif() + +if(CC_SGX) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) + target_include_directories(${OUTPUT} PRIVATE /usr/include/secGear + /opt/intel/sgxsdk/include + ${CMAKE_CURRENT_BINARY_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${SGXSDK}/lib64) + endif() +endif() + +if(CC_SIM) + target_link_libraries(${OUTPUT} secgearsim pthread) +else() + if(CC_GP) + target_link_libraries(${OUTPUT} secgear pthread) + endif() + if(CC_SGX) + target_link_libraries(${OUTPUT} secgear pthread -Wl,--whole-archive -lsgx_uswitchless -Wl,--no-whole-archive -lsgx_urts) + endif() +endif() +set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +if(CC_GP) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION ${LOCAL_ROOT_PATH_INSTALL}/vendor/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + +if(CC_SGX) + install(TARGETS ${OUTPUT} + RUNTIME + DESTINATION ${CMAKE_BINARY_DIR}/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ) +endif() + diff --git a/examples/switchless_performance/host/main.c b/examples/switchless_performance/host/main.c new file mode 100644 index 0000000..f80db25 --- /dev/null +++ b/examples/switchless_performance/host/main.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 <stdio.h> +#include <unistd.h> +#include <stdbool.h> +#include <linux/limits.h> +#include "enclave.h" +#include "switchless_u.h" +#include "string.h" +#include "secgear_uswitchless.h" +#include "secgear_shared_memory.h" +#include <sys/time.h> + +cc_enclave_t g_enclave; + +bool init_enclave(enclave_features_t *features) +{ + char *path = PATH; + cc_enclave_result_t ret; + char real_p[PATH_MAX]; + + /* check file exists, if not exist then use absolute path */ + if (realpath(path, real_p) == NULL) { + if (getcwd(real_p, sizeof(real_p)) == NULL) { + printf("Cannot find enclave.sign.so"); + return false; + } + + if (PATH_MAX - strlen(real_p) <= strlen("/enclave.signed.so")) { + printf("Failed to strcat enclave.sign.so path"); + return false; + } + + (void)strcat(real_p, "/enclave.signed.so"); + } + + ret = cc_enclave_create(real_p, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, features, 1, &g_enclave); + if (ret != CC_SUCCESS) { + printf("Create enclave error: %d\n", ret); + return false; + } + + return true; +} + +void fini_enclave(cc_enclave_t *enclave) +{ + cc_enclave_result_t ret = cc_enclave_destroy(enclave); + if (ret != CC_SUCCESS) { + printf("Error: destroy enclave failed: %x\n", ret); + } +} + +void benchmark_ecall_empty(bool is_switchless, unsigned long nrepeats) +{ + struct timespec time_start; + struct timespec time_end; + struct timespec duration = {0, 0}; + cc_enclave_result_t(*ecall_fn)(cc_enclave_t *) = is_switchless ? ecall_empty_switchless : ecall_empty; + + clock_gettime(CLOCK_REALTIME, &time_start); + unsigned long tmp_nrepeats = nrepeats; + while (tmp_nrepeats--) { + ecall_fn(&g_enclave); + } + clock_gettime(CLOCK_REALTIME, &time_end); + + duration.tv_sec += time_end.tv_sec - time_start.tv_sec; + duration.tv_nsec += time_end.tv_nsec - time_start.tv_nsec; + + printf("Repeating an %s empty ecall for %lu times takes %lu.%09lus\n", + is_switchless ? "[switchless]" : "[ ordinary ]", nrepeats, duration.tv_sec, duration.tv_nsec); +} + +#define TEST_STR "switchless" + +void transfer_data_using_shared_memory() +{ + cc_enclave_result_t ret; + int len = 32; + + char *buf = (char *)cc_malloc_shared_memory(&g_enclave, len); + if (buf == NULL) { + printf("Error: malloc shared memory failed.\n"); + return; + } + + (void)strcpy(buf, TEST_STR); + printf("before test_toupper, buf=%s\n", buf); + test_toupper(&g_enclave, buf, strlen(TEST_STR)); + printf("after test_toupper, buf=%s\n\n", buf); + + ret = cc_free_shared_memory(&g_enclave, buf); + if (ret != CC_SUCCESS) { + printf("Error: free shared memory failed:%x.\n", ret); + } +} + +int main(void) +{ + cc_sl_config_t sl_cfg = CC_USWITCHLESS_CONFIG_INITIALIZER; + sl_cfg.num_tworkers = 2; /* 2 tworkers */ + sl_cfg.sl_call_pool_size_qwords = 2; /* 2 * 64 tasks */ + enclave_features_t features = {ENCLAVE_FEATURE_SWITCHLESS, (void *)&sl_cfg}; + + if (!init_enclave(&features)) { + printf("Error: init enclave failed\n"); + return -1; + } + + printf("\n1. Running a benchmark that compares [ordinary] and [switchless] ecall\n"); + unsigned long nrepeats = 100000; + benchmark_ecall_empty(false, nrepeats); + benchmark_ecall_empty(true, nrepeats); + + printf("\n2. Transfer data using shared memory\n"); + transfer_data_using_shared_memory(); + + fini_enclave(&g_enclave); + + return 0; +} diff --git a/examples/switchless_performance/switchless.edl b/examples/switchless_performance/switchless.edl new file mode 100644 index 0000000..344ee57 --- /dev/null +++ b/examples/switchless_performance/switchless.edl @@ -0,0 +1,24 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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. + */ + +enclave { + include "secgear_urts.h" + from "secgear_tstdc.edl" import *; + from "secgear_tswitchless.edl" import *; + trusted { + public void ecall_empty(void); + public void ecall_empty_switchless(void) transition_using_threads; + + public void test_toupper([in, out, size=len]char *buf, int len) transition_using_threads; + }; +}; + diff --git a/inc/common_inc/bit_operation.h b/inc/common_inc/bit_operation.h new file mode 100644 index 0000000..baa6a1b --- /dev/null +++ b/inc/common_inc/bit_operation.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 __BIT_OPERATION_H__ +#define __BIT_OPERATION_H__ + +#include <stdint.h> +#include <stdbool.h> +#include <assert.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef DEBUG + #define ASSERT(x) assert(x) +#else + #define ASSERT(x) ((void)0) +#endif + +/* + * Returns the number of trailing 0-bits in x, starting at the least significant bit position. + * If x is 0, the result is undefined. + */ +static inline uint32_t count_tailing_zeroes(uint64_t value) +{ + ASSERT(value != 0); + return (uint32_t)__builtin_ctzll(value); +} + +/* + * Returns the number of leading 0-bits in x, starting at the most significant bit position. + * If x is 0, the result is undefined. + */ +static inline uint32_t count_leading_zeroes(uint64_t value) +{ + ASSERT(value != 0); + return (uint32_t)__builtin_clzll(value); +} + +/* + * In the bitmap with the start address of addr, bit i is cleared if it is 1, and true is returned. + * Otherwise, false is returned. + */ +static inline bool test_and_clear_bit(volatile uint64_t *addr, uint32_t i) +{ + uint64_t old_val; + uint64_t new_val; + + while (true) { + old_val = *addr; + if ((old_val & (1UL << i)) == 0) { + break; + } + + new_val = old_val & (~(1UL << i)); + if (__atomic_compare_exchange(addr, &old_val, &new_val, 0, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) { + return true; + } + } + + return false; +} + +/* + * Set bit i in the bitmap whose start address is addr. + */ +static inline void set_bit(volatile uint64_t *addr, uint32_t i) +{ + (void)__atomic_or_fetch(addr, 1ULL << i, __ATOMIC_ACQUIRE); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/common_inc/gp/gp_shared_memory_defs.h b/inc/common_inc/gp/gp_shared_memory_defs.h new file mode 100644 index 0000000..87c9a13 --- /dev/null +++ b/inc/common_inc/gp/gp_shared_memory_defs.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 SHARED_MEMORY_DEFS_H +#define SHARED_MEMORY_DEFS_H + +#include <stdint.h> +#include <pthread.h> +#include "secgear_list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + size_t retval_size; // Size of variable retval + size_t shared_buf_size; // Size of variable shared_buf + size_t shared_buf_len_size; // Size of variable shared_buf_len + size_t is_control_buf_size; // Size of variable is_control_buf +} gp_register_shared_memory_size_t; + +typedef struct { + size_t retval_size; // Size of variable retval + size_t shared_buf_size; // Size of variable shared_buf +} gp_unregister_shared_memory_size_t; + +enum { + fid_register_shared_memory = 0, + fid_unregister_shared_memory = 1, +}; + +#define GP_SHARED_MEMORY_SIZE 64 + +typedef struct { + char shared_mem[GP_SHARED_MEMORY_SIZE]; // refer to TEEC_SharedMemory + bool is_control_buf; // whether it is a control area; otherwise, it is the data area used by the user + bool is_registered; // the shared memory can be used only after being registered + void *enclave; // refer to cc_enclave_t + pthread_t register_tid; + list_node_t node; +} gp_shared_memory_t; + +#define GP_SHARED_MEMORY_ENTRY(ptr) \ + ((gp_shared_memory_t *)((char *)(ptr) - sizeof(gp_shared_memory_t))) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/common_inc/secgear_list.h b/inc/common_inc/secgear_list.h new file mode 100644 index 0000000..a046af3 --- /dev/null +++ b/inc/common_inc/secgear_list.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 __SECGEAR_LIST_H__ +#define __SECGEAR_LIST_H__ + +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _list_node_t { + struct _list_node_t *prev; + struct _list_node_t *next; +} list_node_t; + +typedef list_node_t list_head_t; + +/* + * Initialize the linked list. + */ +static inline void list_init(list_node_t *head) +{ + head->prev = head; + head->next = head; +} + +/* + * Add a new node to the front of the current node. + */ +static inline void list_add_before(list_node_t *new_node, list_node_t *cur_node) +{ + new_node->prev = cur_node->prev; + new_node->next = cur_node; + cur_node->prev->next = new_node; + cur_node->prev = new_node; +} + +/* + * Add a new node after the current node + */ +static inline void list_add_after(list_node_t *new_node, list_node_t *cur_node) +{ + new_node->prev = cur_node; + new_node->next = cur_node->next; + cur_node->next = new_node; + new_node->next->prev = new_node; +} + +/* + * Remove a node from list. + */ +static inline void list_remove(list_node_t *node) +{ + node->prev->next = node->next; + node->next->prev = node->prev; +} + +/* + * Whether the linked list is empty. + */ +static inline bool list_is_empty(const list_head_t *head) +{ + return (head->prev == head) && (head->next == head); +} + +#define list_entry(ptr, type, member) \ + ((type *)((unsigned long)(ptr) - (unsigned long)&((type *)0)->member)) + +#define list_for_each(cur, head) \ + for ((cur) = (head)->next; (cur) != (head); (cur) = (cur)->next) + +#define list_for_each_safe(cur, tmp, head) \ + for ((cur) = (head)->next, (tmp) = (cur)->next; (cur) != (head); (cur) = (tmp), (tmp) = (cur)->next) + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/common_inc/switchless_defs.h b/inc/common_inc/switchless_defs.h new file mode 100644 index 0000000..c7e9dfc --- /dev/null +++ b/inc/common_inc/switchless_defs.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 __SWITCHLESS_DEFS_H__ +#define __SWITCHLESS_DEFS_H__ + +#include <stdint.h> +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define SWITCHLESS_BITS_IN_QWORD 64 + +typedef struct { + uint32_t num_uworkers; // number of untrusted (for ocalls) worker threads + uint32_t num_tworkers; // number of trusted (for ecalls) worker threads + uint32_t call_pool_size_qwords; // number of switchless calls pool size (actual number is x 64) + uint32_t num_max_params; // max number of parameters +} sl_task_pool_config_t; + +typedef struct { + char *pool_buf; // switchless task pool control area + char *task_buf; // part of pool_buf, stores invoking tasks + uint64_t *free_bit_buf; // idle task flag + uint64_t *signal_bit_buf; // to-be-processed task flag + uint32_t bit_buf_size; // size of each task flag area + uint32_t per_task_size; // size of each task + volatile bool need_stop_tworkers; // indicates whether to stop the trusted proxy thread + sl_task_pool_config_t pool_cfg; +} sl_task_pool_t; + +typedef struct { + volatile uint32_t status; + uint32_t func_id; + volatile uint64_t ret_val; + uint64_t params[0]; +} sl_task_t; + +#define SL_CALCULATE_PER_TASK_SIZE(cfg) \ + (sizeof(sl_task_t) + (cfg)->num_max_params * sizeof(uint64_t)) + +typedef enum { + SL_TASK_INIT = 0, + SL_TASK_SUBMITTED, + SL_TASK_ACCEPTED, + SL_TASK_DONE_SUCCESS, + SL_TASK_DONE_FAILED +} sl_task_status_t; + +/* + * Summary: get pool buf size by config + * Parameters: + * pool_cfg: configuration information of the task pool + * Return: + * pool size in bytes + */ +inline size_t sl_get_pool_buf_len_by_config(sl_task_pool_config_t *pool_cfg) +{ + size_t signal_bit_buf_size = pool_cfg->call_pool_size_qwords * sizeof(uint64_t); + size_t each_task_size = SL_CALCULATE_PER_TASK_SIZE(pool_cfg); + size_t task_buf_size = each_task_size * pool_cfg->call_pool_size_qwords * SWITCHLESS_BITS_IN_QWORD; + return sizeof(sl_task_pool_config_t) + signal_bit_buf_size + task_buf_size; +} + +/* + * Summary: Switchless bridge function prototype on the security side + * Parameters: + * task_buf: task_buf, refer to sl_task_t + * Return: NA + */ +typedef void (*sl_ecall_func_t)(void *task_buf); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/enclave_inc/gp/gp.h b/inc/enclave_inc/gp/gp.h index bed6afd..57d8ae4 100644 --- a/inc/enclave_inc/gp/gp.h +++ b/inc/enclave_inc/gp/gp.h @@ -33,6 +33,7 @@ typedef cc_enclave_result_t (*cc_ecall_func_t)( size_t input_buffer_size, uint8_t *output_buffer, size_t output_buffer_size, + uint8_t *shared_buffer, size_t *output_bytes_written); typedef struct _ecall_table diff --git a/inc/enclave_inc/gp/itrustee/random_internal.h b/inc/enclave_inc/gp/itrustee/random_internal.h index c21a0ca..05f83b5 100644 --- a/inc/enclave_inc/gp/itrustee/random_internal.h +++ b/inc/enclave_inc/gp/itrustee/random_internal.h @@ -13,7 +13,6 @@ #ifndef __SECGEAR_CEGENERATE_API_H #define __SECGEAR_CEGENERATE_API_H #include <stdio.h> -#include <stdint.h> int _cc_generate_random(void * buffer, size_t size); diff --git a/inc/host_inc/enclave.h b/inc/host_inc/enclave.h index 1e3aefb..68dc421 100644 --- a/inc/host_inc/enclave.h +++ b/inc/host_inc/enclave.h @@ -144,6 +144,7 @@ typedef struct _call_cc_enclave_function_args { size_t output_buffer_size; size_t output_bytes_written; cc_enclave_result_t result; + cc_enclave_t *enclave; } cc_enclave_call_function_args_t; typedef struct _ocall_cc_enclave_function_args { @@ -153,29 +154,35 @@ typedef struct _ocall_cc_enclave_function_args { } cc_enclave_ocall_function_args_t; cc_enclave_result_t oe_call_enclave_function_by_table_id( - cc_enclave_t *enclave, - uint64_t function_id, - const void *input_buffer, - size_t input_buffer_size, - void *output_buffer, - size_t output_buffer_size, - size_t *output_bytes_written); + cc_enclave_t *enclave, + uint64_t function_id, + const void *input_buffer, + size_t input_buffer_size, + void *output_buffer, + size_t output_buffer_size, + size_t *output_bytes_written); cc_enclave_result_t cc_enclave_call_function( - cc_enclave_t *enclave, - uint32_t function_id, - const void *input_buffer, - size_t input_buffer_size, - void *output_buffer, - size_t output_buffer_size, - void *ms, - const void *ocall_table); + cc_enclave_t *enclave, + uint32_t function_id, + const void *input_buffer, + size_t input_buffer_size, + void *output_buffer, + size_t output_buffer_size, + void *ms, + const void *ocall_table); typedef struct _ocall_table { uint64_t num; cc_ocall_func_t ocalls[]; } ocall_enclave_table_t; +/* Enclave feature flag */ +typedef enum { + ENCLAVE_FEATURE_SWITCHLESS = 1, + ENCLAVE_FEATURE_PROTECTED_CODE_LOADER +} enclave_features_flag_t; + # ifdef __cplusplus } # endif diff --git a/inc/host_inc/enclave_internal.h b/inc/host_inc/enclave_internal.h index 5541557..5a8af38 100644 --- a/inc/host_inc/enclave_internal.h +++ b/inc/host_inc/enclave_internal.h @@ -30,6 +30,12 @@ typedef enum _enclave_state { ENCLAVE_INITIALIZED, } enclave_state_t; +typedef struct { + uint32_t func_id; + uint32_t argc; + void *args; +} sl_ecall_func_info_t; + /*the ops function structure is used to ecall, create, and destroy specific enclave*/ struct cc_enclave_ops { cc_enclave_result_t (*cc_create_enclave)( @@ -48,6 +54,28 @@ struct cc_enclave_ops { size_t output_buffer_size, void *ms, const void *ocall_table); + + cc_enclave_result_t (*cc_ecall_enclave_switchless)( + cc_enclave_t *enclave, + uint32_t function_id, + const void *input_buffer, + size_t input_buffer_size, + void *output_buffer, + size_t output_buffer_size, + void *ms, + const void *ocall_table); + + /* switchless ecall */ + cc_enclave_result_t (*cc_sl_ecall_enclave)(cc_enclave_t *enclave, + void *retval, + size_t retval_size, + sl_ecall_func_info_t *func_info); + + /* shared memory */ + void *(*cc_malloc_shared_memory)(cc_enclave_t *enclave, size_t size, bool is_control_buf); + cc_enclave_result_t (*cc_free_shared_memory)(cc_enclave_t *enclave, void *ptr); + cc_enclave_result_t (*cc_register_shared_memory)(cc_enclave_t *enclave, void *ptr); + cc_enclave_result_t (*cc_unregister_shared_memory)(cc_enclave_t *enclave, void *ptr); }; struct cc_enclave_ops_desc { diff --git a/inc/host_inc/enclave_log.h b/inc/host_inc/enclave_log.h index d1a8417..0f80c29 100644 --- a/inc/host_inc/enclave_log.h +++ b/inc/host_inc/enclave_log.h @@ -13,7 +13,6 @@ #ifndef SECGEAR_ENCLAVE_LOG_H #define SECGEAR_ENCLAVE_LOG_H -#include <stdarg.h> #ifdef __cplusplus extern "C" { diff --git a/inc/host_inc/secgear_defs.h b/inc/host_inc/secgear_defs.h new file mode 100644 index 0000000..4ca11a8 --- /dev/null +++ b/inc/host_inc/secgear_defs.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 __SECGEAR_DEFS_H__ +#define __SECGEAR_DEFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define CC_ARRAY_LEN(ARRAY) (sizeof((ARRAY)) / sizeof((ARRAY)[0])) + +#define CC_IGNORE(param) (void)(param) + +#define CC_API_SPEC __attribute__((visibility("default"))) + +#define CC_RWLOCK_LOCK_WR(lock) CC_IGNORE(pthread_rwlock_wrlock(lock)) +#define CC_RWLOCK_LOCK_RD(lock) CC_IGNORE(pthread_rwlock_rdlock(lock)) +#define CC_RWLOCK_UNLOCK(lock) CC_IGNORE(pthread_rwlock_unlock(lock)) +#define CC_MUTEX_INIT(lock, attr) CC_IGNORE(pthread_mutex_init(lock, attr)) +#define CC_MUTEX_DESTROY(lock) CC_IGNORE(pthread_mutex_destroy(lock)) +#define CC_MUTEX_LOCK(lock) CC_IGNORE(pthread_mutex_lock(lock)) +#define CC_MUTEX_UNLOCK(lock) CC_IGNORE(pthread_mutex_unlock(lock)) +#define CC_COND_INIT(cond, attr) CC_IGNORE(pthread_cond_init(cond, attr)) +#define CC_COND_SIGNAL(cond) CC_IGNORE(pthread_cond_signal(cond)) +#define CC_COND_WAIT(cond, mtx_lock) CC_IGNORE(pthread_cond_wait(cond, mtx_lock)) +#define CC_COND_DESTROY(cond) CC_IGNORE(pthread_cond_destroy(cond)) +#define CC_THREAD_ATTR_INIT(attr) CC_IGNORE(pthread_attr_init(attr)) +#define CC_THREAD_ATTR_DESTROY(attr) CC_IGNORE(pthread_attr_destroy(attr)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/host_inc/secgear_shared_memory.h b/inc/host_inc/secgear_shared_memory.h new file mode 100644 index 0000000..befd0bd --- /dev/null +++ b/inc/host_inc/secgear_shared_memory.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 __SECGEAR_SHARED_MEMORY_H__ +#define __SECGEAR_SHARED_MEMORY_H__ + +#include <stdint.h> +#include "status.h" +#include "enclave.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * Summary: Allocate size bytes and returns a pointer to the allocated memory. + * Parameters: + * enclave: enclave + * size: buffer length + * Return: A pointer to the allocated memory On error, return NULL. + */ +CC_API_SPEC void *cc_malloc_shared_memory(cc_enclave_t *enclave, size_t size); + +/* + * Summary: Frees the memory space pointed to by ptr, which must have been returned by cc_malloc_shared_memory. + * Parameters: + * enclave: enclave + * ptr: buffer address + * Return: CC_SUCCESS, success; others failed. + */ +CC_API_SPEC cc_enclave_result_t cc_free_shared_memory(cc_enclave_t *enclave, void *ptr); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/host_inc/secgear_uswitchless.h b/inc/host_inc/secgear_uswitchless.h new file mode 100644 index 0000000..bff563c --- /dev/null +++ b/inc/host_inc/secgear_uswitchless.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * secGear is 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 SECGEAR_USWITCHLESS_H +#define SECGEAR_USWITCHLESS_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct { + /* number of untrusted (for ocalls) worker threads */ + uint32_t num_uworkers; + + /* number of trusted (for ecalls) worker threads */ + uint32_t num_tworkers; + + /* number of switchless calls pool size. (actual number is x 64) */ + uint32_t sl_call_pool_size_qwords; + + /* max number of parameters, only for GP */ + uint32_t num_max_params; + + /* + * how many times to execute assembly pause instruction while waiting for worker thread to start executing + * switchless call before falling back to direct ECall/OCall, only for SGX + */ + uint32_t retries_before_fallback; + + /* + * how many times a worker thread executes assembly pause instruction while waiting for switchless call request + * before going to sleep, only for SGX + */ + uint32_t retries_before_sleep; +} cc_sl_config_t; + +#define CC_USWITCHLESS_CONFIG_INITIALIZER {1, 1, 1, 16, 0, 0} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/inc/host_inc/sgx/secgear_tswitchless.edl b/inc/host_inc/sgx/secgear_tswitchless.edl index bb0769d..5588b83 100644 --- a/inc/host_inc/sgx/secgear_tswitchless.edl +++ b/inc/host_inc/sgx/secgear_tswitchless.edl @@ -1,4 +1,6 @@ // To do: develop key libraries of secGear version, to be compatible with SGX and GP. enclave { + include "sgx_error.h" + include "sgx_edger8r.h" from "sgx_tswitchless.edl" import *; }; diff --git a/inc/host_inc/status.h b/inc/host_inc/status.h index 1d18d2e..15de9d1 100644 --- a/inc/host_inc/status.h +++ b/inc/host_inc/status.h @@ -153,6 +153,19 @@ typedef enum _enclave_result_t CC_ERROR_INVALID_HANDLE, /*Invalid sdk or engine handler*/ CC_ERROR_NO_FIND_REGFUNC, /*can't find register function*/ CC_ERROR_NO_FIND_UNREGFUNC, /*can't find unregister function*/ +/* Enclave feature */ + CC_ERROR_FEATURE_FUNC_NOT_EXIST = 0xFFFF9200, /* The feature processing function does not exist */ + CC_ERROR_SWITCHLESS_DISABLED = 0xFFFF9220, /* Switchless is disabled */ + CC_ERROR_SWITCHLESS_TASK_POOL_FULL, /* Switchless task pool is full */ + CC_ERROR_SWITCHLESS_INVALID_ARG_NUM, /* The number of switchless parameters is invalid */ + CC_ERROR_SWITCHLESS_INVALID_FUNCTION_ID, /* The function id of switchless call is invalid */ + CC_ERROR_SWITCHLESS_FUNCTION_NOT_EXIST, /* Switchless call is not exist */ + CC_ERROR_SWITCHLESS_REINIT, /* Switchless repeated initialization */ + CC_ERROR_TSWITCHLESS_INIT_FAILED, /* Trust switchless init failed */ + CC_ERROR_SHARED_MEMORY_REPEAT_REGISTER, /* The shared memory is repeatedly registered */ + CC_ERROR_SHARED_MEMORY_START_ADDR_INVALID, /* Invalid start address of the shared memory */ + CC_ERROR_SHARED_MEMORY_NOT_REGISTERED, /* Unregistered shared memory */ + CC_ERROR_ADDRESS_UNACCESSABLE, /* Memory address is not within enclave */ CC_MAXIMUM_ERROR, } cc_enclave_result_t; diff --git a/src/enclave_src/CMakeLists.txt b/src/enclave_src/CMakeLists.txt index f6d353c..3f86120 100644 --- a/src/enclave_src/CMakeLists.txt +++ b/src/enclave_src/CMakeLists.txt @@ -11,7 +11,7 @@ project(secgear_tee C) set(target_lib secgear_tee) -set(LIBRARY_INSTALL /usr/lib64) +set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -33,3 +33,4 @@ endif() if(CC_SGX) add_subdirectory(sgx) endif() + diff --git a/src/enclave_src/gp/gp.c b/src/enclave_src/gp/gp.c index c587e20..6621270 100644 --- a/src/enclave_src/gp/gp.c +++ b/src/enclave_src/gp/gp.c @@ -21,6 +21,7 @@ #define POS_IN 0 #define POS_OUT 1 #define POS_IN_OUT 2 +#define POS_SHARED_MEM 3 extern const cc_ecall_func_t cc_ecall_tables[]; extern const size_t ecall_table_size; @@ -91,8 +92,7 @@ void TA_DestroyEntryPoint(void) } static cc_enclave_result_t get_params_buffer(TEE_Param params[PARAMNUM], - void **input_buffer, - void **output_buffer) + void **input_buffer, void **output_buffer) { void *tmp_input_buffer = NULL; void *tmp_output_buffer = NULL; @@ -190,6 +190,7 @@ static TEE_Result handle_ecall_function(uint32_t param_types, TEE_Param params[P tmp_input_buffer_size, tmp_output_buffer, tmp_output_buffer_size, + params[POS_SHARED_MEM].memref.buffer, &output_bytes_written); if (res != CC_SUCCESS) { goto done; diff --git a/src/enclave_src/gp/itrustee/CMakeLists.txt b/src/enclave_src/gp/itrustee/CMakeLists.txt index 1cfa53f..3424907 100644 --- a/src/enclave_src/gp/itrustee/CMakeLists.txt +++ b/src/enclave_src/gp/itrustee/CMakeLists.txt @@ -8,11 +8,32 @@ # PURPOSE. # See the Mulan PSL v2 for more details. -set(SOURCE_FILES ${SOURCE_FILES} ../gp.c ../gp_ocall.c itrustee_seal_data.c error_conversion.c bottom_memory_check.c itrustee_random.c) +set(CMAKE_C_FLAGS "-W -Wall -fno-short-enums -fno-omit-frame-pointer -fstack-protector-strong -Wstack-protector \ + --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs -fno-peephole \ + -fno-peephole2 -Wno-main -Wno-error=unused-parameter -Wno-error=unused-but-set-variable \ + -Wno-error=format-truncation= -D_FORTIFY_SOURCE=2 -O2") +set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") +set(SOURCE_FILES ${SOURCE_FILES} ../gp.c ../gp_ocall.c itrustee_seal_data.c error_conversion.c bottom_memory_check.c + itrustee_random.c itrustee_tswitchless.c itrustee_shared_memory.c) set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/) set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc) -set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a -fPIC") + +if (CMAKE_COMPILER_IS_GNUCC) + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpfullversion -dumpversion + OUTPUT_VARIABLE GCC_VERSION) + string(REGEX MATCHALL "[0-9]+" GCC_VERSION_COMPONENTS ${GCC_VERSION}) + list(GET GCC_VERSION_COMPONENTS 0 GCC_MAJOR) + list(GET GCC_VERSION_COMPONENTS 1 GCC_MINOR) + set(GCC_VERSION "${GCC_MAJOR}.${GCC_MINOR}") +endif() + +if (GCC_VERSION GREATER_EQUAL "9.4") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a -mno-outline-atomics -fPIC") +else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a -fPIC") +endif() + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS}") add_library(${target_lib} STATIC ${SOURCE_FILES}) @@ -26,9 +47,20 @@ target_include_directories(${target_lib} PRIVATE ${ITRUSTEE_LIBC}/arch/generic ${ITRUSTEE_LIBC}/arch/arm ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/ - ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) + ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee + ${ITRUSTEE_TEEDIR}/include/CA + ${LOCAL_ROOT_PATH}/inc/common_inc + ${LOCAL_ROOT_PATH}/inc/common_inc/gp) install(TARGETS ${target_lib} ARCHIVE DESTINATION ${LIBRARY_INSTALL} PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +file(GLOB GP_ENCLAVE_HEADERS_1 ${LOCAL_ROOT_PATH}/inc/enclave_inc/*.h) +file(GLOB GP_ENCLAVE_HEADERS_2 ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/*.h) +file(GLOB GP_ENCLAVE_HEADERS_3 ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee/*.h) + +install(FILES ${GP_ENCLAVE_HEADERS_1} ${GP_ENCLAVE_HEADERS_2} ${GP_ENCLAVE_HEADERS_3} + DESTINATION /usr/include/secGear + PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) diff --git a/src/enclave_src/gp/itrustee/itrustee_shared_memory.c b/src/enclave_src/gp/itrustee/itrustee_shared_memory.c new file mode 100644 index 0000000..32b8d8e --- /dev/null +++ b/src/enclave_src/gp/itrustee/itrustee_shared_memory.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 <stddef.h> +#include <stdlib.h> +#include <stdbool.h> +#include <pthread.h> +#include "gp.h" +#include "status.h" +#include "secgear_log.h" +#include "itrustee_tswitchless.h" +#include "gp_shared_memory_defs.h" +#include "secgear_list.h" +#include "secgear_defs.h" + +typedef struct { + list_node_t node; + size_t host_addr; // Memory address on the CA side + size_t enclave_addr; // TA-side memory address after mapping + size_t buf_len; // Shared Memory Length + pthread_mutex_t mtx_lock; + pthread_cond_t unregister_cond; + sl_task_pool_t *pool; // switchless task pool control area + pthread_t *tid_arr; // Open a new TA session in a separate thread to register the shared memory +} shared_memory_block_t; + +static pthread_rwlock_t g_shared_memory_list_lock = PTHREAD_RWLOCK_INITIALIZER; +static list_node_t g_shared_memory_list = { + .next = &g_shared_memory_list, + .prev = &g_shared_memory_list +}; + +static shared_memory_block_t *create_shared_memory_block(void *host_buf, size_t host_buf_len, const void *register_buf) +{ + shared_memory_block_t *shared_mem = calloc(1, sizeof(shared_memory_block_t)); + if (shared_mem == NULL) { + return NULL; + } + + list_init(&shared_mem->node); + CC_MUTEX_INIT(&shared_mem->mtx_lock, NULL); + CC_COND_INIT(&shared_mem->unregister_cond, NULL); + + shared_mem->host_addr = (size_t)host_buf; + shared_mem->enclave_addr = (size_t)((char *)register_buf + sizeof(gp_shared_memory_t)); + shared_mem->buf_len = host_buf_len; + + return shared_mem; +} + +static void destroy_shared_memory_block(shared_memory_block_t *shared_mem) +{ + if (shared_mem != NULL) { + CC_MUTEX_DESTROY(&shared_mem->mtx_lock); + CC_COND_DESTROY(&shared_mem->unregister_cond); + free(shared_mem); + } +} + +static void add_shared_memory_block_to_list(const shared_memory_block_t *shared_mem) +{ + CC_RWLOCK_LOCK_WR(&g_shared_memory_list_lock); + list_add_after(&shared_mem->node, &g_shared_memory_list); + CC_RWLOCK_UNLOCK(&g_shared_memory_list_lock); +} + +static void remove_shared_memory_block_from_list(const shared_memory_block_t *shared_mem) +{ + CC_RWLOCK_LOCK_WR(&g_shared_memory_list_lock); + list_remove(&shared_mem->node); + CC_RWLOCK_UNLOCK(&g_shared_memory_list_lock); +} + +static cc_enclave_result_t itrustee_register_shared_memory(void *host_buf, + size_t host_buf_len, + void *registered_buf, + bool is_control_buf) +{ + cc_enclave_result_t ret = CC_FAIL; + + shared_memory_block_t *shared_mem = create_shared_memory_block(host_buf, host_buf_len, registered_buf); + if (shared_mem == NULL) { + return CC_ERROR_OUT_OF_MEMORY; + } + + if (is_control_buf) { + ret = tswitchless_init((void *)shared_mem->enclave_addr, &shared_mem->pool, &shared_mem->tid_arr); + if (ret != CC_SUCCESS) { + destroy_shared_memory_block(shared_mem); + return CC_ERROR_TSWITCHLESS_INIT_FAILED; + } + } + + add_shared_memory_block_to_list(shared_mem); + __atomic_store_n(&(((gp_shared_memory_t *)registered_buf)->is_registered), true, __ATOMIC_RELEASE); + + // Waiting for the deregistration signal + CC_MUTEX_LOCK(&shared_mem->mtx_lock); + CC_COND_WAIT(&shared_mem->unregister_cond, &shared_mem->mtx_lock); + CC_MUTEX_UNLOCK(&shared_mem->mtx_lock); + + __atomic_store_n(&(((gp_shared_memory_t *)registered_buf)->is_registered), false, __ATOMIC_RELEASE); + remove_shared_memory_block_from_list(shared_mem); + + if (is_control_buf) { + tswitchless_fini(shared_mem->pool, shared_mem->tid_arr); + } + + destroy_shared_memory_block(shared_mem); + + return CC_SUCCESS; +} + +cc_enclave_result_t ecall_register_shared_memory(uint8_t *in_buf, + size_t in_buf_size, + uint8_t *out_buf, + size_t out_buf_size, + uint8_t *registered_buf, + size_t *output_bytes_written) +{ + /* Check if the input and output buffers can be visited */ + if ((!in_buf || !cc_is_within_enclave(in_buf, in_buf_size)) || + (!out_buf || !cc_is_within_enclave(out_buf, out_buf_size))) { + return CC_ERROR_ADDRESS_UNACCESSABLE; + } + + /* Parse input parameters from in_buf */ + size_t in_buf_offset = size_to_aligned_size(sizeof(gp_register_shared_memory_size_t)); + gp_register_shared_memory_size_t *args_size = (gp_register_shared_memory_size_t *)in_buf; + + uint8_t *host_buf_p = NULL; + uint8_t *host_buf_len_p = NULL; + uint8_t *is_control_buf_p = NULL; + SET_PARAM_IN_1(host_buf_p, size_t, host_buf, args_size->shared_buf_size); + SET_PARAM_IN_1(host_buf_len_p, size_t, host_buf_len, args_size->shared_buf_len_size); + SET_PARAM_IN_1(is_control_buf_p, bool, is_control_buf, args_size->is_control_buf_size); + + /* Fill return val, out and in-out parameters */ + size_t out_buf_offset = 0; + + uint8_t *retval_p = NULL; + SET_PARAM_OUT(retval_p, int, retval, args_size->retval_size); + + *retval = itrustee_register_shared_memory((void *)host_buf, host_buf_len, registered_buf, is_control_buf); + *output_bytes_written = out_buf_offset; + + return CC_SUCCESS; +} + +size_t addr_host_to_enclave(size_t host_addr) +{ + list_node_t *cur = NULL; + shared_memory_block_t *mem_block = NULL; + size_t ptr = 0; + + CC_RWLOCK_LOCK_RD(&g_shared_memory_list_lock); + + list_for_each(cur, &g_shared_memory_list) { + mem_block = list_entry(cur, shared_memory_block_t, node); + if ((host_addr >= mem_block->host_addr) && (host_addr < (mem_block->host_addr + mem_block->buf_len))) { + ptr = mem_block->enclave_addr + (host_addr - mem_block->host_addr); + break; + } + } + + CC_RWLOCK_UNLOCK(&g_shared_memory_list_lock); + + return ptr; +} + +static cc_enclave_result_t itrustee_unregister_shared_memory(size_t host_addr) +{ + cc_enclave_result_t ret = CC_ERROR_ITEM_NOT_FOUND; + list_node_t *cur = NULL; + shared_memory_block_t *mem_block = NULL; + + CC_RWLOCK_LOCK_RD(&g_shared_memory_list_lock); + + list_for_each(cur, &g_shared_memory_list) { + mem_block = list_entry(cur, shared_memory_block_t, node); + if (host_addr == mem_block->host_addr) { + CC_MUTEX_LOCK(&mem_block->mtx_lock); + CC_COND_SIGNAL(&mem_block->unregister_cond); + CC_MUTEX_UNLOCK(&mem_block->mtx_lock); + ret = CC_SUCCESS; + break; + } + } + + CC_RWLOCK_UNLOCK(&g_shared_memory_list_lock); + + return ret; +} + +cc_enclave_result_t ecall_unregister_shared_memory(uint8_t *in_buf, + size_t in_buf_size, + uint8_t *out_buf, + size_t out_buf_size, + uint8_t *shared_buf, + size_t *output_bytes_written) +{ + CC_IGNORE(shared_buf); + + /* Check if the input and output buffers can be visited */ + if ((!in_buf || !cc_is_within_enclave(in_buf, in_buf_size)) || + (!out_buf || !cc_is_within_enclave(out_buf, out_buf_size))) { + return CC_ERROR_ADDRESS_UNACCESSABLE; + } + + /* Fill in and in-out parameters */ + size_t in_buf_offset = size_to_aligned_size(sizeof(gp_unregister_shared_memory_size_t)); + gp_unregister_shared_memory_size_t *args_size = (gp_unregister_shared_memory_size_t *)in_buf; + + uint8_t *host_addr_p; + SET_PARAM_IN_1(host_addr_p, size_t, host_addr, args_size->shared_buf_size); + + /* Fill return val, out and in-out parameters */ + size_t out_buf_offset = 0; + + uint8_t *retval_p; + SET_PARAM_OUT(retval_p, int, retval, args_size->retval_size); + + *retval = itrustee_unregister_shared_memory(host_addr); + *output_bytes_written = out_buf_offset; + + return CC_SUCCESS; +} diff --git a/src/enclave_src/gp/itrustee/itrustee_tswitchless.c b/src/enclave_src/gp/itrustee/itrustee_tswitchless.c new file mode 100644 index 0000000..5ccb519 --- /dev/null +++ b/src/enclave_src/gp/itrustee/itrustee_tswitchless.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 "itrustee_tswitchless.h" + +#include <stdint.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdlib.h> +#include <time.h> +#include "secgear_defs.h" +#include "switchless_defs.h" +#include "bit_operation.h" +#include "tee_time_api.h" +#include "secgear_log.h" +#include "tee_log.h" + +#ifndef TEESMP_THREAD_ATTR_CA_WILDCARD +#define TEESMP_THREAD_ATTR_CA_WILDCARD 0 +#endif + +#ifndef TEESMP_THREAD_ATTR_CA_INHERIT +#define TEESMP_THREAD_ATTR_CA_INHERIT (-1U) +#endif + +#ifndef TEESMP_THREAD_ATTR_TASK_ID_INHERIT +#define TEESMP_THREAD_ATTR_TASK_ID_INHERIT (-1U) +#endif + +#ifndef TEESMP_THREAD_ATTR_INVALID +#define TEESMP_THREAD_ATTR_INVALID (1U << 31) +#endif + +#ifndef TEESMP_THREAD_ATTR_F_SHADOW +#define TEESMP_THREAD_ATTR_F_SHADOW (1U << 24) +#endif + +#ifndef TEESMP_THREAD_ATTR_HAS_SHADOW +#define TEESMP_THREAD_ATTR_HAS_SHADOW 0x1 +#endif + +#ifndef TEESMP_THREAD_ATTR_NO_SHADOW +#define TEESMP_THREAD_ATTR_NO_SHADOW 0x0 +#endif + +#ifndef TEESMP_THREAD_ATTR_TASK_ID +#define TEESMP_THREAD_ATTR_TASK_ID TEESMP_THREAD_ATTR_TASK_ID_INHERIT +#endif + +static sl_task_pool_t *tswitchless_init_pool(void *pool_buf) +{ + sl_task_pool_t *pool = (sl_task_pool_t *)calloc(1, sizeof(sl_task_pool_t)); + if (pool == NULL) { + SLogError("Malloc memory for tpool failed."); + return NULL; + } + + sl_task_pool_config_t *pool_cfg = (sl_task_pool_config_t *)pool_buf; + + pool->pool_cfg = *pool_cfg; + pool->bit_buf_size = pool_cfg->call_pool_size_qwords * sizeof(uint64_t); + pool->per_task_size = SL_CALCULATE_PER_TASK_SIZE(pool_cfg); + + pool->pool_buf = (char *)pool_buf; + pool->signal_bit_buf = (uint64_t *)(pool->pool_buf + sizeof(sl_task_pool_config_t)); + pool->task_buf = (char *)pool->signal_bit_buf + pool->bit_buf_size; + + return pool; +} + +static void tswitchless_fini_workers(sl_task_pool_t *pool, pthread_t *tids) +{ + int ret; + uint32_t thread_num = pool->pool_cfg.num_tworkers; + pool->need_stop_tworkers = true; + + for (uint32_t i = 0; i < thread_num; ++i) { + if (tids[i] != NULL) { + ret = pthread_join(tids[i], NULL); + if (ret != 0) { + SLogWarning("Failed to exit the tworker thread, ret=%d.", ret); + } + } + } +} + +static inline sl_task_t *tswitchless_get_task_by_index(sl_task_pool_t *pool, int task_index) +{ + return (sl_task_t *)(pool->task_buf + task_index * pool->per_task_size); +} + +static int tswitchless_get_pending_task(sl_task_pool_t *pool) +{ + int call_pool_size_qwords = (int)pool->pool_cfg.call_pool_size_qwords; + uint64_t *signal_bit_buf = pool->signal_bit_buf; + int start_bit = 0; + int end_bit = 0; + uint64_t *element_ptr = NULL; + uint64_t element_val = 0; + + for (int i = 0; i < call_pool_size_qwords; ++i) { + element_ptr = signal_bit_buf + i; + element_val = *element_ptr; + + if (element_val == 0) { + continue; + } + + start_bit = count_tailing_zeroes(element_val); + end_bit = SWITCHLESS_BITS_IN_QWORD - count_leading_zeroes(element_val); + + for (int j = start_bit; j < end_bit; ++j) { + if (test_and_clear_bit(element_ptr, j) != 0) { + return i * SWITCHLESS_BITS_IN_QWORD + j; + } + } + } + + return -1; +} + +extern const sl_ecall_func_t sl_ecall_func_table[]; +extern const size_t sl_ecall_func_table_size; + +static void tswitchless_proc_task(sl_task_t *task) +{ + uint32_t function_id = task->func_id; + if (function_id >= sl_ecall_func_table_size) { + task->ret_val = CC_ERROR_SWITCHLESS_INVALID_FUNCTION_ID; + __atomic_store_n(&task->status, SL_TASK_DONE_FAILED, __ATOMIC_RELEASE); + + SLogError("Invalid switchless function index:%u.", function_id); + return; + } + + sl_ecall_func_t func = sl_ecall_func_table[function_id]; + if (func == NULL) { + task->ret_val = CC_ERROR_SWITCHLESS_FUNCTION_NOT_EXIST; + __atomic_store_n(&task->status, SL_TASK_DONE_FAILED, __ATOMIC_RELEASE); + + SLogError("The switchless function with index:%u does not exist.", function_id); + return; + } + + func(task); + __atomic_store_n(&task->status, SL_TASK_DONE_SUCCESS, __ATOMIC_RELEASE); +} + +static int thread_num = 0; + +static void *tswitchless_thread_routine(void *data) +{ + int thread_index = __atomic_add_fetch(&thread_num, 1, __ATOMIC_ACQ_REL); + SLogTrace("Enter tworkers: %d.", thread_index); + + int task_index; + sl_task_t *task_buf = NULL; + sl_task_pool_t *pool = (sl_task_pool_t *)data; + int processed_count = 0; + + while (true) { + if (pool->need_stop_tworkers) { + break; + } + + task_index = tswitchless_get_pending_task(pool); + if (task_index == -1) { + continue; + } + + task_buf = tswitchless_get_task_by_index(pool, task_index); + __atomic_store_n(&task_buf->status, SL_TASK_ACCEPTED, __ATOMIC_RELEASE); + tswitchless_proc_task(task_buf); + + processed_count++; + } + + SLogTrace("Exit tworkers: %d, processed: %d.", thread_index, processed_count); + (void)__atomic_sub_fetch(&thread_num, 1, __ATOMIC_ACQ_REL); + + return NULL; +} + +static pthread_t *tswitchless_init_workers(sl_task_pool_t *pool) +{ + int ret; + sl_task_pool_config_t *pool_cfg = &pool->pool_cfg; + + pthread_t *tids = (pthread_t *)calloc(pool_cfg->num_tworkers, sizeof(pthread_t)); + if (tids == NULL) { + SLogError("Malloc memory for tworkers failed."); + return NULL; + } + + pthread_attr_t attr; + CC_THREAD_ATTR_INIT(&attr); + ret = pthread_attr_settee(&attr, + TEESMP_THREAD_ATTR_CA_INHERIT, + TEESMP_THREAD_ATTR_TASK_ID_INHERIT, + TEESMP_THREAD_ATTR_HAS_SHADOW); + if (ret != 0) { + free(tids); + CC_THREAD_ATTR_DESTROY(&attr); + + SLogError("Set tee thread attr failed, ret: %d.", ret); + return NULL; + } + + for (uint32_t i = 0; i < pool_cfg->num_tworkers; ++i) { + ret = pthread_create(tids + i, &attr, tswitchless_thread_routine, pool); + if (ret != 0) { + tswitchless_fini_workers(pool, tids); + free(tids); + CC_THREAD_ATTR_DESTROY(&attr); + + SLogError("Create tee thread failed, index:%u, ret:%d.", i, ret); + return NULL; + } + } + + CC_THREAD_ATTR_DESTROY(&attr); + + return tids; +} + +cc_enclave_result_t tswitchless_init(void *pool_buf, sl_task_pool_t **pool, pthread_t **tids) +{ + sl_task_pool_t *tmp_pool = tswitchless_init_pool(pool_buf); + if (tmp_pool == NULL) { + return CC_FAIL; + } + + pthread_t *tmp_tids = tswitchless_init_workers(tmp_pool); + if (tmp_tids == NULL) { + free(tmp_pool); + return CC_FAIL; + } + + *pool = tmp_pool; + *tids = tmp_tids; + + return CC_SUCCESS; +} + +void tswitchless_fini(sl_task_pool_t *pool, pthread_t *tids) +{ + tswitchless_fini_workers(pool, tids); + free(tids); + free(pool); +} diff --git a/src/enclave_src/gp/itrustee/itrustee_tswitchless.h b/src/enclave_src/gp/itrustee/itrustee_tswitchless.h new file mode 100644 index 0000000..fb412af --- /dev/null +++ b/src/enclave_src/gp/itrustee/itrustee_tswitchless.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 __ITRUSTEE_TSWITCHLESS_H__ +#define __ITRUSTEE_TSWITCHLESS_H__ + +#include <pthread.h> +#include "switchless_defs.h" +#include "status.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Summary: Switchless initalization on the TA side + * Parameters: + * pool_buf: address of the task pool buffer + * pool: task pool management data structure + * tids: thread id for tworkers + * Return: CC_SUCCESS, success; others failed. + */ +cc_enclave_result_t tswitchless_init(void *pool_buf, sl_task_pool_t **pool, pthread_t **tids); + +/* + * Summary: Switchless deinitalization on the TA side + * Parameters: + * pool: task pool management data structure + * tids: thread id for tworkers + * Return: CC_SUCCESS, success; others failed. + */ +void tswitchless_fini(sl_task_pool_t *pool, pthread_t *tids); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/host_src/CMakeLists.txt b/src/host_src/CMakeLists.txt index a545e27..bfc49b0 100644 --- a/src/host_src/CMakeLists.txt +++ b/src/host_src/CMakeLists.txt @@ -8,11 +8,16 @@ # PURPOSE. # See the Mulan PSL v2 for more details. -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -fPIC -Wno-stringop-overflow") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -fPIC -Wno-stringop-overflow -fstack-protector-strong \ + -D_FORTIFY_SOURCE=2 -O2") -set(LIBRARY_INSTALL /usr/lib64) +set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) -include_directories(${LOCAL_ROOT_PATH}/inc/host_inc) +include_directories(${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/gp + ${LOCAL_ROOT_PATH}/inc/common_inc + ${LOCAL_ROOT_PATH}/inc/common_inc/gp + ${iTrusteeSDK}/include/CA) if(CC_GP) add_subdirectory(gp) @@ -22,8 +27,8 @@ if(CC_SGX) add_subdirectory(sgx) endif() -add_library(secgear SHARED enclave.c enclave_internal.c ocall_log.c enclave_ocall.c) -add_library(secgearsim SHARED enclave.c enclave_internal.c ocall_log.c enclave_ocall.c) +add_library(secgear SHARED enclave.c enclave_internal.c ocall_log.c enclave_ocall.c secgear_shared_memory.c) +add_library(secgearsim SHARED enclave.c enclave_internal.c ocall_log.c enclave_ocall.c secgear_shared_memory.c) target_link_libraries(secgear dl pthread) target_link_libraries(secgearsim dl pthread) diff --git a/src/host_src/enclave_internal.c b/src/host_src/enclave_internal.c index b30a207..abe121e 100644 --- a/src/host_src/enclave_internal.c +++ b/src/host_src/enclave_internal.c @@ -14,6 +14,7 @@ #include <string.h> #include <stdio.h> #include <sys/utsname.h> +#include <stdarg.h> #include "status.h" #include "enclave_internal.h" @@ -217,14 +218,14 @@ cc_enclave_result_t find_engine_open(enclave_type_version_t type, void **handle) switch (type) { case SGX_ENCLAVE_TYPE_0: #ifdef CC_SIM - *handle = dlopen("/lib64/libsgxsim_0.so", RTLD_LAZY); + *handle = dlopen("libsgxsim_0.so", RTLD_LAZY); #else - *handle = dlopen("/lib64/libsgx_0.so", RTLD_LAZY); + *handle = dlopen("libsgx_0.so", RTLD_LAZY); #endif break; case GP_ENCLAVE_TYPE_0: /*todo: gp supported simulation*/ - *handle = dlopen("/lib64/libgp_0.so", RTLD_LAZY); + *handle = dlopen("libgp_0.so", RTLD_LAZY); break; default: print_error_goto("Input type and version are not supported\n"); diff --git a/src/host_src/gp/CMakeLists.txt b/src/host_src/gp/CMakeLists.txt index ca6d87f..510e46e 100644 --- a/src/host_src/gp/CMakeLists.txt +++ b/src/host_src/gp/CMakeLists.txt @@ -20,10 +20,13 @@ endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error=implicit-function-declaration") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS}") -add_library(${gp_engine} SHARED gp_enclave.h gp_enclave.c) +add_library(${gp_engine} SHARED gp_enclave.h gp_enclave.c gp_uswitchless.c gp_shared_memory.c) target_include_directories(${gp_engine} PRIVATE - ${iTrusteeSDK}/include/CA) + ${iTrusteeSDK}/include/CA + ${LOCAL_ROOT_PATH}/inc/common_inc + ${LOCAL_ROOT_PATH}/inc/common_inc/gp + ${LOCAL_ROOT_PATH}/inc/host_inc/gp) if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") target_link_directories(${gp_engine} PRIVATE ${CMAKE_BINARY_DIR}/lib) @@ -37,3 +40,11 @@ install(TARGETS ${gp_engine} LIBRARY DESTINATION ${LIBRARY_INSTALL} PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +file(GLOB GP_HOST_HEADERS_1 ${LOCAL_ROOT_PATH}/inc/host_inc/*.h) +file(GLOB GP_HOST_HEADERS_2 ${LOCAL_ROOT_PATH}/inc/host_inc/gp/*.h) +file(GLOB GP_HOST_HEADERS_3 ${LOCAL_ROOT_PATH}/inc/host_inc/gp/*.edl) + +install(FILES ${GP_HOST_HEADERS_1} ${GP_HOST_HEADERS_2} ${GP_HOST_HEADERS_3} + DESTINATION /usr/include/secGear + PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) diff --git a/src/host_src/gp/gp_enclave.c b/src/host_src/gp/gp_enclave.c index b7cc46a..27952e7 100644 --- a/src/host_src/gp/gp_enclave.c +++ b/src/host_src/gp/gp_enclave.c @@ -16,12 +16,18 @@ #include <stdlib.h> #include <signal.h> #include <pthread.h> +#include <time.h> +#include <tee_client_type.h> +#include "secgear_defs.h" #include "enclave.h" #include "enclave_internal.h" #include "enclave_log.h" #include "gp_enclave.h" #include "register_agent.h" +#include "gp_uswitchless.h" +#include "gp_shared_memory_defs.h" +#include "gp_shared_memory.h" #define OCALL_AGENT_REGISTER_SUCCESS 0 #define OCALL_AGENT_REGISTER_FAIL 1 @@ -263,7 +269,7 @@ done: free(tmp_output_buffer); tmp_output_buffer = NULL; } - + return ret; } @@ -347,24 +353,132 @@ cleanup: return res_cc; } +static void fini_context(gp_context_t *gp_context) +{ + if (gp_context != NULL) { + TEEC_CloseSession(&gp_context->session); + TEEC_FinalizeContext(&(gp_context->ctx)); + free(gp_context->sl_task_pool); + free(gp_context); + } +} + +cc_enclave_result_t init_uswitchless(cc_enclave_t *enclave, const enclave_features_t *feature) +{ + gp_context_t *gp_ctx = (gp_context_t *)enclave->private_data; + if (gp_ctx->sl_task_pool != NULL) { + return CC_ERROR_SWITCHLESS_REINIT; + } + + sl_task_pool_config_t *cfg = (sl_task_pool_config_t *)feature->feature_desc; + if (!uswitchless_is_valid_config(cfg)) { + return CC_ERROR_BAD_PARAMETERS; + } + uswitchless_adjust_config(cfg); + + size_t pool_buf_len = sl_get_pool_buf_len_by_config(cfg); + void *pool_buf = gp_malloc_shared_memory(enclave, pool_buf_len, true); + if (pool_buf == NULL) { + return CC_ERROR_OUT_OF_MEMORY; + } + (void)memset(pool_buf, 0, pool_buf_len); + + // Fill config + (void)memcpy(pool_buf, cfg, sizeof(sl_task_pool_config_t)); + + // Layout task pool + sl_task_pool_t *pool = uswitchless_create_task_pool(pool_buf, cfg); + if (pool == NULL) { + (void)gp_free_shared_memory(enclave, pool_buf); + return CC_ERROR_OUT_OF_MEMORY; + } + + // Registering a task pool + cc_enclave_result_t ret = gp_register_shared_memory(enclave, pool_buf); + if (ret != CC_SUCCESS) { + free(pool); + (void)gp_free_shared_memory(enclave, pool_buf); + return ret; + } + + gp_ctx->sl_task_pool = pool; + return CC_SUCCESS; +} + +void fini_uswitchless(cc_enclave_t *enclave) +{ + cc_enclave_result_t ret; + gp_context_t *gp_ctx = (gp_context_t *)enclave->private_data; + sl_task_pool_t *pool = gp_ctx->sl_task_pool; + + if (pool != NULL) { + ret = gp_unregister_shared_memory(enclave, pool->pool_buf); + if (ret != CC_SUCCESS) { + print_error_term("finish uswitchless, failed to unregister task pool, ret=%d\n", ret); + } + (void)gp_free_shared_memory(enclave, pool->pool_buf); + free(pool); + gp_ctx->sl_task_pool = NULL; + } +} + +typedef cc_enclave_result_t (*func_init_feature)(cc_enclave_t *enclave, const enclave_features_t *feature); + + +static const struct { + enclave_features_flag_t flag; + func_init_feature init_func; +} g_gp_handle_feature_func_array[] = { + {ENCLAVE_FEATURE_SWITCHLESS, init_uswitchless} +}; + +func_init_feature get_handle_feature_func(enclave_features_flag_t feature_flag) +{ + for (size_t i = 0; i < CC_ARRAY_LEN(g_gp_handle_feature_func_array); ++i) { + if (g_gp_handle_feature_func_array[i].flag == feature_flag) { + return g_gp_handle_feature_func_array[i].init_func; + } + } + + return NULL; +} + +cc_enclave_result_t init_features(cc_enclave_t *enclave, const enclave_features_t *features, const uint32_t count) +{ + cc_enclave_result_t ret; + func_init_feature init_func = NULL; + + for (uint32_t i = 0; i < count; ++i) { + init_func = get_handle_feature_func((enclave_features_flag_t)features[i].setting_type); + if (init_func == NULL) { + return CC_ERROR_FEATURE_FUNC_NOT_EXIST; + } + + ret = init_func(enclave, features + i); + if (ret != CC_SUCCESS) { + return ret; + } + } + + return CC_SUCCESS; +} + +void fini_features(cc_enclave_t *enclave) +{ + fini_uswitchless(enclave); +} + /* itrustee enclave engine create func */ -cc_enclave_result_t _gp_create(cc_enclave_t *enclave, - const enclave_features_t *features, const uint32_t features_count) +cc_enclave_result_t _gp_create(cc_enclave_t *enclave, const enclave_features_t *features, const uint32_t features_count) { TEEC_Result result_tee; cc_enclave_result_t result_cc; - if (!enclave) { + if ((enclave == NULL) || (features_count > 0 && features == NULL)) { print_error_term("Context parameter error\n"); return CC_ERROR_BAD_PARAMETERS; } - /* itrustee does not currently support feature */ - if (features != NULL || features_count > 0) { - print_error_term("GP does not currently support additional features\n"); - return CC_ERROR_NOT_SUPPORTED; - } - gp_context_t *gp_context = NULL; result_cc = malloc_and_init_context(&gp_context, enclave->path, enclave->type); if (result_cc != CC_SUCCESS) { @@ -387,13 +501,18 @@ cc_enclave_result_t _gp_create(cc_enclave_t *enclave, print_error_term("TEEC open session failed\n"); goto cleanup; } - print_debug("TEEC open session success\n"); enclave->private_data = (void *)gp_context; + + result_cc = init_features(enclave, features, features_count); + if (result_cc != CC_SUCCESS) { + goto cleanup; + } + return CC_SUCCESS; cleanup: - TEEC_FinalizeContext(&(gp_context->ctx)); - free(gp_context); + fini_context(gp_context); gp_context = NULL; + enclave->private_data = NULL; return result_cc; } @@ -407,6 +526,8 @@ cc_enclave_result_t _gp_destroy(cc_enclave_t *context) return CC_ERROR_BAD_PARAMETERS; } + fini_features(context); + gp_context_t *tmp = (gp_context_t*)context->private_data; TEEC_CloseSession(&tmp->session); TEEC_FinalizeContext(&tmp->ctx); @@ -436,6 +557,14 @@ done: return CC_FAIL; } +#define GET_HOST_BUF_FROM_INPUT_PARAMS(in_param_buf) \ + ({ \ + void *ptr = NULL; \ + (void)memcpy(&ptr, (char *)(in_param_buf) + size_to_aligned_size(sizeof(gp_register_shared_memory_size_t)), \ + sizeof(void *)); \ + ptr; \ + }) + static cc_enclave_result_t init_operation(TEEC_Operation *operation, cc_enclave_call_function_args_t *args) { const int input_pos = 0; @@ -462,21 +591,121 @@ static cc_enclave_result_t init_operation(TEEC_Operation *operation, cc_enclave_ operation->params[inout_pos].tmpref.size = sizeof(*args); paramtypes[inout_pos] = TEEC_MEMREF_TEMP_INOUT; + /* Fill shared buffer */ + if (args->function_id == fid_register_shared_memory) { + gp_shared_memory_t *shared_mem = GP_SHARED_MEMORY_ENTRY(GET_HOST_BUF_FROM_INPUT_PARAMS(args->input_buffer)); + TEEC_SharedMemory *teec_shared_mem = (TEEC_SharedMemory *)(&shared_mem->shared_mem); + operation->params[other_pos].memref.parent = teec_shared_mem; + operation->params[other_pos].memref.size = teec_shared_mem->size; + paramtypes[other_pos] = TEEC_MEMREF_SHARED_INOUT; + } + operation->paramTypes = TEEC_PARAM_TYPES( paramtypes[input_pos], paramtypes[output_pos], paramtypes[inout_pos], paramtypes[other_pos]); return CC_SUCCESS; } -static cc_enclave_result_t handle_ecall_function( - cc_enclave_t *enclave, - cc_enclave_call_function_args_t *args) +void *handle_ecall_function_with_new_session(void *data) +{ + cc_enclave_call_function_args_t *args = (cc_enclave_call_function_args_t *)data; + gp_context_t *gp = (gp_context_t *)(((cc_enclave_t *)args->enclave)->private_data); + + TEEC_Operation oper; + memset(&oper, 0, sizeof(oper)); + oper.started = 1; + oper.paramTypes = TEEC_PARAM_TYPES(TEEC_NONE, TEEC_NONE, TEEC_MEMREF_TEMP_INPUT, TEEC_MEMREF_TEMP_INPUT); + + uint32_t origin; + TEEC_Session session; + TEEC_Result result = TEEC_OpenSession(&gp->ctx, &session, &gp->uuid, TEEC_LOGIN_IDENTIFY, NULL, &oper, &origin); + if (result != TEEC_SUCCESS) { + print_error_goto("Handle ecall with new session, failed to open session, ret:%x, origin:%x\n", result, origin); + } + + cc_enclave_result_t cc_res = init_operation(&oper, args); + if (cc_res != CC_SUCCESS) { + TEEC_CloseSession(&session); + print_error_goto("Handle ecall with new session, failed to init operation, ret:%x\n", cc_res); + } + + result = TEEC_InvokeCommand(&session, SECGEAR_ECALL_FUNCTION, &oper, &origin); + if (result != TEEC_SUCCESS || args->result != CC_SUCCESS) { + TEEC_CloseSession(&session); + print_error_goto("Handle ecall with new session, failed to invoke cmd, ret:%x\n", result); + } + + TEEC_CloseSession(&session); + +done: + free(args); + return NULL; +} + +#define REGISTER_SHAREDMEM_GETTIME_PER_CNT 100000000 +#define REGISTER_SHAREDMEM_TIMEOUT_IN_SEC 3 + +cc_enclave_result_t handle_ecall_function_register_shared_memory(cc_enclave_t *enclave, + cc_enclave_call_function_args_t *args) +{ + CC_IGNORE(enclave); + int count = 0; + struct timespec start; + struct timespec end; + + size_t buf_len = sizeof(cc_enclave_call_function_args_t) + args->input_buffer_size + args->output_buffer_size; + char *buf = (char *)calloc(buf_len, sizeof(char)); + if (buf == NULL) { + return CC_ERROR_OUT_OF_MEMORY; + } + + /* Copy parameters */ + cc_enclave_call_function_args_t *tmpArgs = (cc_enclave_call_function_args_t *)buf; + (void)memcpy(tmpArgs, args, sizeof(cc_enclave_call_function_args_t)); + + tmpArgs->input_buffer = buf + sizeof(cc_enclave_call_function_args_t); + (void)memcpy(buf + sizeof(cc_enclave_call_function_args_t), args->input_buffer, args->input_buffer_size); + + tmpArgs->output_buffer = buf + sizeof(cc_enclave_call_function_args_t) + args->input_buffer_size; + (void)memcpy(buf + sizeof(cc_enclave_call_function_args_t) + args->input_buffer_size, args->output_buffer, + args->output_buffer_size); + + gp_shared_memory_t *shared_mem = GP_SHARED_MEMORY_ENTRY(GET_HOST_BUF_FROM_INPUT_PARAMS(args->input_buffer)); + if (pthread_create(&shared_mem->register_tid, NULL, handle_ecall_function_with_new_session, tmpArgs) != 0) { + free(buf); + return CC_FAIL; + } + + /* Waiting for registration success */ + clock_gettime(CLOCK_MONOTONIC_COARSE, &start); + while (__atomic_load_n(&shared_mem->is_registered, __ATOMIC_ACQUIRE) == false) { + __asm__ __volatile__("yield" : : : "memory"); + + if (count > REGISTER_SHAREDMEM_GETTIME_PER_CNT) { + clock_gettime(CLOCK_MONOTONIC_COARSE, &end); + if (end.tv_sec - start.tv_sec > REGISTER_SHAREDMEM_TIMEOUT_IN_SEC) { + return CC_ERROR_TIMEOUT; + } + count = 0; + } + ++count; + } + + return CC_SUCCESS; +} + +static cc_enclave_result_t handle_ecall_function(cc_enclave_t *enclave, cc_enclave_call_function_args_t *args) { cc_enclave_result_t cc_res; TEEC_Result result; TEEC_Operation operation; uint32_t origin; gp_context_t *gp = (gp_context_t*)enclave->private_data; + + if (args->function_id == fid_register_shared_memory) { + return handle_ecall_function_register_shared_memory(enclave, args); + } + cc_res = init_operation(&operation, args); if (cc_res != CC_SUCCESS) { goto done; @@ -577,6 +806,7 @@ cc_enclave_result_t cc_enclave_call_function( args.output_buffer_size = output_buffer_size; args.output_bytes_written = 0; args.result = CC_FAIL; + args.enclave = enclave; result = handle_ecall_function(enclave, &args); if (result != CC_SUCCESS) { goto done; @@ -587,10 +817,41 @@ done: return result; } +cc_enclave_result_t cc_sl_enclave_call_function(cc_enclave_t *enclave, + void *retval, + size_t retval_size, + sl_ecall_func_info_t *func_info) +{ + if (!uswitchless_is_switchless_enabled(enclave)) { + return CC_ERROR_SWITCHLESS_DISABLED; + } + + if (!uswitchless_is_valid_param_num(enclave, func_info->argc)) { + return CC_ERROR_SWITCHLESS_INVALID_ARG_NUM; + } + + int task_index = uswitchless_get_idle_task_index(enclave); + if (task_index < 0) { + return CC_ERROR_SWITCHLESS_TASK_POOL_FULL; + } + + uswitchless_fill_task(enclave, task_index, func_info->func_id, func_info->argc, func_info->args); + uswitchless_submit_task(enclave, task_index); + cc_enclave_result_t ret = uswitchless_get_task_result(enclave, task_index, retval, retval_size); + uswitchless_put_idle_task_by_index(enclave, task_index); + + return ret; +} + const struct cc_enclave_ops g_ops = { - .cc_create_enclave = _gp_create, - .cc_destroy_enclave = _gp_destroy, - .cc_ecall_enclave = cc_enclave_call_function, + .cc_create_enclave = _gp_create, + .cc_destroy_enclave = _gp_destroy, + .cc_ecall_enclave = cc_enclave_call_function, + .cc_sl_ecall_enclave = cc_sl_enclave_call_function, + .cc_malloc_shared_memory = gp_malloc_shared_memory, + .cc_free_shared_memory = gp_free_shared_memory, + .cc_register_shared_memory = gp_register_shared_memory, + .cc_unregister_shared_memory = gp_unregister_shared_memory }; struct cc_enclave_ops_desc g_name = { diff --git a/src/host_src/gp/gp_enclave.h b/src/host_src/gp/gp_enclave.h index 52dc911..e788ed3 100644 --- a/src/host_src/gp/gp_enclave.h +++ b/src/host_src/gp/gp_enclave.h @@ -14,16 +14,18 @@ #define FINAL_SECGEAR_GP_ENCLAVE_H #include "tee_client_api.h" +#include "switchless_defs.h" enum { SECGEAR_ECALL_FUNCTION = 0, }; -typedef struct _gp_context{ +typedef struct _gp_context { TEEC_UUID uuid; TEEC_Context ctx; TEEC_Session session; + sl_task_pool_t *sl_task_pool; } gp_context_t; typedef struct _thread_param { diff --git a/src/host_src/gp/gp_shared_memory.c b/src/host_src/gp/gp_shared_memory.c new file mode 100644 index 0000000..60520a4 --- /dev/null +++ b/src/host_src/gp/gp_shared_memory.c @@ -0,0 +1,264 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 "gp_shared_memory.h" + +#include <stdlib.h> +#include <pthread.h> +#include <tee_client_type.h> +#include "secgear_defs.h" +#include "gp_shared_memory_defs.h" +#include "enclave_internal.h" +#include "gp_enclave.h" +#include "gp_uswitchless.h" +#include "secgear_list.h" +#include "enclave_log.h" +#include "status.h" + +#define TEEC_SHARED_MEMORY_ENTRY(ptr) \ + ((TEEC_SharedMemory *)((char *)(ptr) - sizeof(gp_shared_memory_t))) + +static pthread_rwlock_t g_shared_mem_list_lock = PTHREAD_RWLOCK_INITIALIZER; +static list_node_t g_shared_mem_list = { + .next = &g_shared_mem_list, + .prev = &g_shared_mem_list +}; + +static void gp_remove_shared_mem_from_list(gp_shared_memory_t *shared_mem) +{ + CC_RWLOCK_LOCK_WR(&g_shared_mem_list_lock); + list_remove(&shared_mem->node); + CC_RWLOCK_UNLOCK(&g_shared_mem_list_lock); +} + +static void gp_add_shared_mem_to_list(gp_shared_memory_t *shared_mem) +{ + CC_RWLOCK_LOCK_WR(&g_shared_mem_list_lock); + list_add_after(&shared_mem->node, &g_shared_mem_list); + CC_RWLOCK_UNLOCK(&g_shared_mem_list_lock); +} + +void *gp_malloc_shared_memory(cc_enclave_t *context, size_t size, bool is_control_buf) +{ + gp_context_t *gp_context = (gp_context_t *)context->private_data; + gp_shared_memory_t gp_shared_mem = { + .is_control_buf = is_control_buf, + .is_registered = false, + .enclave = (void *) context, + .register_tid = 0 + }; + TEEC_SharedMemory *teec_shared_mem = (TEEC_SharedMemory *)(&gp_shared_mem.shared_mem); + teec_shared_mem->size = size + sizeof(gp_shared_memory_t); + teec_shared_mem->flags = TEEC_MEM_SHARED_INOUT; + + TEEC_Result result = TEEC_AllocateSharedMemory(&gp_context->ctx, teec_shared_mem); + if (result != TEEC_SUCCESS) { + return NULL; + } + + // save meta data + (void)memcpy(teec_shared_mem->buffer, &gp_shared_mem, sizeof(gp_shared_mem)); + + gp_add_shared_mem_to_list((gp_shared_memory_t *)teec_shared_mem->buffer); + return (char *)teec_shared_mem->buffer + sizeof(gp_shared_mem); +} + +static bool gp_is_shared_mem_start_addr(const void *ptr) +{ + size_t addr = (size_t)ptr; + bool isExist = false; + list_node_t *cur = NULL; + gp_shared_memory_t *mem = NULL; + + CC_RWLOCK_LOCK_RD(&g_shared_mem_list_lock); + list_for_each(cur, &g_shared_mem_list) { + mem = list_entry(cur, gp_shared_memory_t, node); + if (addr == (size_t)((char *)mem + sizeof(gp_shared_memory_t))) { + isExist = true; + break; + } + } + CC_RWLOCK_UNLOCK(&g_shared_mem_list_lock); + + return isExist; +} + +cc_enclave_result_t gp_free_shared_memory(cc_enclave_t *enclave, void *ptr) +{ + CC_IGNORE(enclave); + + if (!gp_is_shared_mem_start_addr(ptr)) { + print_error_term("GP free shared memory failed: invalid shared memory start address.\n"); + return CC_ERROR_SHARED_MEMORY_NOT_REGISTERED; + } + + if (GP_SHARED_MEMORY_ENTRY(ptr)->enclave != enclave) { + return CC_ERROR_INVALID_HANDLE; + } + + gp_remove_shared_mem_from_list(GP_SHARED_MEMORY_ENTRY(ptr)); + + TEEC_SharedMemory sharedMem = *TEEC_SHARED_MEMORY_ENTRY(ptr); + TEEC_ReleaseSharedMemory(&sharedMem); + + return CC_SUCCESS; +} + +#ifndef TEE_SECE_AGENT_ID +#define TEE_SECE_AGENT_ID 0x53656345 +#endif + +#define PARAM_OFFSET_MOVE(cur_param_offset, offset_var_name, cur_param_size) \ + size_t offset_var_name = cur_param_offset; \ + cur_param_offset += (cur_param_size) + +cc_enclave_result_t gp_register_shared_memory(cc_enclave_t *enclave, void *ptr) +{ + uint32_t ms = TEE_SECE_AGENT_ID; + + if (!gp_is_shared_mem_start_addr(ptr)) { + return CC_ERROR_SHARED_MEMORY_START_ADDR_INVALID; + } + + gp_shared_memory_t *gp_shared_mem = GP_SHARED_MEMORY_ENTRY(ptr); + if (!gp_shared_mem->is_control_buf && !uswitchless_is_switchless_enabled(enclave)) { + return CC_ERROR_SWITCHLESS_DISABLED; + } + + if (GP_SHARED_MEMORY_ENTRY(ptr)->enclave != enclave) { + return CC_ERROR_INVALID_HANDLE; + } + + if (__atomic_load_n(&gp_shared_mem->is_registered, __ATOMIC_ACQUIRE)) { + return CC_ERROR_SHARED_MEMORY_REPEAT_REGISTER; + } + + gp_register_shared_memory_size_t args_size = { + .retval_size = size_to_aligned_size(sizeof(int)), + .shared_buf_size = size_to_aligned_size(sizeof(void *)), + .shared_buf_len_size = size_to_aligned_size(sizeof(size_t)), + .is_control_buf_size = size_to_aligned_size(sizeof(bool)) + }; + + /* Calculate the input parameter offset. */ + size_t in_param_buf_size = size_to_aligned_size(sizeof(args_size)); + PARAM_OFFSET_MOVE(in_param_buf_size, ptr_offset, args_size.shared_buf_size); + PARAM_OFFSET_MOVE(in_param_buf_size, ptr_len_offset, args_size.shared_buf_len_size); + PARAM_OFFSET_MOVE(in_param_buf_size, is_control_buf_offset, args_size.is_control_buf_size); + + /* Calculate the output parameter offset. */ + size_t out_param_buf_size = 0; + PARAM_OFFSET_MOVE(out_param_buf_size, retval_offset, args_size.retval_size); + + /* Allocate in_buf and out_buf */ + char *param_buf = (char *)calloc(in_param_buf_size + out_param_buf_size, sizeof(char)); + if (param_buf == NULL) { + return CC_ERROR_OUT_OF_MEMORY; + } + + char *in_param_buf = param_buf; + char *out_param_buf = param_buf + in_param_buf_size; + + /* Copy in_params to in_buf */ + memcpy(in_param_buf, &args_size, size_to_aligned_size(sizeof(args_size))); + memcpy(in_param_buf + ptr_offset, &ptr, sizeof(void*)); + size_t shared_mem_size = ((TEEC_SharedMemory *)(&gp_shared_mem->shared_mem))->size - sizeof(gp_shared_memory_t); + memcpy(in_param_buf + ptr_len_offset, &shared_mem_size, sizeof(size_t)); + memcpy(in_param_buf + is_control_buf_offset, &gp_shared_mem->is_control_buf, sizeof(bool)); + + /* Call the cc_enclave function */ + cc_enclave_result_t ret = enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave(enclave, + fid_register_shared_memory, in_param_buf, in_param_buf_size, out_param_buf, out_param_buf_size, &ms, NULL); + if (ret != CC_SUCCESS) { + free(param_buf); + return ret; + } + + /* Copy out_buf to out_params */ + int retval = 0; + (void)memcpy(&retval, out_param_buf + retval_offset, sizeof(int)); + if (retval != (int)CC_SUCCESS) { + free(param_buf); + return CC_FAIL; + } + + free(param_buf); + return CC_SUCCESS; +} + +cc_enclave_result_t gp_unregister_shared_memory(cc_enclave_t *enclave, void* ptr) +{ + uint32_t ms = TEE_SECE_AGENT_ID; + + if (!gp_is_shared_mem_start_addr(ptr)) { + return CC_ERROR_SHARED_MEMORY_START_ADDR_INVALID; + } + + if (GP_SHARED_MEMORY_ENTRY(ptr)->enclave != enclave) { + return CC_ERROR_INVALID_HANDLE; + } + + gp_shared_memory_t *gp_shared_mem = GP_SHARED_MEMORY_ENTRY(ptr); + if (!__atomic_load_n(&gp_shared_mem->is_registered, __ATOMIC_ACQUIRE)) { + return CC_ERROR_SHARED_MEMORY_NOT_REGISTERED; + } + + /* Fill argments size */ + gp_unregister_shared_memory_size_t args_size = { + .retval_size = size_to_aligned_size(sizeof(int)), + .shared_buf_size = size_to_aligned_size(sizeof(void *)) + }; + + /* Calculate the input parameter offset. */ + size_t in_param_buf_size = size_to_aligned_size(sizeof(args_size)); + PARAM_OFFSET_MOVE(in_param_buf_size, ptr_offset, args_size.shared_buf_size); + + /* Calculate the output parameter offset. */ + size_t out_param_buf_size = 0; + PARAM_OFFSET_MOVE(out_param_buf_size, retval_offset, args_size.retval_size); + + /* Allocate in_buf and out_buf */ + char *param_buf = (char *)calloc(in_param_buf_size + out_param_buf_size, sizeof(char)); + if (param_buf == NULL) { + return CC_ERROR_OUT_OF_MEMORY; + } + + char *in_param_buf = param_buf; + char *out_param_buf = param_buf + in_param_buf_size; + + /* Copy in_params to in_buf */ + memcpy(in_param_buf, &args_size, size_to_aligned_size(sizeof(args_size))); + memcpy(in_param_buf + ptr_offset, &ptr, sizeof(void*)); + + cc_enclave_result_t ret = enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave(enclave, + fid_unregister_shared_memory, in_param_buf, in_param_buf_size, out_param_buf, out_param_buf_size, &ms, NULL); + if (ret != CC_SUCCESS) { + free(param_buf); + return ret; + } + + /* Copy out_buf to out_params */ + int retval = 0; + (void)memcpy(&retval, out_param_buf + retval_offset, sizeof(int)); + if (retval != (int)CC_SUCCESS) { + free(param_buf); + return CC_FAIL; + } + + if (gp_shared_mem->register_tid) { + (void)pthread_join(gp_shared_mem->register_tid, NULL); + gp_shared_mem->register_tid = 0; + } + + free(param_buf); + return CC_SUCCESS; +} diff --git a/src/host_src/gp/gp_shared_memory.h b/src/host_src/gp/gp_shared_memory.h new file mode 100644 index 0000000..2ec66a8 --- /dev/null +++ b/src/host_src/gp/gp_shared_memory.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 __GP_SHARED_MEMORY_H__ +#define __GP_SHARED_MEMORY_H__ + +#include <stdint.h> +#include <stdbool.h> +#include <stddef.h> +#include "enclave.h" +#include "status.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Summary: Allocates size bytes and returns a pointer to the allocated memory. + * Parameters: + * context: enclave + * size: buffer length + * is_control_buf: whether it is a control area buffer + * Return: A pointer to the allocated memory. On error, return NULL. + */ +void *gp_malloc_shared_memory(cc_enclave_t *context, size_t size, bool is_control_buf); + +/* + * Summary: Frees the memory space pointed to by ptr, which must have been returned by gp_malloc_shared_memory. + * Parameters: + * context: enclave + * ptr: buffer address + * Return: CC_SUCCESS, success; others failed. + */ +cc_enclave_result_t gp_free_shared_memory(cc_enclave_t *context, void *ptr); + +/* + * Summary: Register a pointer to enclave, which must have been returned by gp_malloc_shared_memory. + * Parameters: + * enclave: enclave + * ptr: buffer address + * Return: CC_SUCCESS, success; others failed. + */ +cc_enclave_result_t gp_register_shared_memory(cc_enclave_t *enclave, void *ptr); + +/* + * Summary: Unregister a pointer from enclave, which must have been returned by gp_malloc_shared_memory. + * Parameters: + * enclave: enclave + * ptr: buffer address + * Return: CC_SUCCESS, success; others failed. + */ +cc_enclave_result_t gp_unregister_shared_memory(cc_enclave_t *enclave, void *ptr); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/host_src/gp/gp_uswitchless.c b/src/host_src/gp/gp_uswitchless.c new file mode 100644 index 0000000..8db756e --- /dev/null +++ b/src/host_src/gp/gp_uswitchless.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 "gp_uswitchless.h" + +#include <stdint.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "status.h" +#include "bit_operation.h" +#include "enclave_internal.h" +#include "gp_enclave.h" + + +#define USWITCHLESS_TASK_POOL(enclave) (((gp_context_t *)((enclave)->private_data))->sl_task_pool) + +#define SWITCHLESS_MAX_UWORKERS 512 +#define SWITCHLESS_MAX_TWORKERS 512 +#define SWITCHLESS_MAX_PARAMETER_NUM 16 +#define SWITCHLESS_MAX_POOL_SIZE_QWORDS 8 +#define SWITCHLESS_DEFAULT_UWORKERS 8 +#define SWITCHLESS_DEFAULT_TWORKERS 8 +#define SWITCHLESS_DEFAULT_POOL_SIZE_QWORDS 1 + +bool uswitchless_is_valid_config(sl_task_pool_config_t *cfg) +{ + if ((cfg->num_uworkers > SWITCHLESS_MAX_UWORKERS) || + (cfg->num_tworkers > SWITCHLESS_MAX_TWORKERS) || + (cfg->num_max_params > SWITCHLESS_MAX_PARAMETER_NUM) || + (cfg->call_pool_size_qwords > SWITCHLESS_MAX_POOL_SIZE_QWORDS)) { + return false; + } + + return true; +} + +void uswitchless_adjust_config(sl_task_pool_config_t *cfg) +{ + if (cfg->num_uworkers == 0) { + cfg->num_uworkers = SWITCHLESS_DEFAULT_UWORKERS; + } + + if (cfg->num_tworkers == 0) { + cfg->num_tworkers = SWITCHLESS_DEFAULT_TWORKERS; + } + + if (cfg->call_pool_size_qwords == 0) { + cfg->call_pool_size_qwords = SWITCHLESS_DEFAULT_POOL_SIZE_QWORDS; + } +} + +sl_task_pool_t *uswitchless_create_task_pool(void *pool_buf, sl_task_pool_config_t *pool_cfg) +{ + size_t bit_buf_size = pool_cfg->call_pool_size_qwords * sizeof(uint64_t); + sl_task_pool_t *pool = (sl_task_pool_t *)calloc(sizeof(sl_task_pool_t) + bit_buf_size, sizeof(char)); + if (pool == NULL) { + return NULL; + } + + pool->pool_cfg = *pool_cfg; + pool->bit_buf_size = bit_buf_size; + pool->per_task_size = SL_CALCULATE_PER_TASK_SIZE(pool_cfg); + + pool->pool_buf = (char *)pool_buf; + pool->free_bit_buf = (uint64_t *)((char *)pool + sizeof(sl_task_pool_t)); + (void)memset(pool->free_bit_buf, 0xFF, bit_buf_size); + pool->signal_bit_buf = (uint64_t *)(pool->pool_buf + sizeof(sl_task_pool_config_t)); + pool->task_buf = (char *)pool->signal_bit_buf + pool->bit_buf_size; + + return pool; +} + +bool uswitchless_is_switchless_enabled(cc_enclave_t *enclave) +{ + if ((enclave != NULL) && (enclave->private_data != NULL) && (USWITCHLESS_TASK_POOL(enclave) != NULL)) { + return true; + } + + return false; +} + +bool uswitchless_is_valid_param_num(cc_enclave_t *enclave, uint32_t argc) +{ + return argc <= USWITCHLESS_TASK_POOL(enclave)->pool_cfg.num_max_params; +} + +int uswitchless_get_idle_task_index(cc_enclave_t *enclave) +{ + sl_task_pool_t *pool = USWITCHLESS_TASK_POOL(enclave); + int call_pool_size_qwords = (int)pool->pool_cfg.call_pool_size_qwords; + uint64_t *free_bit_buf = pool->free_bit_buf; + int start_bit = 0; + int end_bit = 0; + uint64_t *element_ptr = NULL; + uint64_t element_val = 0; + + for (int i = 0; i < call_pool_size_qwords; ++i) { + element_ptr = free_bit_buf + i; + element_val = *element_ptr; + + if (element_val == 0) { + continue; + } + + start_bit = count_tailing_zeroes(element_val); + end_bit = SWITCHLESS_BITS_IN_QWORD - count_leading_zeroes(element_val); + + for (int j = start_bit; j < end_bit; ++j) { + if (test_and_clear_bit(element_ptr, j) != 0) { + return i * SWITCHLESS_BITS_IN_QWORD + j; + } + } + } + + return -1; +} + +void uswitchless_put_idle_task_by_index(cc_enclave_t *enclave, int task_index) +{ + int i = task_index / SWITCHLESS_BITS_IN_QWORD; + int j = task_index % SWITCHLESS_BITS_IN_QWORD; + sl_task_pool_t *pool = USWITCHLESS_TASK_POOL(enclave); + + set_bit(pool->free_bit_buf + i, j); +} + +static inline sl_task_t *uswitchless_get_task_by_index(cc_enclave_t *enclave, int task_index) +{ + sl_task_pool_t *pool = USWITCHLESS_TASK_POOL(enclave); + + return (sl_task_t *)(pool->task_buf + task_index * pool->per_task_size); +} + +void uswitchless_fill_task(cc_enclave_t *enclave, int task_index, uint32_t func_id, uint32_t argc, const void *args) +{ + sl_task_t *task = uswitchless_get_task_by_index(enclave, task_index); + + task->func_id = func_id; + __atomic_store_n(&task->status, SL_TASK_INIT, __ATOMIC_RELEASE); + memcpy(&task->params[0], args, sizeof(uint64_t) * argc); +} + +void uswitchless_submit_task(cc_enclave_t *enclave, int task_index) +{ + sl_task_t *task = uswitchless_get_task_by_index(enclave, task_index); + __atomic_store_n(&task->status, SL_TASK_SUBMITTED, __ATOMIC_RELEASE); + + int i = task_index / SWITCHLESS_BITS_IN_QWORD; + int j = task_index % SWITCHLESS_BITS_IN_QWORD; + set_bit(USWITCHLESS_TASK_POOL(enclave)->signal_bit_buf + i, j); +} + +#define CA_TIMEOUT_IN_SEC 60 +#define CA_GETTIME_PER_CNT 100000000 +cc_enclave_result_t uswitchless_get_task_result(cc_enclave_t *enclave, int task_index, void *retval, size_t retval_size) +{ + sl_task_t *task = uswitchless_get_task_by_index(enclave, task_index); + uint32_t cur_status; + int count = 0; + struct timespec start; + struct timespec end; + + clock_gettime(CLOCK_MONOTONIC_COARSE, &start); + + while (true) { + cur_status = __atomic_load_n(&task->status, __ATOMIC_ACQUIRE); + if (cur_status == SL_TASK_DONE_SUCCESS) { + if ((retval != NULL) && (retval_size != 0)) { + (void)memcpy(retval, (void *)&task->ret_val, retval_size); + } + + return CC_SUCCESS; + } else if (cur_status == SL_TASK_DONE_FAILED) { + return (cc_enclave_result_t)task->ret_val; + } + + if (count > CA_GETTIME_PER_CNT) { + clock_gettime(CLOCK_MONOTONIC_COARSE, &end); + if (end.tv_sec - start.tv_sec > CA_TIMEOUT_IN_SEC) { + break; + } + count = 0; + } + ++count; + } + + return CC_ERROR_TIMEOUT; +} diff --git a/src/host_src/gp/gp_uswitchless.h b/src/host_src/gp/gp_uswitchless.h new file mode 100644 index 0000000..e435ad1 --- /dev/null +++ b/src/host_src/gp/gp_uswitchless.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 __GP_USWITCHLESS_H__ +#define __GP_USWITCHLESS_H__ + +#include <stdint.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdbool.h> +#include "enclave.h" +#include "switchless_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Summary: Check the validity of the configuration + * Parameters: + * cfg: configuration information of the task pool + * Return: + * true: valid + * false: invalid + */ +bool uswitchless_is_valid_config(sl_task_pool_config_t *cfg); + +/* + * Summary: Adjusting default configurations + * Parameters: + * cfg: configuration information of the task pool + * Return: NA + */ +void uswitchless_adjust_config(sl_task_pool_config_t *cfg); + +/* + * Summary: initializing the switchless invoking task pool + * Parameters: + * pool_buf: address of the task pool + * pool_cfg: configuration information of the task pool + * Return: NA + */ +sl_task_pool_t *uswitchless_create_task_pool(void *pool_buf, sl_task_pool_config_t *pool_cfg); + +/* + * Summary: obtains the index of an idle task area from specified enclave + * Parameters: + * enclave: enclave + * Return: + * -1: no idle task area + * other: index of an idle task area + */ +int uswitchless_get_idle_task_index(cc_enclave_t *enclave); + +/* + * Summary: Releasing an idle task area + * Parameters: + * enclave: enclave + * task_index: index of an idle task area + * Return: NA + */ +void uswitchless_put_idle_task_by_index(cc_enclave_t *enclave, int task_index); + +/* + * Summary: submitting a switchless ecall task + * Parameters: + * enclave: enclave + * task_index: index of an task area + * Return: NA + */ +void uswitchless_submit_task(cc_enclave_t *enclave, int task_index); + +/* + * Summary: submitting a task + * Parameters: + * enclave: enclave + * task_index: index of an task area + * ret_val: address that accepts the return value + * ret_val_size: size of the return value + * Return: CC_SUCCESS, success; others failed. + */ +cc_enclave_result_t uswitchless_get_task_result(cc_enclave_t *enclave, + int task_index, + void *ret_val, + size_t ret_val_size); + +/* + * Summary: whether the switchless features is enabled + * Parameters: + * enclave: enclave + * Return: + * true: enalbe + * false: disabled + */ +bool uswitchless_is_switchless_enabled(cc_enclave_t *enclave); + +/* + * Summary: whether the number of switchless ecall parameters is valid + * Parameters: + * enclave: enclave + * argc: number of parameters + * Return: + * true: the number of parameters is valid + * false: invalid number of parameters + */ +bool uswitchless_is_valid_param_num(cc_enclave_t *enclave, uint32_t argc); + +/* + * Summary: fill a task + * Parameters: + * enclave: enclave + * task_index: index of an task area + * func_id: switchless function index + * argc: number of parameters + * args: parameter buffer + * Return: NA + */ +void uswitchless_fill_task(cc_enclave_t *enclave, int task_index, uint32_t func_id, uint32_t argc, const void *args); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/host_src/secgear_shared_memory.c b/src/host_src/secgear_shared_memory.c new file mode 100644 index 0000000..d7e8d35 --- /dev/null +++ b/src/host_src/secgear_shared_memory.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 "secgear_shared_memory.h" + +#include "status.h" +#include "enclave_internal.h" +#include "gp_shared_memory_defs.h" +#include "secgear_defs.h" + +#define FUNC_CREATE_SHARED_MEM(enclave) \ + (enclave)->list_ops_node->ops_desc->ops->cc_malloc_shared_memory +#define FUNC_FREE_SHARED_MEM(enclave) \ + (enclave)->list_ops_node->ops_desc->ops->cc_free_shared_memory +#define FUNC_REGISTER_SHARED_MEM(enclave) \ + (enclave)->list_ops_node->ops_desc->ops->cc_register_shared_memory +#define FUNC_UNREGISTER_SHARED_MEM(enclave) \ + (enclave)->list_ops_node->ops_desc->ops->cc_unregister_shared_memory + +void *cc_malloc_shared_memory(cc_enclave_t *enclave, size_t size) +{ + if (enclave == NULL || size == 0 || !enclave->used_flag) { + return NULL; + } + + CC_RWLOCK_LOCK_RD(&enclave->rwlock); + + if (enclave->list_ops_node == NULL || FUNC_CREATE_SHARED_MEM(enclave) == NULL || + FUNC_REGISTER_SHARED_MEM(enclave) == NULL || FUNC_FREE_SHARED_MEM(enclave) == NULL) { + CC_RWLOCK_UNLOCK(&enclave->rwlock); + return NULL; + } + + void *ptr = FUNC_CREATE_SHARED_MEM(enclave)(enclave, size, false); + if (ptr == NULL) { + CC_RWLOCK_UNLOCK(&enclave->rwlock); + return NULL; + } + + cc_enclave_result_t ret = FUNC_REGISTER_SHARED_MEM(enclave)(enclave, ptr); + if (ret != CC_SUCCESS) { + CC_IGNORE(FUNC_FREE_SHARED_MEM(enclave)(enclave, ptr)); + CC_RWLOCK_UNLOCK(&enclave->rwlock); + return NULL; + } + + CC_RWLOCK_UNLOCK(&enclave->rwlock); + + return ptr; +} + +cc_enclave_result_t cc_free_shared_memory(cc_enclave_t *enclave, void *ptr) +{ + if (enclave == NULL || ptr == NULL) { + return CC_ERROR_BAD_PARAMETERS; + } + + CC_RWLOCK_LOCK_RD(&enclave->rwlock); + + if (enclave->list_ops_node == NULL || FUNC_FREE_SHARED_MEM(enclave) == NULL || + FUNC_UNREGISTER_SHARED_MEM(enclave) == NULL) { + CC_RWLOCK_UNLOCK(&enclave->rwlock); + return CC_ERROR_NOT_IMPLEMENTED; + } + + cc_enclave_result_t ret = FUNC_UNREGISTER_SHARED_MEM(enclave)(enclave, ptr); + if (ret != CC_SUCCESS) { + CC_RWLOCK_UNLOCK(&enclave->rwlock); + return ret; + } + + ret = FUNC_FREE_SHARED_MEM(enclave)(enclave, ptr); + + CC_RWLOCK_UNLOCK(&enclave->rwlock); + + return ret; +} \ No newline at end of file diff --git a/src/host_src/sgx/CMakeLists.txt b/src/host_src/sgx/CMakeLists.txt index d77fdd5..e6bafbb 100644 --- a/src/host_src/sgx/CMakeLists.txt +++ b/src/host_src/sgx/CMakeLists.txt @@ -17,8 +17,8 @@ if(${CMAKE_VERSION} VERSION_LESS "3.13.0") ${CMAKE_BINARY_DIR}/lib) endif() -add_library(${sgx_engine} SHARED sgx_enclave.c sgx_enclave.h ) -add_library(${sgxsim_engine} SHARED sgx_enclave.c sgx_enclave.h ) +add_library(${sgx_engine} SHARED sgx_enclave.c sgx_enclave.h sgx_shared_memory.c) +add_library(${sgxsim_engine} SHARED sgx_enclave.c sgx_enclave.h sgx_shared_memory.c) target_include_directories(${sgx_engine} PRIVATE ${SGXSDK}/include) @@ -53,3 +53,11 @@ install(TARGETS ${sgxsim_engine} LIBRARY DESTINATION ${LIBRARY_INSTALL} PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +file(GLOB GP_HOST_HEADERS_1 ${LOCAL_ROOT_PATH}/inc/host_inc/*.h) +file(GLOB GP_HOST_HEADERS_2 ${LOCAL_ROOT_PATH}/inc/host_inc/sgx/*.h) +file(GLOB GP_HOST_HEADERS_3 ${LOCAL_ROOT_PATH}/inc/host_inc/sgx/*.edl) + +install(FILES ${GP_HOST_HEADERS_1} ${GP_HOST_HEADERS_2} ${GP_HOST_HEADERS_3} + DESTINATION /usr/include/secGear + PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) + diff --git a/src/host_src/sgx/sgx_enclave.c b/src/host_src/sgx/sgx_enclave.c index 7b61ba8..89a9b31 100644 --- a/src/host_src/sgx/sgx_enclave.c +++ b/src/host_src/sgx/sgx_enclave.c @@ -21,6 +21,8 @@ #include "sgx_uswitchless.h" #include "sgx_edger8r.h" #include "sgx_urts.h" +#include "secgear_uswitchless.h" +#include "sgx_shared_memory.h" extern list_ops_management g_list_ops; @@ -79,16 +81,19 @@ cc_enclave_result_t _sgx_create_with_features(cc_enclave_t *enclave, const encla const void *enclave_ex_p[32] = { 0 }; cesgx_plc_config_t *l_plc = NULL; - cesgx_switch_config_t *l_switch = NULL; + cc_sl_config_t *l_switch = NULL; if (features->setting_type & _CESGX_SWITCHLESS_FEATURES) { res = CC_ERROR_BAD_PARAMETERS; - l_switch = (cesgx_switch_config_t *)features->feature_desc; + l_switch = (cc_sl_config_t *)features->feature_desc; /* check host and worker configuration */ - SECGEAR_CHECK_SIZE(l_switch->host_worker); - SECGEAR_CHECK_SIZE(l_switch->enclave_worker); + SECGEAR_CHECK_SIZE(l_switch->num_uworkers); + SECGEAR_CHECK_SIZE(l_switch->num_tworkers); - l_config.num_tworkers = l_switch->enclave_worker; - l_config.num_uworkers = l_switch->host_worker; + l_config.num_tworkers = l_switch->num_tworkers; + l_config.num_uworkers = l_switch->num_uworkers; + l_config.switchless_calls_pool_size_qwords = l_switch->sl_call_pool_size_qwords; + l_config.retries_before_fallback = l_switch->retries_before_fallback; + l_config.retries_before_sleep = l_switch->retries_before_sleep; enclave_ex_p[SGX_CREATE_ENCLAVE_EX_SWITCHLESS_BIT_IDX] = (const void *)&l_config; sgx_res = sgx_create_enclave_ex(enclave->path, (uint32_t)(enclave->flags & SECGEAR_DEBUG_FLAG), NULL, @@ -205,11 +210,37 @@ cc_enclave_result_t cc_enclave_sgx_call_function( cc_status = conversion_res_status(status, enclave->type); return cc_status; } + +cc_enclave_result_t cc_enclave_sgx_call_function_switchless( + cc_enclave_t *enclave, + uint32_t function_id, + const void *input_buffer, + size_t input_buffer_size, + void *output_buffer, + size_t output_buffer_size, + void *ms, + const void *ocall_table) +{ + (void)input_buffer; + (void)input_buffer_size; + (void)output_buffer; + (void)output_buffer_size; + sgx_status_t status; + cc_enclave_result_t cc_status; + status = sgx_ecall_switchless(((sgx_context_t *)(enclave->private_data))->edi, (int)function_id, ocall_table, ms); + cc_status = conversion_res_status(status, enclave->type); + return cc_status; +} const struct cc_enclave_ops sgx_ops = { .cc_create_enclave = _sgx_create, .cc_destroy_enclave = _sgx_destroy, .cc_ecall_enclave = cc_enclave_sgx_call_function, + .cc_ecall_enclave_switchless = cc_enclave_sgx_call_function_switchless, + .cc_malloc_shared_memory = sgx_malloc_shared_memory, + .cc_free_shared_memory = sgx_free_shared_memory, + .cc_register_shared_memory = sgx_register_shared_memory, + .cc_unregister_shared_memory = sgx_unregister_shared_memory }; struct cc_enclave_ops_desc sgx_ops_name = { diff --git a/src/host_src/sgx/sgx_shared_memory.c b/src/host_src/sgx/sgx_shared_memory.c new file mode 100644 index 0000000..b9ecf9a --- /dev/null +++ b/src/host_src/sgx/sgx_shared_memory.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 "sgx_shared_memory.h" + +#include <stdlib.h> +#include "secgear_defs.h" + +void *sgx_malloc_shared_memory(cc_enclave_t *enclave, size_t size, bool is_control_buf) +{ + CC_IGNORE(enclave); + CC_IGNORE(is_control_buf); + + return malloc(size); +} + +cc_enclave_result_t sgx_free_shared_memory(cc_enclave_t *enclave, void *ptr) +{ + CC_IGNORE(enclave); + + free(ptr); + return CC_SUCCESS; +} + +cc_enclave_result_t sgx_register_shared_memory(cc_enclave_t *enclave, void *ptr) +{ + CC_IGNORE(enclave); + CC_IGNORE(ptr); + + return CC_SUCCESS; +} + +cc_enclave_result_t sgx_unregister_shared_memory(cc_enclave_t *enclave, void *ptr) +{ + CC_IGNORE(enclave); + CC_IGNORE(ptr); + + return CC_SUCCESS; +} diff --git a/src/host_src/sgx/sgx_shared_memory.h b/src/host_src/sgx/sgx_shared_memory.h new file mode 100644 index 0000000..861cea7 --- /dev/null +++ b/src/host_src/sgx/sgx_shared_memory.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * secGear is 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 __SGX_SHARED_MEMORY_H__ +#define __SGX_SHARED_MEMORY_H__ + +#include <stdint.h> +#include <stdbool.h> +#include <stddef.h> +#include "status.h" +#include "enclave.h" + +/* + * Summary: Allocates size bytes and returns a pointer to the allocated memory. + * Parameters: + * context: enclave + * size: buffer length + * is_control_buf: whether it is a control area buffer + * Return: A pointer to the allocated memory. On error, return NULL. + */ +void *sgx_malloc_shared_memory(cc_enclave_t *context, size_t size, bool is_control_buf); + +/* + * Summary: Frees the memory space pointed to by ptr, which must have been returned by sgx_malloc_shared_memory. + * Parameters: + * context: enclave + * ptr: buffer address + * Return: NA + */ +cc_enclave_result_t sgx_free_shared_memory(cc_enclave_t *context, void *ptr); + +/* + * Summary: Register a pointer to enclave, which must have been returned by sgx_malloc_shared_memory. + * Parameters: + * enclave: enclave + * ptr: buffer address + * Return: CC_SUCCESS, success; others failed. + */ +cc_enclave_result_t sgx_register_shared_memory(cc_enclave_t *enclave, void *ptr); + +/* + * Summary: Unregister a pointer from enclave, which must have been returned by sgx_malloc_shared_memory. + * Parameters: + * enclave: enclave + * ptr: buffer address + * Return: CC_SUCCESS, success; others failed. + */ +cc_enclave_result_t sgx_unregister_shared_memory(cc_enclave_t *enclave, void *ptr); + +#endif diff --git a/tools/codegener/CMakeLists.txt b/tools/codegener/CMakeLists.txt index e52d894..9ba2039 100644 --- a/tools/codegener/CMakeLists.txt +++ b/tools/codegener/CMakeLists.txt @@ -21,9 +21,14 @@ endif() set(code codegen) ExternalProject_Add(codegen - SOURCE_DIR ${LOCAL_ROOT_PATH}/tools/codegener - CONFIGURE_COMMAND "" - BUILD_COMMAND dune build - BUILD_IN_SOURCE TRUE - INSTALL_COMMAND mv ${CMAKE_CURRENT_SOURCE_DIR}/_build/default/main.exe ${LOCAL_ROOT_PATH}/bin/${code} + SOURCE_DIR ${LOCAL_ROOT_PATH}/tools/codegener + CONFIGURE_COMMAND "" + BUILD_COMMAND dune build + BUILD_IN_SOURCE TRUE + INSTALL_COMMAND mv ${CMAKE_CURRENT_SOURCE_DIR}/_build/default/main.exe ${LOCAL_ROOT_PATH}/bin/${code} +) + +install(FILES ${LOCAL_ROOT_PATH}/bin/${code} + DESTINATION /usr/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) diff --git a/tools/codegener/Codegener.ml b/tools/codegener/Codegener.ml index c825614..66b6c01 100644 --- a/tools/codegener/Codegener.ml +++ b/tools/codegener/Codegener.ml @@ -82,9 +82,6 @@ let check_trust_funcs_method (tfs : trusted_func list) (ep : edger8r_params)= if t.tf_is_priv then failwithf "%s :Trustzone mode is not support 'private' feature" t.tf_fdecl.fname; - if t.tf_is_switchless then - failwithf "%s :Trustzone mode is not support 'switchless' feature" - t.tf_fdecl.fname; if check_is_user_check t.tf_fdecl then failwithf "%s :Trustzone mode is not support 'user_check' feature" t.tf_fdecl.fname) @@ -161,7 +158,7 @@ let check_structure (ec: enclave_content) = ) fd.plist ) (trusted_fds @ untrusted_fds) -let generate_enclave_code (ec : enclave_content) (ep : edger8r_params) = +let generate_enclave_code (ec : enclave_content) (ep : edger8r_params) = g_undir := ep.untrusted_dir; g_dir := ep.trusted_dir; let trust_funcs = ec.tfunc_decls in @@ -182,3 +179,4 @@ let generate_enclave_code (ec : enclave_content) (ep : edger8r_params) = create_untrusted_source ec ); printf "Success. \n" + diff --git a/tools/codegener/Commonfunc.ml b/tools/codegener/Commonfunc.ml index 6f3966a..0dbdd50 100644 --- a/tools/codegener/Commonfunc.ml +++ b/tools/codegener/Commonfunc.ml @@ -263,6 +263,45 @@ let set_call_user_func (fd : func_decl) = pl) ^ ");"; ] +let set_call_user_sl_func (fd : func_decl) = + let is_ptr_type (t : atype) = match t with Ptr t -> true | _ -> false in + let pl = fd.plist in + [ + (match fd.rtype with Void -> "" | _ -> (get_tystr2 fd.rtype) ^ (if (is_ptr_type fd.rtype) then "*" else "") ^ " ret = ") ^ fd.fname ^ "("; + " " ^ concat ",\n " + (List.map + (fun(ptype, decl) -> + match ptype with + | PTVal _ -> sprintf " %s" decl.identifier + | PTPtr (t, a) -> + if is_array decl then + sprintf " *(%s(*)%s)%s" (get_tystr t) (get_array_dims decl.array_dims) decl.identifier + else if params_is_foreign_array ptype then + sprintf " *(%s*)%s" (get_tystr t) decl.identifier + else if a.pa_rdonly then + sprintf " (const %s)%s" (get_tystr t) decl.identifier + else if a.pa_chkptr=false then + sprintf " &%s" decl.identifier + else sprintf " %s" decl.identifier) + pl) ^ ");"; + ] + +let set_sl_call_params (fd : func_decl) = + let pl = fd.plist in + [ + "/* get switchless function params from task buf */\n " ^ concat "\n " + (List.map + (fun(ptype, decl) -> + let var_type = get_tystr2 (get_param_atype ptype) in + let var_name = decl.identifier in + match ptype with + | PTVal _ -> + sprintf "%s %s = SL_GET_VAL_PARAM_FROM_TASK_BUF(%s);" var_type var_name var_type + | PTPtr (t, a) -> + sprintf "%s *%s = SL_GET_PTR_PARAM_FROM_TASK_BUF(%s *);" var_type var_name var_type) + pl) ^ "\n"; + ] + let set_args_size (fd : func_decl) = let deep_copy = List.filter is_deep_copy fd.plist in let argment_size = @@ -472,3 +511,5 @@ let set_out_memcpy (fd : func_decl) = else "/* There is no out_buf to out_params */" ] +let is_switchless_function (tf : trusted_func) = tf.tf_is_switchless == true +let is_not_switchless_function (tf : trusted_func) = tf.tf_is_switchless == false diff --git a/tools/codegener/Genheader.ml b/tools/codegener/Genheader.ml index e683670..9d0514c 100644 --- a/tools/codegener/Genheader.ml +++ b/tools/codegener/Genheader.ml @@ -241,15 +241,26 @@ let generate_args_header (ec: enclave_content) = in String.concat "\n" untrust_fstruct_pre in + let tfunc_decls = List.filter is_not_switchless_function ec.tfunc_decls in + let sl_tfunc_decls = List.filter is_switchless_function ec.tfunc_decls in let trust_fid_com = "/**** Trusted function IDs ****/\n" in + let sl_trust_fid_com = "\n/**** Trusted switchless function IDs ****/\n" in let untrust_fid_com = "/**** Untrusted function IDs ****/\n" in let trust_fid_body = let trust_fid_pre = List.mapi - (fun i f -> sprintf " %s = %d," (generate_function_id f.tf_fdecl) i) ec.tfunc_decls + (fun i f -> sprintf " %s = %d," (generate_function_id f.tf_fdecl) (i + 2)) tfunc_decls in String.concat "\n" trust_fid_pre in + let sl_trust_fid_body = + let sl_trust_fid_pre = + List.mapi + (fun i f -> sprintf " %s = %d," (generate_function_id f.tf_fdecl) i) sl_tfunc_decls + in + String.concat "\n" sl_trust_fid_pre + in + let sl_trust_fid_max = " fid_trusted_switchless_call_id_max = SECGEAR_ENUM_MAX\n" in let untrust_fid_body = let untrust_fid_pre = List.mapi @@ -264,6 +275,7 @@ let generate_args_header (ec: enclave_content) = " fid_trusted_call_id_max = SECGEAR_ENUM_MAX\n" in let trust_fid = "enum\n{\n" ^ trust_fid_body ^ "\n" ^ trust_fid_max ^ "};" in + let sl_trust_fid = "enum\n{\n" ^ sl_trust_fid_body ^ "\n" ^ sl_trust_fid_max ^ "};" in let untrust_fid = "enum\n{\n" ^ untrust_fid_body ^ "\n" ^ untrust_fid_max ^ "};" in [ hfile_start ^ hfile_include; @@ -272,7 +284,8 @@ let generate_args_header (ec: enclave_content) = def_types_com ^ def_types; trust_fstruct_com ^ trust_fstruct; untrust_fstruct_com ^ untrust_fstruct; - trust_fid_com ^ trust_fid; + trust_fid_com ^ trust_fid; + sl_trust_fid_com ^ sl_trust_fid; untrust_fid_com ^ untrust_fid; c_end; hfile_end; diff --git a/tools/codegener/Gentrust.ml b/tools/codegener/Gentrust.ml index b62624e..6b6fa00 100644 --- a/tools/codegener/Gentrust.ml +++ b/tools/codegener/Gentrust.ml @@ -134,7 +134,37 @@ let get_array_dims (il : int list) = else sprintf "[%d]" n) il) +let set_switchless_ecall_func (tf : trusted_func) = + let tfd = tf.tf_fdecl in + let out_task_params = if tfd.plist <> [] then " uint64_t *task_params = (uint64_t *)task_buf + 2;" else "" in + let unused_params = if tfd.plist == [] && tfd.rtype == Void then " CC_IGNORE(task_buf);" else "" in + let out_retval = + match tfd.rtype with + | Void -> "" + | _ -> " uint64_t *retval = (uint64_t *)task_buf + 1;" in + let write_back_retval = + match tfd.rtype with + | Void -> "" + | _ -> " (void)memcpy(retval, &ret, sizeof(ret));" in + [ + sprintf "\nvoid sl_ecall_%s(void *task_buf)" tfd.fname; + "{"; + out_task_params; + unused_params; + out_retval; + ""; + " " ^ concat " \n" (Commonfunc.set_sl_call_params tfd); + "\n /* call user-defined function */"; + " " ^ concat "\n" (Commonfunc.set_call_user_sl_func tfd); + "\n /* write back ret-val */"; + write_back_retval; + "}"; + ] + let set_ecall_func (tf : trusted_func) = + if tf.tf_is_switchless then + set_switchless_ecall_func tf + else let tfd = tf.tf_fdecl in let params_point = set_parameters_point tfd in let out_params = set_out_params tfd in @@ -144,11 +174,13 @@ let set_ecall_func (tf : trusted_func) = " size_t in_buf_size,"; " uint8_t* out_buf,"; " size_t out_buf_size,"; + " uint8_t* register_buf,"; " size_t* output_bytes_written)"; "{"; " cc_enclave_result_t result = CC_FAIL;"; " size_t in_buf_offset = 0;"; " size_t out_buf_offset = 0;"; + " (void)register_buf;"; ""; " /* Prepare parameters point */"; if not (params_point = ["";""]) then ( @@ -351,18 +383,36 @@ let g_caller_ca_owner = let gen_trusted(ec : enclave_content) = let trust_funcs = ec.tfunc_decls in let untrust_funcs = ec.ufunc_decls in - let ecall_func = List.flatten (List.map set_ecall_func trust_funcs) in let ocall_func = List.flatten (List.map set_ocall_func untrust_funcs) in + let ecall_func = List.flatten (List.map set_ecall_func trust_funcs) in let ecall_table = [ + "extern cc_enclave_result_t ecall_register_shared_memory(uint8_t *in_buf, size_t in_buf_size,"; + " uint8_t *out_buf, size_t out_buf_size, uint8_t *shared_buf, size_t *output_bytes_written);"; + "extern cc_enclave_result_t ecall_unregister_shared_memory(uint8_t *in_buf, size_t in_buf_size,"; + " uint8_t *out_buf, size_t out_buf_size, uint8_t *shared_buf, size_t *output_bytes_written);\n"; "cc_ecall_func_t cc_ecall_tables[] = {"; - " "^ concat ",\n " + " (cc_ecall_func_t) ecall_register_shared_memory,"; + " (cc_ecall_func_t) ecall_unregister_shared_memory,"; + " " ^ concat ",\n " (List.map (fun (tf) -> sprintf "(cc_ecall_func_t) ecall_%s" tf.tf_fdecl.fname) - trust_funcs); + (List.filter (fun tf -> not tf.tf_is_switchless) trust_funcs)); "};"; ""; - "size_t ecall_table_size = COUNT(cc_ecall_tables);"; + "size_t ecall_table_size = CC_ARRAY_LEN(cc_ecall_tables);\n"; + ] + in + let sl_ecall_table = + [ + "\n/* switchless ECALL table */"; + "sl_ecall_func_t sl_ecall_func_table[] = {"; + " " ^ concat ",\n " + (List.map + (fun (tf) -> sprintf "(sl_ecall_func_t) sl_ecall_%s" tf.tf_fdecl.fname) + (List.filter (fun tf -> tf.tf_is_switchless) trust_funcs)); + "};\n"; + "size_t sl_ecall_func_table_size = CC_ARRAY_LEN(sl_ecall_func_table);\n"; ] in [ @@ -371,7 +421,20 @@ let gen_trusted(ec : enclave_content) = ""; "#include <stdio.h>"; "#include <string.h>"; + "#include \"secgear_defs.h\""; ""; + "/*"; + " * Summary: Switchless bridge function prototype on the security side"; + " * Parameters:"; + " * task_buf: task buf, refer to sl_task_t"; + " * Return: NA"; + " */"; + "typedef void (*sl_ecall_func_t)(void *task_buf);\n"; + "extern size_t addr_host_to_enclave(size_t addr);"; + "#define SL_GET_VAL_PARAM_FROM_TASK_BUF(var_type) \\"; + " (var_type)(*(var_type *)(task_params++))"; + "#define SL_GET_PTR_PARAM_FROM_TASK_BUF(var_type) \\"; + " (var_type)addr_host_to_enclave((size_t)((var_type)(*(var_type *)(task_params++))))\n"; " /* ECALL FUNCTIONs */"; concat "\n" ecall_func; ""; @@ -382,5 +445,6 @@ let gen_trusted(ec : enclave_content) = if (List.length untrust_funcs <> 0 ) then concat "\n" ocall_func ^"\n" else "/* There is no ocall functions */\n"; concat "\n" ecall_table; + concat "\n" sl_ecall_table; ""; ] diff --git a/tools/codegener/Genuntrust.ml b/tools/codegener/Genuntrust.ml index 7171ef2..dc3010d 100644 --- a/tools/codegener/Genuntrust.ml +++ b/tools/codegener/Genuntrust.ml @@ -97,8 +97,91 @@ let set_ecall_func_arguments (fd : func_decl) = fd.plist) else "") ] - + +let set_sl_ecall_func (tf : trusted_func) = + let tfd = tf.tf_fdecl in + let init_point = set_init_pointer tfd in + let get_param_name (_, decl) = decl.identifier in + (*let is_ptr_type (ptype) = + match ptype with + | PTVal _ -> false + | PTPtr (_, a) -> true + in + let get_param_type_str (ptype, _) = if (is_ptr_type ptype) == true + then + (get_tystr (get_param_atype ptype)) ^ "*" + else + (get_tystr (get_param_atype ptype)) + in*) + let get_param_type_str (ptype, _) = (get_tystr (get_param_atype ptype)) + in + let out_retval = + match tfd.rtype with + | Void -> "NULL" + | _ -> "retval" in + let out_retval_size = + match tfd.rtype with + | Void -> "0" + | _ -> "sizeof(" ^ get_tystr tfd.rtype ^ ")" in + let num_params = if tfd.plist <> [] then "" ^ string_of_int (List.length tfd.plist) else "0" in + let params = if tfd.plist <> [] then + " void *params_buf = calloc(sizeof(uint64_t) * " ^ num_params ^ ", sizeof(char));\n" ^ + " if (params_buf == NULL) {\n" ^ + " pthread_rwlock_unlock(&enclave->rwlock);\n" ^ + " return CC_ERROR_OUT_OF_MEMORY;\n" ^ + " }\n\n" ^ + " uint64_t *params_offset = (uint64_t *)params_buf;\n" ^ + (concat "" + (List.map + (fun p -> + " (void)memcpy(params_offset++, &" ^ (get_param_name p) ^ ", sizeof(" ^ get_param_type_str p ^ "));\n") + tfd.plist)) + else + "" + in + let out_params = if tfd.plist <> [] then "params_buf" else "NULL" in + [ + ""; + concat ",\n " (set_ecall_func_arguments tfd) ^ ")"; + "{"; + " cc_enclave_result_t ret;\n"; + " if (enclave == NULL) {"; + " return CC_ERROR_BAD_PARAMETERS;"; + " }\n"; + " if (pthread_rwlock_rdlock(&enclave->rwlock)) {"; + " return CC_ERROR_BUSY;"; + " }\n"; + " if (enclave->list_ops_node == NULL ||\n enclave->list_ops_node->ops_desc == NULL ||"; + " enclave->list_ops_node->ops_desc->ops == NULL ||"; + " enclave->list_ops_node->ops_desc->ops->cc_sl_ecall_enclave == NULL) {"; + " pthread_rwlock_unlock(&enclave->rwlock);"; + " return CC_ERROR_BAD_PARAMETERS;"; + " }"; + ""; + params; + " /* Call the cc_enclave function */"; + + " sl_ecall_func_info_t func_info = {"; + " .func_id = " ^ "fid_" ^ tfd.fname ^ ","; + " .argc = " ^ num_params ^ ","; + " .args = " ^ out_params ^ ","; + " };"; + + " ret = enclave->list_ops_node->ops_desc->ops->cc_sl_ecall_enclave(enclave,"; + " " ^ out_retval ^ ","; + " " ^ out_retval_size ^ ","; + " &func_info);\n"; + + " pthread_rwlock_unlock(&enclave->rwlock);"; + (if tfd.plist <> [] then " free(params_buf);" else ""); + " return ret;"; + "}"; + ] + let set_ecall_func (tf : trusted_func) = + if tf.tf_is_switchless then + set_sl_ecall_func tf + else let tfd = tf.tf_fdecl in let init_point = set_init_pointer tfd in let arg_size = set_args_size tfd in diff --git a/tools/codegener/intel/Ast.ml b/tools/codegener/intel/Ast.ml index 69daf87..fdbc054 100644 --- a/tools/codegener/intel/Ast.ml +++ b/tools/codegener/intel/Ast.ml @@ -1,5 +1,5 @@ (* - * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/codegener/intel/CodeGen.ml b/tools/codegener/intel/CodeGen.ml index 6fb05fb..fd19278 100644 --- a/tools/codegener/intel/CodeGen.ml +++ b/tools/codegener/intel/CodeGen.ml @@ -1,5 +1,5 @@ (* - * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -57,12 +57,16 @@ type enclave_content = Ast.enclave_content = { * sgx_ecall(). *) type sgx_fn_id = SGX_ECALL | SGX_OCALL | SGX_OCALLOC | SGX_OCFREE let get_sgx_fname fn_id is_switchless = - let func_name = match fn_id with - SGX_ECALL -> "sgx_ecall" - | SGX_OCALL -> "sgx_ocall" - | SGX_OCALLOC -> "sgx_ocalloc" - | SGX_OCFREE -> "sgx_ocfree" in - sprintf "%s%s" func_name (if is_switchless then "_switchless" else "") + let switchless_str = if is_switchless then "_switchless" else "" in + match fn_id with + SGX_ECALL -> "sgx_ecall" ^ switchless_str + | SGX_OCALL -> "sgx_ocall" ^ switchless_str + | SGX_OCALLOC -> "sgx_ocalloc" + | SGX_OCFREE -> "sgx_ocfree" + +let get_secgear_ecall_fname is_switchless = + let switchless_str = if is_switchless then "_switchless" else "" in + "cc_ecall_enclave" ^ switchless_str (* Whether to prefix untrusted proxy with Enclave name *) let g_use_prefix = ref false @@ -84,6 +88,9 @@ let get_tf_fname (tf: Ast.trusted_func) = let is_priv_ecall (tf: Ast.trusted_func) = tf.Ast.tf_is_priv +let is_switchless_ecall (tf: Ast.trusted_func) = + tf.Ast.tf_is_switchless + let get_uf_fname (uf: Ast.untrusted_func) = uf.Ast.uf_fdecl.Ast.fname @@ -265,11 +272,15 @@ let get_tsource_name (file_shortnm: string) = let mk_struct_decl (fs: string) (name: string) = sprintf "typedef struct %s {\n%s} %s;\n" name fs name -(* Construct the string of union definition *) -let mk_union_decl (fs: string) (name: string) = - sprintf "typedef union %s {\n%s} %s;\n" name fs name +(* Construct the string of structure definition with #ifndef surrounded *) +let mk_struct_decl_with_macro (fs: string) (name: string) = + sprintf "#ifndef _%s\n#define _%s\ntypedef struct %s {\n%s} %s;\n#endif\n" name name name fs name + +(* Construct the string of union definition with #ifndef surrounded *) +let mk_union_decl_with_macro (fs: string) (name: string) = + sprintf "#ifndef _%s\n#define _%s\ntypedef union %s {\n%s} %s;\n#endif\n" name name name fs name -(* Generate a definition of enum *) +(* Generate a definition of enum with #ifndef surrounded *) let mk_enum_def (e: Ast.enum_def) = let gen_enum_ele_str (ele: Ast.enum_ele) = let k, v = ele in @@ -396,6 +407,12 @@ let check_structure (ec: enclave_content) = in if deep_copy then failwithf "the structure declaration \"%s\" specifies a deep copy is expected. Referenced by value in function \"%s\" detected."s fd.Ast.fname + else + if List.exists (fun (pt, _) -> + match pt with + Ast.PTVal _ -> false + | Ast.PTPtr _ -> true ) struct_def.Ast.smlist + then (eprintf "warning: the structure \"%s\" is referenced by value in function \"%s\". Part of the data may not be copied.\n"s fd.Ast.fname) else () else () | Ast.PTPtr (Ast.Ptr(Ast.Struct(s)), attr) -> @@ -406,7 +423,16 @@ let check_structure (ec: enclave_content) = failwithf "the structure declaration \"%s\" specifies a deep copy, should not be used with an `out' attribute in function \"%s\"."s fd.Ast.fname else () else () - | _ -> () + | a -> let (found, name) = is_foreign_a_structure a + in + if found then + let (_, deep_copy) = get_struct_def name + in + if deep_copy then + failwithf "`%s' in function `%s' is a structure and it specifies a deep copy. Use `struct %s' instead." name fd.Ast.fname name + else + (eprintf "warning: `%s' in function `%s' is a structure. Use `struct %s' instead.\n" name fd.Ast.fname name) + else () ) fd.Ast.plist ) (trusted_fds @ untrusted_fds) @@ -449,8 +475,8 @@ let gen_comp_def (st: Ast.composite_type) = acc ^ mk_member_decl (Ast.get_param_atype pt) declr) "" mlist in match st with - Ast.StructDef s -> mk_struct_decl (gen_struct_member_list s.Ast.smlist) s.Ast.sname - | Ast.UnionDef u -> mk_union_decl (gen_union_member_list u.Ast.umlist) u.Ast.uname + Ast.StructDef s -> mk_struct_decl_with_macro (gen_struct_member_list s.Ast.smlist) s.Ast.sname + | Ast.UnionDef u -> mk_union_decl_with_macro (gen_union_member_list u.Ast.umlist) u.Ast.uname | Ast.EnumDef e -> mk_enum_def e (* Generate a list of '#include' *) @@ -503,9 +529,10 @@ let gen_parm_retval (rt: Ast.atype) = struct { void *ecall_addr; uint8_t is_priv; + uint8_t is_switchless; } ecall_table [nr_ecall]; } g_ecall_table = { - 2, { {sgx_foo, 1}, {sgx_bar, 0} } + 2, { {sgx_foo, 1, 0}, {sgx_bar, 0, 1} } }; *) let gen_ecall_table (tfs: Ast.trusted_func list) = @@ -515,16 +542,18 @@ let gen_ecall_table (tfs: Ast.trusted_func list) = let priv_bits = tf_list_to_priv_list tfs in let tbridge_names = List.map (fun (fd: Ast.func_decl) -> mk_tbridge_name fd.Ast.fname) trusted_fds in + let priv_switchless_bits = List.map (fun (tf: Ast.trusted_func ) -> + (is_priv_ecall tf, is_switchless_ecall tf) ) tfs in let ecall_table = let bool_to_int b = if b then 1 else 0 in let inner_table = - List.fold_left2 (fun acc s b -> - sprintf "%s\t\t{(void*)(uintptr_t)%s, %d},\n" acc s (bool_to_int b)) "" tbridge_names priv_bits + List.fold_left2 (fun acc s (b1, b2) -> + sprintf "%s\t\t{(void*)(uintptr_t)%s, %d, %d},\n" acc s (bool_to_int b1) (bool_to_int b2)) "" tbridge_names priv_switchless_bits in "\t{\n" ^ inner_table ^ "\t}\n" in sprintf "SGX_EXTERNC const struct {\n\ \tsize_t nr_ecall;\n\ -\tstruct {void* ecall_addr; uint8_t is_priv;} ecall_table[%d];\n\ +\tstruct {void* ecall_addr; uint8_t is_priv; uint8_t is_switchless;} ecall_table[%d];\n\ } %s = {\n\ \t%d,\n\ %s};\n" ecall_table_size @@ -625,7 +654,21 @@ let gen_tproxy_proto (fd: Ast.func_decl) = * with the `prefix' parameter. * *) -let gen_uproxy_com_proto (fd: Ast.func_decl) (prefix: string) = +let gen_uproxy_com_proto_sgx_inner_switchless (fd: Ast.func_decl) (prefix: string) = + let retval_parm_str = gen_parm_retval fd.Ast.rtype in + + let eid_parm_str = + if fd.Ast.rtype = Ast.Void then sprintf "(sgx_enclave_id_t %s" eid_name + else sprintf "(sgx_enclave_id_t %s, " eid_name in + let parm_list = + List.fold_left (fun acc pd -> acc ^ ", " ^ gen_parm_str pd) + retval_parm_str fd.Ast.plist in + let fname = + if !g_use_prefix then sprintf "%s_%s" prefix fd.Ast.fname + else fd.Ast.fname + in "sgx_status_t " ^ fname ^ eid_parm_str ^ parm_list ^ ")" + +let gen_uproxy_com_proto_common (fd: Ast.func_decl) (prefix: string) = let retval_parm_str = gen_parm_retval fd.Ast.rtype in let eid_parm_str = @@ -639,6 +682,14 @@ let gen_uproxy_com_proto (fd: Ast.func_decl) (prefix: string) = else fd.Ast.fname in "cc_enclave_result_t " ^ fname ^ eid_parm_str ^ parm_list ^ ")" +let gen_uproxy_com_proto (fd: Ast.func_decl) (prefix: string) = + if fd.fname = "sl_init_switchless" || fd.fname = "sl_run_switchless_tworker" then ( + gen_uproxy_com_proto_sgx_inner_switchless fd prefix + ) + else ( + gen_uproxy_com_proto_common fd prefix + ) + let get_ret_tystr (fd: Ast.func_decl) = Ast.get_tystr fd.Ast.rtype let get_plist_str (fd: Ast.func_decl) = if fd.Ast.plist = [] then "void" @@ -856,8 +907,47 @@ let fill_ms_field (isptr: bool) (pd: Ast.pdecl) = let tystr = Ast.get_tystr (Ast.Ptr (Ast.get_param_atype pt)) in sprintf "%s%s%s = (%s)%s;" ms_struct_val accessor ms_member_name tystr param_name +(* Generate untrusted proxy code for sgx inner switchless trusted function. *) +let gen_func_uproxy_sgx_inner_switchless (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = + let fd = tf.Ast.tf_fdecl in + let func_open = + gen_uproxy_com_proto fd ec.enclave_name ^ + "\n{\n\tsgx_status_t status;\n" + in + let func_close = "\treturn status;\n}\n" in + let ocall_table_name = mk_ocall_table_name ec.enclave_name in + let ms_struct_name = mk_ms_struct_name fd.Ast.fname in + let declare_ms_expr = sprintf "%s %s;" ms_struct_name ms_struct_val in + let ocall_table_ptr = + sprintf "&%s" ocall_table_name in + let sgx_ecall_fn = get_sgx_fname SGX_ECALL tf.Ast.tf_is_switchless in + + (* Normal case - do ECALL with marshaling structure*) + let ecall_with_ms = sprintf "status = %s(%s, %d, %s, &%s);" + sgx_ecall_fn eid_name idx ocall_table_ptr ms_struct_val in + + (* Rare case - the trusted function doesn't have parameter nor return value. + * In this situation, no marshaling structure is required - passing in NULL. + *) + let ecall_null = sprintf "status = %s(%s, %d, %s, NULL);" + sgx_ecall_fn eid_name idx ocall_table_ptr + in + let update_retval = sprintf "if (status == SGX_SUCCESS && %s) *%s = %s.%s;" + retval_name retval_name ms_struct_val ms_retval_name in + let func_body = ref [] in + if is_naked_func fd then + sprintf "%s\t%s\n%s" func_open ecall_null func_close + else + begin + func_body := declare_ms_expr :: !func_body; + List.iter (fun pd -> func_body := fill_ms_field false pd :: !func_body) fd.Ast.plist; + func_body := ecall_with_ms :: !func_body; + if fd.Ast.rtype <> Ast.Void then func_body := update_retval :: !func_body; + List.fold_left (fun acc s -> acc ^ "\t" ^ s ^ "\n") func_open (List.rev !func_body) ^ func_close + end + (* Generate untrusted proxy code for a given trusted function. *) -let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = +let gen_func_uproxy_common (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = let fd = tf.Ast.tf_fdecl in let func_open = gen_uproxy_com_proto fd ec.enclave_name ^ @@ -869,7 +959,7 @@ let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = let declare_ms_expr = sprintf "%s %s;" ms_struct_name ms_struct_val in let ocall_table_ptr = sprintf "&%s" ocall_table_name in - let sgx_ecall_fn = get_sgx_fname SGX_ECALL tf.Ast.tf_is_switchless in + let cc_ecall_fn = get_secgear_ecall_fname tf.Ast.tf_is_switchless in (* Normal case - do ECALL with marshaling structure*) let ecall_with_ms = sprintf "if(!enclave) \n\ @@ -878,9 +968,9 @@ let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = \t\treturn CC_ERROR_BUSY; if (!enclave->list_ops_node || !enclave->list_ops_node->ops_desc ||\n\ \t\t!enclave->list_ops_node->ops_desc->ops || \n\ - \t\t!enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave)\n\ + \t\t!enclave->list_ops_node->ops_desc->ops->%s)\n\ \t\treturn CC_ERROR_BAD_PARAMETERS; - result = enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave( \n\ + result = enclave->list_ops_node->ops_desc->ops->%s( \n\ \t\tenclave,\n\ \t\t%d,\n\ \t\tNULL,\n\ @@ -889,7 +979,7 @@ let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = \t\t0,\n\ \t\t&%s,\n\ \t\t%s); - pthread_rwlock_unlock(&enclave->rwlock);\n" idx ms_struct_val ocall_table_ptr in + pthread_rwlock_unlock(&enclave->rwlock);\n" cc_ecall_fn cc_ecall_fn idx ms_struct_val ocall_table_ptr in (* Rare case - the trusted function doesn't have parameter nor return value. * In this situation, no marshaling structure is required - passing in NULL. @@ -900,9 +990,9 @@ let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = \t\treturn CC_ERROR_BUSY; if(!enclave || !enclave->list_ops_node || !enclave->list_ops_node->ops_desc ||\n\ \t\t!enclave->list_ops_node->ops_desc->ops || \n\ - \t\t!enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave)\n\ + \t\t!enclave->list_ops_node->ops_desc->ops->%s)\n\ \t\treturn CC_ERROR_BAD_PARAMETERS; - result = enclave->list_ops_node->ops_desc->ops->cc_ecall_enclave( \n\ + result = enclave->list_ops_node->ops_desc->ops->%s( \n\ \t\tenclave,\n\ \t\t%d,\n\ \t\tNULL,\n\ @@ -911,7 +1001,7 @@ let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = \t\t0,\n\ \t\tNULL,\n\ \t\t%s); - pthread_rwlock_unlock(&enclave->rwlock);\n" idx ocall_table_ptr + pthread_rwlock_unlock(&enclave->rwlock);\n" cc_ecall_fn cc_ecall_fn idx ocall_table_ptr in let update_retval = sprintf "if (result == CC_SUCCESS && %s) *%s = %s.%s;" retval_name retval_name ms_struct_val ms_retval_name in @@ -927,6 +1017,14 @@ let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = List.fold_left (fun acc s -> acc ^ "\t" ^ s ^ "\n") func_open (List.rev !func_body) ^ func_close end +let gen_func_uproxy (tf: Ast.trusted_func) (idx: int) (ec: enclave_content) = + if tf.Ast.tf_fdecl.fname = "sl_init_switchless" || tf.Ast.tf_fdecl.fname = "sl_run_switchless_tworker" then ( + gen_func_uproxy_sgx_inner_switchless tf idx ec + ) + else ( + gen_func_uproxy_common tf idx ec + ) + (* Generate an expression to check the pointers. *) let mk_check_ptr (name: string) (lenvar: string) = let checker = "CHECK_UNIQUE_POINTER" @@ -1761,6 +1859,49 @@ let tproxy_fill_ms_field (pd: Ast.pdecl) (is_ocall_switchless: bool) = "\t}"; ] in + let copy_out = + let deep_copy_out = + let pre struct_type name = + let code_template =[ + sprintf "for (i = 0; i < %s / sizeof(struct %s); i++){" (mk_len_var name) struct_type; + sprintf "\t\tif (memcpy_s(&__local_%s, sizeof(__local_%s), %s + i, sizeof(struct %s))) {" name name name struct_type; + sprintf "\t\t\t%s();" sgx_ocfree_fn; + "\t\t\treturn SGX_ERROR_UNEXPECTED;"; + "\t\t}"; + ] + in + List.fold_left (fun acc s -> acc ^ "\t" ^ s ^ "\n") "" code_template + in + let clear_member(param_direction: Ast.ptr_direction) (struct_type: string) (struct_name: string) (ty: Ast.atype) (attr: Ast.ptr_attr) (declr: Ast.declarator) = + let member_name = declr.Ast.identifier in + sprintf "\t\t\t__local_%s.%s = NULL;\n" struct_name member_name + in + let post = + let code_template =[ + sprintf "\tif (memcpy_s((void *)((size_t)__tmp + sizeof(__local_%s) * i), sizeof(__local_%s), &__local_%s, sizeof(__local_%s))) {" name name name name; + sprintf "\t\t%s();" sgx_ocfree_fn; + "\t\treturn SGX_ERROR_UNEXPECTED;"; + "\t}"; + "}"; + sprintf "memset(&__local_%s, 0, sizeof(__local_%s));" name name; + ] + in + List.fold_left (fun acc s -> acc ^ "\t\t" ^ s ^ "\n") "" code_template + in + invoke_if_struct ty attr.Ast.pa_direction name pre clear_member post + in + let non_deep_copy_out = + let code_template = + [ + sprintf "if (memcpy_s(__tmp, ocalloc_size, %s, %s)) {" name len_var; + sprintf "\t\t%s();" sgx_ocfree_fn; + "\t\treturn SGX_ERROR_UNEXPECTED;"; + "\t}"; + ] + in List.fold_left (fun acc s -> acc ^ "\t" ^ s ^ "\n") "" code_template + in + if deep_copy_out = "" then non_deep_copy_out else deep_copy_out + in match attr.Ast.pa_direction with Ast.PtrOut -> let code_template = @@ -1790,7 +1931,7 @@ let tproxy_fill_ms_field (pd: Ast.pdecl) (is_ocall_switchless: bool) = sprintf "\t\t%s();" sgx_ocfree_fn; "\t\treturn SGX_ERROR_UNEXPECTED;"; "\t}"; - sprintf "\t__tmp = (void *)((size_t)__tmp + %s);" len_var; + sprintf "%s\t\t__tmp = (void *)((size_t)__tmp + %s);"copy_out len_var; sprintf "\tocalloc_size -= %s;" len_var; "} else {"; sprintf "\t%s = NULL;" parm_accessor; @@ -1808,7 +1949,7 @@ let tproxy_fill_ms_field (pd: Ast.pdecl) (is_ocall_switchless: bool) = sprintf "\t\t%s();" sgx_ocfree_fn; "\t\treturn SGX_ERROR_UNEXPECTED;"; "\t}"; - sprintf "\t__tmp = (void *)((size_t)__tmp + %s);" len_var; + sprintf "%s\t\t__tmp = (void *)((size_t)__tmp + %s);"copy_out len_var; sprintf "\tocalloc_size -= %s;" len_var; "} else {"; sprintf "\t%s = NULL;" parm_accessor; @@ -1884,7 +2025,12 @@ let gen_tproxy_local_vars (plist: Ast.pdecl list) = let in_len_ptr_name = mk_len_var2 struct_name member_name in sprintf "\tsize_t %s = 0;\n" in_len_ptr_name in - invoke_if_struct ty attr.Ast.pa_direction name (fun _ name -> if attr.Ast.pa_direction = Ast.PtrInOut then sprintf"\tvoid* __tmp_member_%s = NULL;\n" name else "") gen_in_ptr_struct_var "" + invoke_if_struct ty attr.Ast.pa_direction name (fun struct_type name -> + sprintf "\tstruct %s __local_%s;\n" struct_type name ^ + if attr.Ast.pa_direction = Ast.PtrInOut then + sprintf"\tvoid* __tmp_member_%s = NULL;\n" name else + "" + ) gen_in_ptr_struct_var "" in (do_gen_local_var ^ in_ptr_struct_var, if in_ptr_struct_var <> "" then true else false) in @@ -2581,8 +2727,9 @@ let gen_enclave_code (e: Ast.enclave) (ep: edger8r_params) = check_structure ec; check_allow_list ec; (if not ep.header_only then check_priv_funcs ec); - if Plugin.available() && ep.trustzone_mode then + if Plugin.available() && not ep.sgx_mode then ( Plugin.gen_edge_routines ec ep + ) else ( (if ep.gen_untrusted then (gen_untrusted_header ec; if not ep.header_only then gen_untrusted_source ec)); (if ep.gen_trusted then (gen_trusted_header ec; if not ep.header_only then gen_trusted_source ec)) diff --git a/tools/codegener/intel/Edger8r.ml b/tools/codegener/intel/Edger8r.ml index 80a04a8..35b92f2 100644 --- a/tools/codegener/intel/Edger8r.ml +++ b/tools/codegener/intel/Edger8r.ml @@ -1,5 +1,5 @@ (* - * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/codegener/intel/Lexer.mll b/tools/codegener/intel/Lexer.mll index 8bd55e3..f5fdb2e 100644 --- a/tools/codegener/intel/Lexer.mll +++ b/tools/codegener/intel/Lexer.mll @@ -1,5 +1,5 @@ (* - * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/codegener/intel/Makefile b/tools/codegener/intel/Makefile index ad0ad0e..527db5a 100644 --- a/tools/codegener/intel/Makefile +++ b/tools/codegener/intel/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 2011-2019 Intel Corporation. All rights reserved. +# Copyright (C) 2011-2021 Intel Corporation. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions diff --git a/tools/codegener/intel/Parser.mly b/tools/codegener/intel/Parser.mly index e9121dd..e8eb30b 100644 --- a/tools/codegener/intel/Parser.mly +++ b/tools/codegener/intel/Parser.mly @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/codegener/intel/Plugin.ml b/tools/codegener/intel/Plugin.ml index 373f8f8..ba1fb4b 100644 --- a/tools/codegener/intel/Plugin.ml +++ b/tools/codegener/intel/Plugin.ml @@ -1,5 +1,5 @@ (* - * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/codegener/intel/Preprocessor.ml b/tools/codegener/intel/Preprocessor.ml index 6894d7f..4e856a0 100644 --- a/tools/codegener/intel/Preprocessor.ml +++ b/tools/codegener/intel/Preprocessor.ml @@ -1,5 +1,5 @@ (* - * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,10 +51,6 @@ let read_process (command : string) : Unix.process_status * string = (*Return None if gcc not found, caller should handle it*) let processor_macro ( full_path : string) : string option= - None - (* Preprocessor is disabled because: - * 1. It causes edger8r to print incorrect line numbers in error messages. - * 2. It does not work in windows. let gcc_path = snd (read_process "which gcc") in if not (String.contains gcc_path '/' ) then (eprintf "warning: preprocessor is not found\n"; None) @@ -70,4 +66,4 @@ let processor_macro ( full_path : string) : string option= else Some(snd output) | _ -> failwithf "Preprocessor stopped by signal\n" - *) + diff --git a/tools/codegener/intel/SimpleStack.ml b/tools/codegener/intel/SimpleStack.ml index a2c03b0..5b9e6c3 100644 --- a/tools/codegener/intel/SimpleStack.ml +++ b/tools/codegener/intel/SimpleStack.ml @@ -1,5 +1,5 @@ (* - * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/codegener/intel/Util.ml b/tools/codegener/intel/Util.ml index 9dd22bd..f7957a9 100644 --- a/tools/codegener/intel/Util.ml +++ b/tools/codegener/intel/Util.ml @@ -1,5 +1,5 @@ (* - * Copyright (C) 2011-2019 Intel Corporation. All rights reserved. + * Copyright (C) 2011-2021 Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -87,6 +87,7 @@ type edger8r_params = { untrusted_dir : string; (* Directory to save untrusted code *) trusted_dir : string; (* Directory to save trusted code *) trustzone_mode: bool; (* Generate code for trustzone mode *) + penlai_mode : bool; (* Generate code for penglai mode *) sgx_mode : bool; (* Generate code for sgx mode *) } @@ -105,13 +106,14 @@ let path_separator : char = | _ -> ':' (* "Unix" or "Cygwin" *) (* Parse the command line and return a record of `edger8r_params'. *) -let parse_cmdline (progname: string) (cmdargs: string list) = +let rec parse_cmdline (progname: string) (cmdargs: string list) = let use_pref = ref false in let hd_only = ref false in let untrusted= ref false in let trusted = ref false in let sgx = ref false in let trustzone= ref false in + let penglai = ref false in let u_dir = ref "." in let t_dir = ref "." in let files = ref [] in @@ -127,6 +129,7 @@ let parse_cmdline (progname: string) (cmdargs: string list) = | "--trusted" -> trusted := true; local_parser ops | "--sgx" -> sgx := true; local_parser ops | "--trustzone" -> trustzone := true; local_parser ops + | "--penglai" -> penglai := true; local_parser ops | "--untrusted-dir" -> (match ops with [] -> usage progname @@ -153,13 +156,14 @@ let parse_cmdline (progname: string) (cmdargs: string list) = untrusted_dir = !u_dir; trusted_dir = !t_dir; sgx_mode = !sgx; trustzone_mode = !trustzone; + penlai_mode = !penglai; } in if opt.input_files = [] then usage progname; - if !sgx && !trustzone + if (!sgx && !trustzone) || (!sgx && !penglai) || (!penglai && !trustzone) then (eprintf "Error:Only one mode use in conmmand.\n"; exit 1) - else if !sgx || !trustzone then + else if !sgx || !trustzone || !penglai then (if !untrusted || !trusted (* User specified '--untrusted' or '--trusted' *) then { opt with gen_trusted = !trusted; gen_untrusted = !untrusted } else opt) -- 2.27.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2