SecGear则是面向计算产业的机密计算安全应用开发套件。旨在方便开发者在不同的硬件设备上提供统一开发框架。目前secGear支持intel SGX硬件,Trustzone itrustee,以及RISC-V 蓬莱TEE.
开发目录 .../secGear/examples/test/
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硬件。
保存文件名为test.edl
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:用于定义非安全侧使用安全侧动态库的绝对路径
#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参数)
#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()
设置使用代码辅助生成工具根据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()
在iTrustee硬件环境上,设置头文件的搜索路径及编译生成非安全侧二进制文件。
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()
在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()
设置secGear链接库,当指定模拟模式CC_SIM时链接libsecgearsim.so,否则链接libsecgear.so。 在iTrustee硬件环境上需指定安装固定的安全白名单。
#include <stdio.h>
#include <string.h>
#include "test_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;
}
test_t.h:该头文件为自动生成代码工具codegen通过edl文件生成的头文件。该头文件命名为edl文件名加"_t"。
#set auto code prefix
set(PREFIX test)
#set sign key
set(PEM Enclave_private.pem)
设置enclave签名私钥
#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})
设置签名工具已经安全侧打印日志level
if(CC_GP)
#set signed output
set(OUTPUT ${UUID}.sec)
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)
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()
WHITE_LIST_x:为设置iTrustee的二进制白名单,只有这里定义的白名单,在非安全侧的二进制才可以调用安全侧的动态库。上限为8个。 WHITE_LIST_OWNER:为设置运行二进制的用户,只有该用户才可以调用安全侧动态库。 AUTO_FILES:由edl文件生成的安全侧二进制文件
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()
设置自动生成代码及签名动态库。
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")
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(${SECGEAR_INSTALL_PATH})
endif()
add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES})
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)
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}")
target_link_libraries(${PREFIX} -lsecgear_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})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT}
DESTINATION /data
PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
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()
在SGX硬件环境上,指定一些与sgx相关的编译选项、链接选项。链接动态库时有所不同,因为itrustee是一个具有更多功能的安全操作系统。提供如muslibc和openssl。在编译和链接itrustee时不用链接一些基本库,但是sgx没有OS概念。所以要在安全侧调用这些基本库的接口都要以静态的形式在sgxsdk中给出。例如"sgx_trts"
有关更多详细信息,请参阅sgx示例的Makefile。最后用enclave配置文件完成签名,稍后将进行介绍。secGear尚不支持远程身份验证。
编写与sgx enclave相关的配置文件中Enclave.config.xml文件及enclave.lds文件与官方sgx配置相同。详情参阅官方开发文档。
编写itrustee enclave相关配置文件 mainfest.txt.in:其中gpd.ta.appID 为动态生成uuid。其他配置参见itrustee开发文档。
进入开发目录: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硬件环境)
非安全侧日志记录:
非安全侧是开发与普通开发环境一样,可使用通用打印日志接口。
安全侧日志记录:
由于各架构安全能力不同的限制,为了像非安全侧一样开发使用日志打印功能,因为我们提供了PrintInfo接口将安全端日志记录到syslog系统中。 相关配置文件为 conf/logrotate.d/secgear和conf/rsyslog.d/secgear.conf文件,安装时将安装在系统目录/etc/中。
注意:在itrustee上,需要include secgear_log.h头文件,但是sgx不需要,sgx通过ocall功能实现的,所以相关代码生成在辅助代码中。 当文件安装成功后需要运行"systemctl restart rsyslog"使日志功能生效。
日志等级:
PRINT_ERROR 0
PRINT_WARNING 1
PRINT_STRACE 2
PRINT_DEBUG 3
目前ocall仅在sgx平台支持,itrustee尚不支持。
接口定义在secgear_dataseal.h、secgear_random.h中。 注意:由于itrustee派生密钥的功能仍然不完善,因此目前还没有与密封相关的接口在itrustee平台上支持。
secGear引入EDL(Enclave Description Language)和中间代码辅助生成工具codegener。edl与intel sgx定义兼容。