secGear 开发指南

这里给出使用 secGear 开发一个 C 语言程序 helloworld 的例子,方便用户理解使用 secGear 开发应用程序。

目录结构说明

使用 secGear 开发的应用程序,遵循统一的目录结构如下:

  1. ├── helloworld
  2. ├── CMakeLists.txt
  3. ├── enclave
  4. ├── CMakeLists.txt
  5. ├── Enclave.config.xml
  6. ├── Enclave.lds
  7. ├── hello.c
  8. ├── manifest.txt.in
  9. └── rsa_public_key_cloud.pem
  10. ├── helloworld.edl
  11. └── host
  12. ├── CMakeLists.txt
  13. └── main.c

快速入门

  1. 创建程序工作目录 helloworld,并在 helloworld 目录下新建 enclave 和 host

  2. 编写 EDL(Enclave Definition Language)文件

    为了确保开发代码的一致性,secGear 提供了 secgear_urts.h 和 secgear_tstdc.edl 用于屏蔽底层 Intel SGX 和 ARM iTrustee 之间的差异。因此,使用到 C 语言函数库时,EDL 文件默认需要导入 secgear_urts.h 和 secgear_tstdc.edl。helloworld.edl 文件参考如下:

    1. enclave {
    2. include "secgear_urts.h"
    3. from "secgear_tstdc.edl" import *;
    4. trusted {
    5. public int get_string([out, size=32]char *buf);
    6. };
    7. };

    说明:EDL 语法详细信息请参见 Intel SGX 开发指南中对应内容。

  3. 编写顶层文件 CMakeLists.txt

    编写顶层文件 CMakeLists.txt,置于 helloworld 工作目录下,用于配置编译时的处理器架构、所需的 EDL 文件等信息。

    其中,EDL_FILE 是 EDL 文件,需用户指定,例子中为 helloworld.edl。DPATH 是安全侧加载动态库,配置如例子中所示。

    1. cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
    2. project(HelloWorld C)
    3. set(CMAKE_C_STANDARD 99)
    4. set(CURRENT_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
    5. set(EDL_FILE helloworld.edl)
    6. set(LOCAL_ROOT_PATH "$ENV{CC_SDK}")
    7. set(SECGEAR_INSTALL_PATH /lib64/)
    8. if(CC_GP)
    9. set(CODETYPE trustzone)
    10. set(CODEGEN codegen_arm64)
    11. execute_process(COMMAND uuidgen -r OUTPUT_VARIABLE UUID)
    12. string(REPLACE "\n" "" UUID ${UUID})
    13. add_definitions(-DPATH="/data/${UUID}.sec")
    14. endif()
    15. if(CC_SGX)
    16. set(CODETYPE sgx)
    17. set(CODEGEN codegen_x86_64)
    18. add_definitions(-DPATH="${CMAKE_CURRENT_BINARY_DIR}/enclave/enclave.signed.so")
    19. endif()
    20. add_subdirectory(${CURRENT_ROOT_PATH}/enclave)
    21. add_subdirectory(${CURRENT_ROOT_PATH}/host)
  1. 编写非安全侧代码和 CMakeLists.txt

    4.1 编写 main.c

    编写非安全侧 main.c,置于 host目录。enclave.h 为 secGear 头文件,helloworld_u.h 为辅助代码生成工具生成的头文件。使用 cc_enclave_create 创建安全区 enclave 上下文,cc_enclave_destroy 销毁安全区上下文。 get_string 为 EDL 文件中定义 trusted 的安全侧函数,注意这里与 EDL 中定义的 get_string 有差别,多出两个参数 context 为安全区上下文,retval 为 EDL 中get_string 的返回值。 res 为 get_string 调用成功标志。

    1. #include <stdio.h>
    2. #include "enclave.h"
    3. #include "helloworld_u.h"
    4. #define BUF_LEN 32
    5. int main()
    6. {
    7. int retval = 0;
    8. char *path = PATH;
    9. char buf[BUF_LEN];
    10. cc_enclave_t *context = NULL;
    11. cc_enclave_result_t res;
    12. res = cc_enclave_create(path, AUTO_ENCLAVE_TYPE, 0, SECGEAR_DEBUG_FLAG, NULL, 0, &context);
    13. ...
    14. res = get_string(context, &retval, buf);
    15. if (res != CC_SUCCESS || retval != (int)CC_SUCCESS) {
    16. printf("Ecall enclave error\n");
    17. } else {
    18. printf("%s\n", buf);
    19. }
    20. if (context != NULL) {
    21. res = cc_enclave_destroy(context);
    22. ...
    23. }
    24. return res;
    25. }

    4.2 编写非安全侧 CMakeLists.txt

    1. # 设置编译环境变量
    2. #set auto code prefix
    3. set(PREFIX helloworld)
    4. #set host exec name
    5. set(OUTPUT secgear_helloworld)
    6. #set host src code
    7. set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/main.c)
    8. # 使用代码生成工具生成辅助代码。CODEGEN 和 CODETYPE 变量也在顶层 CMakeLists.txt 中定义。--search-path 用于指定 helloword.edl 中导入依赖的其他 EDL 文件路径
    9. #set auto code
    10. if(CC_GP)
    11. set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h)
    12. add_custom_command(OUTPUT ${AUTO_FILES}
    13. DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
    14. COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp)
    15. endif()
    16. if(CC_SGX)
    17. set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_u.c)
    18. add_custom_command(OUTPUT ${AUTO_FILES}
    19. DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
    20. COMMAND ${CODEGEN} --${CODETYPE} --untrusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include)
    21. endif()
    22. # 设置编译选项和链接选项
    23. set(CMAKE_C_FLAGS "-fstack-protector-all -W -Wall -Werror -Wextra -Werror=array-bounds -D_FORTIFY_SOURCE=2 -O2 -ftrapv -fPIE")
    24. set(CMAKE_EXE_LINKER_FLAGS "-Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack")
    25. # 编译链接引用目录
    26. if(CC_GP)
    27. if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
    28. link_directories(${SECGEAR_INSTALL_PATH})
    29. endif()
    30. add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES})
    31. target_include_directories(${OUTPUT} PRIVATE
    32. /usr/include/secGear/host_inc
    33. /usr/include/secGear/host_inc/gp
    34. ${CMAKE_CURRENT_BINARY_DIR})
    35. if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
    36. target_link_directories(${OUTPUT} PRIVATE ${SECGEAR_INSTALL_PATH})
    37. endif()
    38. target_link_libraries(${OUTPUT} secgear)
    39. endif()
    40. if(CC_SGX)
    41. if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
    42. link_directories(${SECGEAR_INSTALL_PATH} ${SGXSDK}/lib64)
    43. endif()
    44. set(SGX_MODE HW)
    45. if(${SGX_MODE} STREQUAL HW)
    46. set(Urts_Library_Name sgx_urts)
    47. else()
    48. set(Urts_Library_Name sgx_urts_sim)
    49. endif()
    50. add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES} ${LOCAL_ROOT_PATH}/src/host_src/sgx/sgx_log.c)
    51. target_include_directories(${OUTPUT} PRIVATE
    52. /usr/include/secGear/host_inc
    53. /usr/include/secGear/host_inc/sgx
    54. ${CMAKE_CURRENT_BINARY_DIR})
    55. if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
    56. target_link_directories(${OUTPUT} PRIVATE ${SECGEAR_INSTALL_PATH} ${SGXSDK}/lib64)
    57. endif()
    58. target_link_libraries(${OUTPUT} secgear ${Urts_Library_Name})
    59. endif()
    60. # 指定二进制安装目录
    61. set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE)
    62. if(CC_GP)
    63. install(TARGETS ${OUTPUT}
    64. RUNTIME
    65. DESTINATION /vendor/bin/
    66. PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ)
    67. endif()
    68. if(CC_SGX)
    69. install(TARGETS ${OUTPUT}
    70. RUNTIME
    71. DESTINATION ${CMAKE_BINARY_DIR}/bin/
    72. PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ)
    73. endif()
  1. 编写安全侧代码、CMakeLists.txt 和配置文件,放在 enclave 目录

    5.1 编写安全侧代码 hello.c

    编写安全侧代码 hello.c,置于 enclave 目录。其中,helloworld_t.h 为辅助代码生成工具,通过 EDL 文件生成的安全侧头文件。

    1. #include <stdio.h>
    2. #include <string.h>
    3. #include "helloworld_t.h"
    4. #define TA_HELLO_WORLD "secGear hello world!"
    5. #define BUF_MAX 32
    6. int get_string(char *buf)
    7. {
    8. strncpy(buf, TA_HELLO_WORLD, strlen(TA_HELLO_WORLD) + 1);
    9. return 0;
    10. }

    5.2 编写安全侧 CMakeLists.txt

    1. #set auto code prefix
    2. set(PREFIX helloworld)
    3. #set sign key
    4. set(PEM Enclave_private.pem)
    5. #set sign tool
    6. set(SIGN_TOOL ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh)
    7. #set enclave src code
    8. set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/hello.c)
    9. #set log level
    10. set(PRINT_LEVEL 3)
    11. add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL})
    12. # WHITE_LIS_X 设置 itrustee 白名单,只有这些路径的主机二进制文件可以调用此安全映像,并且最多可以配置 8 个列表路径。WHITE_LIST_OWNER 设置用户,此用户将应用于所有白名单路径。DEVICEPEM 公钥由itrustee 使用,并用于通过动态生成的 aes 密钥加密安全侧的安全动态库。
    13. if(CC_GP)
    14. #set signed output
    15. set(OUTPUT ${UUID}.sec)
    16. #set itrustee device key
    17. set(DEVICEPEM ${CMAKE_CURRENT_SOURCE_DIR}/rsa_public_key_cloud.pem)
    18. #set whilelist. default: /vendor/bin/teec_hello
    19. set(WHITE_LIST_0 /vendor/bin/helloworld)
    20. set(WHITE_LIST_OWNER root)
    21. set(WHITE_LIST_1 /vendor/bin/secgear_helloworld)
    22. set(WHITELIST WHITE_LIST_0 WHITE_LIST_1)
    23. set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h)
    24. add_custom_command(OUTPUT ${AUTO_FILES}
    25. DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
    26. COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/gp)
    27. endif()
    28. # SGX 安全侧动态库签名
    29. if(CC_SGX)
    30. set(OUTPUT enclave.signed.so)
    31. set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.c)
    32. add_custom_command(OUTPUT ${AUTO_FILES}
    33. DEPENDS ${CURRENT_ROOT_PATH}/${EDL_FILE}
    34. COMMAND ${CODEGEN} --${CODETYPE} --trusted ${CURRENT_ROOT_PATH}/${EDL_FILE} --search-path ${LOCAL_ROOT_PATH}/inc/host_inc/sgx --search-path ${SGXSDK}/include)
    35. endif()
    36. # 设置编译选项
    37. set(COMMON_C_FLAGS "-W -Wall -Werror -fno-short-enums -fno-omit-frame-pointer -fstack-protector \
    38. -Wstack-protector --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs \
    39. -fno-peephole -fno-peephole2 -Wno-main -Wno-error=unused-parameter \
    40. -Wno-error=unused-but-set-variable -Wno-error=format-truncation=")
    41. set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles")
    42. # itrustee 需生成 manifest.txt。指定 itrustee 编译选项和头文件、链接文件的搜索路径
    43. if(CC_GP)
    44. configure_file("${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt.in" "${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt")
    45. set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -march=armv8-a ")
    46. set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s -fPIC")
    47. set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s")
    48. set(ITRUSTEE_TEEDIR ${iTrusteeSDK}/)
    49. set(ITRUSTEE_LIBC ${iTrusteeSDK}/thirdparty/open_source/musl/libc)
    50. if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
    51. link_directories(${CMAKE_BINARY_DIR}/lib/)
    52. endif()
    53. add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES})
    54. target_include_directories( ${PREFIX} PRIVATE
    55. ${CMAKE_CURRENT_BINARY_DIR}
    56. ${LOCAL_ROOT_PATH}/inc/host_inc
    57. ${LOCAL_ROOT_PATH}/inc/host_inc/gp
    58. ${LOCAL_ROOT_PATH}/inc/enclave_inc
    59. ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp
    60. ${ITRUSTEE_TEEDIR}/include/TA
    61. ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext
    62. ${ITRUSTEE_LIBC}/arch/aarch64
    63. ${ITRUSTEE_LIBC}/
    64. ${ITRUSTEE_LIBC}/arch/arm/bits
    65. ${ITRUSTEE_LIBC}/arch/generic
    66. ${ITRUSTEE_LIBC}/arch/arm
    67. ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee)
    68. if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
    69. target_link_directories(${PREFIX} PRIVATE
    70. ${CMAKE_BINARY_DIR}/lib/)
    71. endif()
    72. foreach(WHITE_LIST ${WHITELIST})
    73. add_definitions(-D${WHITE_LIST}="${${WHITE_LIST}}")
    74. endforeach(WHITE_LIST)
    75. add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}")
    76. target_link_libraries(${PREFIX} -lsecgear_tee)
    77. add_custom_command(TARGET ${PREFIX}
    78. POST_BUILD
    79. COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -m ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt
    80. -e ${DEVICEPEM} -o ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT})
    81. install(FILES ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT}
    82. DESTINATION /data
    83. PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
    84. endif()
    85. if(CC_SGX)
    86. set(SGX_DIR ${SGXSDK})
    87. set(CMAKE_C_FLAGS "${COMMON_C_FLAGS} -m64 -fvisibility=hidden")
    88. set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s")
    89. set(LINK_LIBRARY_PATH ${SGX_DIR}/lib64)
    90. if(CC_SIM)
    91. set(Trts_Library_Name sgx_trts_sim)
    92. set(Service_Library_Name sgx_tservice_sim)
    93. else()
    94. set(Trts_Library_Name sgx_trts)
    95. set(Service_Library_Name sgx_tservice)
    96. endif()
    97. set(Crypto_Library_Name sgx_tcrypto)
    98. set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-z,defs -Wl,-pie -Bstatic -Bsymbolic -eenclave_entry \
    99. -Wl,--export-dynamic -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/Enclave.lds")
    100. if(${CMAKE_VERSION} VERSION_LESS "3.13.0")
    101. link_directories(${LINK_LIBRARY_PATH})
    102. endif()
    103. add_library(${PREFIX} SHARED ${SOURCE_FILES} ${AUTO_FILES})
    104. target_include_directories(${PREFIX} PRIVATE
    105. ${CMAKE_CURRENT_BINARY_DIR}
    106. ${SGX_DIR}/include/tlibc
    107. ${SGX_DIR}/include/libcxx
    108. ${SGX_DIR}/include
    109. ${LOCAL_ROOT_PATH}/inc/host_inc
    110. ${LOCAL_ROOT_PATH}/inc/host_inc/sgx)
    111. if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
    112. target_link_directories(${PREFIX} PRIVATE
    113. ${LINK_LIBRARY_PATH})
    114. endif()
    115. target_link_libraries(${PREFIX} -Wl,--whole-archive ${Trts_Library_Name} -Wl,--no-whole-archive
    116. -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l${Crypto_Library_Name} -l${Service_Library_Name} -Wl,--end-group)
    117. add_custom_command(TARGET ${PREFIX}
    118. POST_BUILD
    119. COMMAND umask 0177
    120. COMMAND openssl genrsa -3 -out ${PEM} 3072
    121. 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)
    122. endif()
    123. set_target_properties(${PREFIX} PROPERTIES SKIP_BUILD_RPATH TRUE)
  1. 编写配置文件

    针对使用 Intel SGX 的 x86_64 处理器架构,请编写 Enclave.config.xml 和 Enclave.lds 文件,置于安全侧 enclave 目录。文件的具体配置格式请参见 SGX 官方文档。

    Enclave.config.xml 参考:

    ```c 0 0 0x40000 0x100000 10

    1
  1. <DisableDebug>0</DisableDebug>
  2. <MiscSelect>0</MiscSelect>
  3. <MiscMask>0xFFFFFFFF</MiscMask>

  1. Enclave.lds 参考:
  2. ```c
  3. enclave.so
  4. {
  5. global:
  6. g_global_data_sim;
  7. g_global_data;
  8. enclave_entry;
  9. g_peak_heap_used;
  10. local:
  11. *;
  12. };

将设备公钥文件 rsa_public_key_cloud.pem 复制到 enclave 目录。此处的设备公钥用于使用临时生成的 aes 密钥对安全区动态库进行加密。

说明:rsa_public_key_cloud.pem 文件下载路径:https://gitee.com/openeuler/secGear/blob/master/examples/helloworld/enclave/rsa_public_key_cloud.pem

  1. 编译程序

    SGX 版本编译命令如下,编译后将生成可执行程序 secgear_helloworld

    1. cmake -DCMAKE_BUILD_TYPE=debug -DCC_SGX=ON -DSGXSDK="PATH" ./ && make
  1. 执行程序

    1. $ ./secgear_helloworld
    2. Create secgear enclave
    3. secgear hello world!