Projects
Eulaceura:Factory
secGear
_service:obs_scm:0029-some-adaptations-for-trus...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:0029-some-adaptations-for-trustzone.patch of Package secGear
From 45cf3b4bb86d5dc9d149f5e6056e9b2cb27eff63 Mon Sep 17 00:00:00 2001 From: zgzxx <zhangguangzhi3@huawei.com> Date: Tue, 18 May 2021 14:27:31 +0800 Subject: [PATCH 12/14] some adaptations for trustzone --- CMakeLists.txt | 11 +- README.en.md | 2 +- README.md | 2 +- docs/sign_tool.md | 19 +- examples/CMakeLists.txt | 28 ++ examples/helloworld/CMakeLists.txt | 3 +- examples/helloworld/enclave/CMakeLists.txt | 16 +- examples/helloworld/enclave/config_cloud.ini | 49 ++ examples/helloworld/enclave/manifest.txt | 7 + examples/helloworld/enclave/manifest.txt.in | 8 - examples/helloworld/host/CMakeLists.txt | 7 +- examples/helloworld/host/main.c | 1 + examples/seal_data/CMakeLists.txt | 4 +- examples/seal_data/enclave/CMakeLists.txt | 19 +- examples/seal_data/enclave/config_cloud.ini | 49 ++ examples/seal_data/enclave/manifest.txt | 7 + examples/seal_data/enclave/manifest.txt.in | 8 - examples/seal_data/host/CMakeLists.txt | 1 + .../gp/itrustee/itrustee_seal_data.c | 3 +- src/host_src/gp/CMakeLists.txt | 4 +- src/host_src/gp/gp_enclave.c | 4 +- .../{ => cloud}/rsa_public_key_cloud.pem | 0 tools/sign_tool/generate_signature.py | 56 +++ tools/sign_tool/manifest.py | 170 ++++--- tools/sign_tool/sign_tool.py | 471 ------------------ tools/sign_tool/sign_tool.sh | 141 ++---- tools/sign_tool/signtool_v3.py | 428 ++++++++++++++++ 27 files changed, 802 insertions(+), 716 deletions(-) create mode 100644 examples/CMakeLists.txt create mode 100644 examples/helloworld/enclave/config_cloud.ini create mode 100644 examples/helloworld/enclave/manifest.txt delete mode 100644 examples/helloworld/enclave/manifest.txt.in create mode 100644 examples/seal_data/enclave/config_cloud.ini create mode 100644 examples/seal_data/enclave/manifest.txt delete mode 100644 examples/seal_data/enclave/manifest.txt.in rename tools/sign_tool/{ => cloud}/rsa_public_key_cloud.pem (100%) create mode 100644 tools/sign_tool/generate_signature.py delete mode 100644 tools/sign_tool/sign_tool.py create mode 100644 tools/sign_tool/signtool_v3.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 3886316..b373328 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,17 +49,8 @@ add_subdirectory(src) execute_process(COMMAND mkdir ${LOCAL_ROOT_PATH}/bin) -if(CC_GP) - add_subdirectory(${LOCAL_ROOT_PATH}/examples/seal_data) - add_subdirectory(${LOCAL_ROOT_PATH}/examples/helloworld) -endif() +add_subdirectory(examples) -if(CC_SGX) - add_subdirectory(${LOCAL_ROOT_PATH}/examples/helloworld) - add_subdirectory(${LOCAL_ROOT_PATH}/examples/seal_data) -# add_subdirectory(${LOCAL_ROOT_PATH}/examples/tls_enclave) - add_subdirectory(${LOCAL_ROOT_PATH}/examples/lrt) -endif() install(FILES ${LOCAL_ROOT_PATH}/conf/logrotate.d/secgear DESTINATION /etc/logrotate.d/) diff --git a/README.en.md b/README.en.md index aa8c4a8..8aaa1b0 100644 --- a/README.en.md +++ b/README.en.md @@ -335,7 +335,7 @@ so -nostdinc -nodefaultlibs -nostdlib -nodefaultlibs compile link options was in 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 + 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} diff --git a/README.md b/README.md index a90450b..b95dcc9 100644 --- a/README.md +++ b/README.md @@ -315,7 +315,7 @@ AUTO_FILES:由edl文件生成的安全侧二进制文件 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 + 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} diff --git a/docs/sign_tool.md b/docs/sign_tool.md index ccaa2e6..399e4c5 100644 --- a/docs/sign_tool.md +++ b/docs/sign_tool.md @@ -13,38 +13,37 @@ The tool supports the following two modes: For example: - `$ ./sign_tool.sh –d sign –x trustzone –i test.enclave -c manifest.txt –o signed.enclave ` + `$ ./sign_tool.sh –d sign –x trustzone –i test.enclave -c manifest.txt -m config_cloud.ini –o signed.enclave ` - two-step method, it is used when the signature needs to be obtained from the signing organization or the private key is stored on another secure platform. For example: (1) generate the digest value. - `$ ./sign_tool.sh –d digest –x trustzone –i input -c manifest.txt –o digest.data ` + `$ ./sign_tool.sh –d digest –x trustzone –i input -c manifest.txt -m config_cloud.ini –o digest.data ` For trustzone, temporary files KeyInfo.enc, rawData.enc, and rawDataHash.bin are generated in the current directory. And for sgx, a temporary file signdata is generated in the current directory. The temporary file is required when generating the signed enclave in step 3 and is deleted after the signed enclave is generated. (2) send the digest.data to the signing organization or platform and get the signature. (3) use the signature to generate the signed enclave. - `$ ./sign_tool.sh –d sign –x trustzone –i input -c manifest.txt –p pub.pem –s signature –o signed.enclave ` + `$ ./sign_tool.sh –d sign –x trustzone –i input -c manifest.txt -m config_cloud.ini –s signature –o signed.enclave ` ## sign_tool.sh parameter ``` - -a <parameter> API_LEVEL, indicates trustzone GP API version, defalut is 1. -c <file> basic config file. -d <parameter> sign tool command, sign/digest. The sign command is used to generate a signed enclave. The digest command is used to generate a digest value. - -f <parameter> OTRP_FLAG, indicates whether the OTRP standard protocol is supported, default is 0. -i <file> enclave to be signed. - -k <file> private key required for single-step method, required when trustzone TA_TYPE is 2 or sgx. - -m <file> additional config for trustzone when TA_TYPE is 2. - -o <file> output parameters, the sign command outputs sigend enclave, the digest command outputs digest value. + -k <file> private key required for single-step method + -m <file> additional config_cloud.ini for trustzone. + -o <file> output parameters, the sign command outputs sigend enclave, the digest command outputs + digest value. -p <file> signing server public key certificate, required for two-step method. - -s <file> the signed digest value required for two-step method, this parameter is empty to indicate single-step method. - -t <parameter> trustzone TA_TYPE, default is 1. + -s <file> the signed digest value required for two-step method, this parameter is empty to indicate + single-step method. -x <parameter> enclave type, sgx or trustzone. -h printf help message. ``` diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 0000000..cfd0171 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,28 @@ +add_custom_target(copy ALL + COMMAND mkdir -p ${CMAKE_BINARY_DIR}/inc/secGear + COMMAND cp ${LOCAL_ROOT_PATH}/inc/host_inc/*.h ${CMAKE_BINARY_DIR}/inc/secGear/ + COMMAND cp ${LOCAL_ROOT_PATH}/inc/enclave_inc/*.h ${CMAKE_BINARY_DIR}/inc/secGear/) + +if(CC_GP) + add_custom_command(TARGET copy + POST_BUILD + COMMAND cp ${LOCAL_ROOT_PATH}/inc/host_inc/gp/*.edl ${CMAKE_BINARY_DIR}/inc/secGear/ + COMMAND cp ${LOCAL_ROOT_PATH}/inc/host_inc/gp/*.h ${CMAKE_BINARY_DIR}/inc/secGear/ + COMMAND cp ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/*.h ${CMAKE_BINARY_DIR}/inc/secGear/ + COMMAND cp ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee/*.h ${CMAKE_BINARY_DIR}/inc/secGear/) + add_subdirectory(seal_data) + add_subdirectory(helloworld) +endif() + +if(CC_SGX) + add_custom_command(TARGET copy + POST_BUILD + COMMAND cp ${LOCAL_ROOT_PATH}/inc/host_inc/sgx/*.h ${CMAKE_BINARY_DIR}/inc/secGear/ + COMMAND cp ${LOCAL_ROOT_PATH}/inc/host_inc/sgx/*.edl ${CMAKE_BINARY_DIR}/inc/secGear/ + COMMAND cp ${LOCAL_ROOT_PATH}/inc/enclave_inc/sgx/*.h ${CMAKE_BINARY_DIR}/inc/secGear/) + add_subdirectory(seal_data) + add_subdirectory(helloworld) + #add_subdirectory(tls_enclave) + #add_subdirectory(lrt) +endif() + diff --git a/examples/helloworld/CMakeLists.txt b/examples/helloworld/CMakeLists.txt index 5da2a6b..843a573 100644 --- a/examples/helloworld/CMakeLists.txt +++ b/examples/helloworld/CMakeLists.txt @@ -20,8 +20,7 @@ set(CODEGEN codegen) if(CC_GP) set(CODETYPE trustzone) - execute_process(COMMAND uuidgen -r OUTPUT_VARIABLE UUID) - string(REPLACE "\n" "" UUID ${UUID}) + set(UUID f68fd704-6eb1-4d14-b218-722850eb3ef0) add_definitions(-DPATH="/data/${UUID}.sec") endif() diff --git a/examples/helloworld/enclave/CMakeLists.txt b/examples/helloworld/enclave/CMakeLists.txt index 0aefdae..f7967ef 100644 --- a/examples/helloworld/enclave/CMakeLists.txt +++ b/examples/helloworld/enclave/CMakeLists.txt @@ -55,7 +55,6 @@ set(COMMON_C_FLAGS "-W -Wall -Werror -fno-short-enums -fno-omit-frame-pointer set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-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") @@ -72,6 +71,7 @@ if(CC_GP) target_include_directories( ${PREFIX} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${LOCAL_ROOT_PATH}/debug/inc ${LOCAL_ROOT_PATH}/inc/host_inc ${LOCAL_ROOT_PATH}/inc/host_inc/gp ${LOCAL_ROOT_PATH}/inc/enclave_inc @@ -97,14 +97,14 @@ if(CC_GP) target_link_libraries(${PREFIX} -lsecgear_tee) - 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 - -o ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT}) + #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) + # 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() diff --git a/examples/helloworld/enclave/config_cloud.ini b/examples/helloworld/enclave/config_cloud.ini new file mode 100644 index 0000000..552f59c --- /dev/null +++ b/examples/helloworld/enclave/config_cloud.ini @@ -0,0 +1,49 @@ +[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/helloworld/enclave/manifest.txt b/examples/helloworld/enclave/manifest.txt new file mode 100644 index 0000000..d78354e --- /dev/null +++ b/examples/helloworld/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: false +gpd.ta.instanceKeepAlive: false +gpd.ta.dataSize: 819200 +gpd.ta.stackSize: 40960 diff --git a/examples/helloworld/enclave/manifest.txt.in b/examples/helloworld/enclave/manifest.txt.in deleted file mode 100644 index 7b8ecf5..0000000 --- a/examples/helloworld/enclave/manifest.txt.in +++ /dev/null @@ -1,8 +0,0 @@ -gpd.ta.appID: @UUID@ -gpd.ta.service_name: test0108 -gpd.ta.singleInstance: true -gpd.ta.multiSession: false -gpd.ta.multiCommand: false -gpd.ta.instanceKeepAlive: false -gpd.ta.dataSize: 16384 -gpd.ta.stackSize: 20480 diff --git a/examples/helloworld/host/CMakeLists.txt b/examples/helloworld/host/CMakeLists.txt index 1c96ffd..60173a9 100644 --- a/examples/helloworld/host/CMakeLists.txt +++ b/examples/helloworld/host/CMakeLists.txt @@ -38,9 +38,10 @@ if(CC_GP) 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/gp + target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/debug/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}) diff --git a/examples/helloworld/host/main.c b/examples/helloworld/host/main.c index 51993ce..7213a5e 100644 --- a/examples/helloworld/host/main.c +++ b/examples/helloworld/host/main.c @@ -15,6 +15,7 @@ #include <linux/limits.h> #include "enclave.h" #include "helloworld_u.h" +#include "string.h" #define BUF_LEN 32 diff --git a/examples/seal_data/CMakeLists.txt b/examples/seal_data/CMakeLists.txt index 3577301..dce8b81 100644 --- a/examples/seal_data/CMakeLists.txt +++ b/examples/seal_data/CMakeLists.txt @@ -21,9 +21,7 @@ set(CODEGEN codegen) if(CC_GP) set(CODETYPE trustzone) - execute_process(COMMAND uuidgen -r - OUTPUT_VARIABLE UUID) - string(REPLACE "\n" "" UUID ${UUID}) + set(UUID 9cb38838-2766-42be-8b7b-0d184a996066) add_definitions(-DPATH="/data/${UUID}.sec") endif() diff --git a/examples/seal_data/enclave/CMakeLists.txt b/examples/seal_data/enclave/CMakeLists.txt index 0ddcbd5..b24e498 100644 --- a/examples/seal_data/enclave/CMakeLists.txt +++ b/examples/seal_data/enclave/CMakeLists.txt @@ -52,7 +52,6 @@ set(COMMON_C_FLAGS "-W -Wall -Werror -fno-short-enums -fno-omit-frame-pointer set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-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") set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s -fPIC") @@ -67,6 +66,7 @@ if(CC_GP) target_include_directories( ${PREFIX} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ${LOCAL_ROOT_PATH}/debug/inc ${LOCAL_ROOT_PATH}/inc/host_inc ${LOCAL_ROOT_PATH}/inc/host_inc/gp ${LOCAL_ROOT_PATH}/inc/enclave_inc @@ -91,15 +91,14 @@ if(CC_GP) endforeach(WHITE_LIST) target_link_libraries(${PREFIX} -lsecgear_tee) - - add_custom_command(TARGET ${PREFIX} - POST_BUILD - COMMAND bash ${SIGN_TOOL} -d sign -x trustzone -a 2 -i ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/lib${PREFIX}.so -c ${CMAKE_CURRENT_SOURCE_DIR}/manifest.txt - -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) + # 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() diff --git a/examples/seal_data/enclave/config_cloud.ini b/examples/seal_data/enclave/config_cloud.ini new file mode 100644 index 0000000..f0c0e39 --- /dev/null +++ b/examples/seal_data/enclave/config_cloud.ini @@ -0,0 +1,49 @@ +[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/seal_data/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/seal_data/enclave/signed_config/config diff --git a/examples/seal_data/enclave/manifest.txt b/examples/seal_data/enclave/manifest.txt new file mode 100644 index 0000000..e845fd7 --- /dev/null +++ b/examples/seal_data/enclave/manifest.txt @@ -0,0 +1,7 @@ +gpd.ta.appID: 9cb38838-2766-42be-8b7b-0d184a996066 +gpd.ta.service_name: secstorage-demo +gpd.ta.singleInstance: true +gpd.ta.multiSession: false +gpd.ta.instanceKeepAlive: False +gpd.ta.dataSize: 819200 +gpd.ta.stackSize: 40960 diff --git a/examples/seal_data/enclave/manifest.txt.in b/examples/seal_data/enclave/manifest.txt.in deleted file mode 100644 index 749815a..0000000 --- a/examples/seal_data/enclave/manifest.txt.in +++ /dev/null @@ -1,8 +0,0 @@ -gpd.ta.appID: @UUID@ -gpd.ta.service_name: seal_data -gpd.ta.singleInstance: true -gpd.ta.multiSession: false -gpd.ta.multiCommand: false -gpd.ta.instanceKeepAlive: false -gpd.ta.dataSize: 4038400 -gpd.ta.stackSize: 6048000 diff --git a/examples/seal_data/host/CMakeLists.txt b/examples/seal_data/host/CMakeLists.txt index 75b33f7..691cd07 100644 --- a/examples/seal_data/host/CMakeLists.txt +++ b/examples/seal_data/host/CMakeLists.txt @@ -40,6 +40,7 @@ if(CC_GP) endif() add_executable(${OUTPUT} ${SOURCE_FILE} ${AUTO_FILES}) target_include_directories(${OUTPUT} PRIVATE + ${LOCAL_ROOT_PATH}/debug/inc ${LOCAL_ROOT_PATH}/inc/host_inc ${LOCAL_ROOT_PATH}/inc/host_inc/gp ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/enclave_src/gp/itrustee/itrustee_seal_data.c b/src/enclave_src/gp/itrustee/itrustee_seal_data.c index 5b1676a..cf13bd9 100644 --- a/src/enclave_src/gp/itrustee/itrustee_seal_data.c +++ b/src/enclave_src/gp/itrustee/itrustee_seal_data.c @@ -221,12 +221,11 @@ TEE_Result itrustee_unseal_data(void *sealed_data, uint8_t *decrypted_data, uint SLogError("malloc key_buf failed\n"); return TEE_ERROR_OUT_OF_MEMORY; } - result = TEE_EXT_DeriveTARootKey(salt, strlen(salt), key_buf, key_len); + result = TEE_EXT_DeriveTARootKey(salt, SEAL_KEY_SALT_LEN, key_buf, key_len); if (result != TEE_SUCCESS) { SLogError("DeriveTARootKey failed"); goto done; } - *decrypted_data_len = tmp_sealed_data->encrypted_data_len; *mac_data_len = tmp_sealed_data->aad_len; result = aes_seal_unseal_data(key_buf, key_len, (uint8_t *)&(tmp_sealed_data->nonce), SEAL_DATA_NONCE_LEN, diff --git a/src/host_src/gp/CMakeLists.txt b/src/host_src/gp/CMakeLists.txt index 37635ec..ca6d87f 100644 --- a/src/host_src/gp/CMakeLists.txt +++ b/src/host_src/gp/CMakeLists.txt @@ -11,8 +11,6 @@ set(gp_engine gp_0) # to do itrustee sdk Open Source -set(itrustee_lib ) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib/gp) if(${CMAKE_VERSION} VERSION_LESS "3.13.0") @@ -33,7 +31,7 @@ endif() set_target_properties(${gp_engine} PROPERTIES SKIP_BUILD_RPATH TRUE) #link iTrustee teec lib -target_link_libraries(${gp_engine} ${itrustee_lib} secgear pthread) +target_link_libraries(${gp_engine} secgear pthread teec_adaptor) install(TARGETS ${gp_engine} LIBRARY diff --git a/src/host_src/gp/gp_enclave.c b/src/host_src/gp/gp_enclave.c index b185958..86ea941 100644 --- a/src/host_src/gp/gp_enclave.c +++ b/src/host_src/gp/gp_enclave.c @@ -25,7 +25,7 @@ #define OCALL_AGENT_REGISTER_SUCCESS 0 #define OCALL_AGENT_REGISTER_FAIL 1 - +#define SECGEAR_OCALL 0 #define MAX_LEN 4096 static pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER; @@ -535,7 +535,7 @@ cc_enclave_result_t cc_enclave_call_function( /* for ocall thread */ ires = pthread_mutex_lock(&g_mtx_flag); SECGEAR_CHECK_MUTEX_RES(ires); - if (!(g_list_ops.pthread_flag)) { + if (g_list_ops.pthread_flag || SECGEAR_OCALL) { param.agent_id = *(uint32_t *)ms; param.num = ((ocall_enclave_table_t *)ocall_table)->num; param.ocalls = ((ocall_enclave_table_t *)ocall_table)->ocalls; diff --git a/tools/sign_tool/rsa_public_key_cloud.pem b/tools/sign_tool/cloud/rsa_public_key_cloud.pem similarity index 100% rename from tools/sign_tool/rsa_public_key_cloud.pem rename to tools/sign_tool/cloud/rsa_public_key_cloud.pem diff --git a/tools/sign_tool/generate_signature.py b/tools/sign_tool/generate_signature.py new file mode 100644 index 0000000..b3264ba --- /dev/null +++ b/tools/sign_tool/generate_signature.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# coding:utf-8 +#---------------------------------------------------------------------------- +# Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. +# iTrustee licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan +# PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. +# Description: tools for generating a trusted application load image +# Author: Li mingjuan +# Create: 2020-10-27 +#---------------------------------------------------------------------------- + +import struct +import os +import hashlib +import subprocess + +HASH256 = 0 +HASH512 = 1 + +def gen_hash(hash_type, in_file_path, out_file_path): + in_file_size = os.path.getsize(in_file_path) + # Initialize a SHA256 object from the Python hash library + if int(hash_type) == HASH256: + hash_op = hashlib.sha256() + elif int(hash_type) == HASH512: + hash_op = hashlib.sha512() + # Set the input buffer and return the output digest + with open(in_file_path, 'rb') as in_file: + hash_op.update(in_file.read(in_file_size)) + + #-----hash file used for ras sign--- + with open(out_file_path, 'wb') as hash_fp: + # fixed hash prefix value + hash_fp.write(struct.pack('B'*19, 0x30, 0x31, 0x30, 0x0d, 0x06, \ + 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, \ + 0x05, 0x00, 0x04, 0x20)) + hash_fp.write(hash_op.digest()) + return + +def gen_ta_signature(cfg, hash_file_path, out_file_path): + cmd = "openssl rsautl -sign -inkey {} -in {} -out {}".\ + format(cfg.sign_key, hash_file_path, out_file_path) + try: + subprocess.check_output(cmd.split(), shell=False) + except Exception: + print("sign operation failed") + raise RuntimeError + return + diff --git a/tools/sign_tool/manifest.py b/tools/sign_tool/manifest.py index 4de8407..9cc2360 100644 --- a/tools/sign_tool/manifest.py +++ b/tools/sign_tool/manifest.py @@ -1,10 +1,20 @@ #!/usr/bin/env python # coding:utf-8 #---------------------------------------------------------------------------- -# Copyright @ Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. -# tools for generating a trusted application load image +# Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved. +# iTrustee licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan +# PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. +# Description: tools for generating a trusted application load image +# Author: Li mingjuan +# Create: 2018-02-20 #---------------------------------------------------------------------------- - import string import struct import uuid @@ -14,31 +24,32 @@ PRODUCT_TA_IMAGE = 1 PRODUCT_DYN_LIB = 2 PRODUCT_SERVICE_IMAGE = 3 -class TEE_UUID: + +class PackUuid: # Structure object to align and package the TEE_UUID - s = struct.Struct('IHH8b') + data = struct.Struct('IHH8b') def __init__(self, data): - unpacked_data = (TEE_UUID.s).unpack(str.encode(data)) + unpacked_data = (PackUuid.data).unpack(str.encode(data)) self.unpacked_data = unpacked_data - self.timeLow = unpacked_data[0] - self.timeMid = unpacked_data[1] - self.timeHiAndVersion = unpacked_data[2] - self.clockSeqAndNode = unpacked_data[3] + self.time_low = unpacked_data[0] + self.time_mid = unpacked_data[1] + self.time_hi_version = unpacked_data[2] + self.clock_seq_node = unpacked_data[3] - def printValues(self): + def print_values(self): print("ATTRIBUTE / VALUE") for attr, value in self.__dict__.items(): print(attr, value) - def getPackedData(self): - values = [self.timeLow, - self.timeMid, - self.timeHiAndVersion, - self.clockSeqAndNode, + def get_pack_data(self): + values = [self.time_low, + self.time_mid, + self.time_hi_version, + self.clock_seq_node, ] - return (TEE_UUID.s).pack(*values) + return (PackUuid.data).pack(*values) #---------------------------------------------------------------------------- @@ -47,10 +58,10 @@ class TEE_UUID: class Manifest: # Structure object to align and package the Manifest - s = struct.Struct('I' * 6) + data = struct.Struct('I' * 6) def __init__(self, data): - unpacked_data = (Manifest.s).unpack(str.encode(data)) + unpacked_data = (Manifest.data).unpack(str.encode(data)) self.unpacked_data = unpacked_data self.single_instance = unpacked_data[0] self.multi_session = unpacked_data[1] @@ -59,12 +70,12 @@ class Manifest: self.stack_size = unpacked_data[4] self.instancekeepalive = unpacked_data[5] - def printValues(self): + def print_values(self): print("ATTRIBUTE / VALUE") for attr, value in self.__dict__.items(): print(attr, value) - def getPackedData(self): + def get_pack_data(self): values = [self.single_instance, self.multi_session, self.multi_command, @@ -73,21 +84,22 @@ class Manifest: self.instancekeepalive, ] - return (Manifest.s).pack(*values) + return (Manifest.data).pack(*values) + #---------------------------------------------------------------------------- # verify property name in manifest file #---------------------------------------------------------------------------- -def verify_property_name(strLine): +def verify_property_name(str_line): print('verify property name') alphas = string.ascii_letters + string.digits cont = "".join([alphas, '-', '_', '.']) - if len(strLine) > 1: - if strLine[0] not in alphas: + if len(str_line) > 1: + if str_line[0] not in alphas: print('invalid first letter in property name') return False else: - for otherchar in strLine[1:]: + for otherchar in str_line[1:]: if otherchar not in cont: print('invalid char in property name') return False @@ -97,35 +109,37 @@ def verify_property_name(strLine): return True + #---------------------------------------------------------------------------- # verify property value in manifest file #---------------------------------------------------------------------------- -def verify_property_value(strLine): +def verify_property_value(str_line): print('verify property value') - filt_letter = chr(0) + chr(10) +chr(13) - for thechar in strLine: + filt_letter = chr(0) + chr(10) + chr(13) + for thechar in str_line: if thechar in filt_letter: print('invalid letter in prop value') return False return True + #---------------------------------------------------------------------------- # remove tabs and space in property value #---------------------------------------------------------------------------- -def trailing_space_tabs(strLine): +def trailing_space_tabs(str_line): print('trailing space tabs in value head and trail') - space_tabs = chr(9) + chr(32) +chr(160) - space_tabs_newlines = space_tabs + chr(10) +chr(13) + space_tabs = chr(9) + chr(32) + chr(160) + space_tabs_newlines = space_tabs + chr(10) + chr(13) print('tab: {}'.format(space_tabs)) - print('str in: {}'.format(strLine)) + print('str in: {}'.format(str_line)) index = 0 - for thechar in strLine: + for thechar in str_line: if thechar in space_tabs: index += 1 else: break - headvalue = strLine[index:] + headvalue = str_line[index:] strlen = len(headvalue) @@ -137,21 +151,20 @@ def trailing_space_tabs(strLine): else: break - #print 'str len: '+str(strlen) - strRet = headvalue[0:strlen+1] + chr(10) - print('str ret: {}'.format(strRet)) + str_ret = headvalue[0:strlen+1] + chr(10) + print('str ret: {}'.format(str_ret)) + + return str_ret - return strRet #---------------------------------------------------------------------------- # verify manifest file, parse manifest file, generate a new manfiest file #---------------------------------------------------------------------------- -def parserManifest(manifest, manifestDataPath, mani_ext): +def parser_manifest(manifest, manifest_data_path, mani_ext): print('verify manifest') - targetType = PRODUCT_TA_IMAGE + target_type = PRODUCT_TA_IMAGE - uuid_val_flag = 1 - uuid_val = TEE_UUID('\0' * 16) + uuid_val = PackUuid('\0' * 16) #manifest default manifest_val = Manifest('\0'*24) @@ -166,30 +179,29 @@ def parserManifest(manifest, manifestDataPath, mani_ext): service_name = 'external_service' with open(manifest, 'r') as mani_fp, open(mani_ext, 'wb') as mani_ext_fp: - for eachLine in mani_fp: - print(eachLine) - if eachLine.startswith("#") or not len(eachLine.strip()): + for each_line in mani_fp: + print(each_line) + if each_line.startswith("#") or not len(each_line.strip()): continue - index = eachLine.find(':', 1, len(eachLine)) - #print 'index name : value is ' + str(index) + index = each_line.find(':', 1, len(each_line)) - prop_name = eachLine[0:index] #no ':' - prop_name_t = eachLine[0:index+1] #with ':' - prop_value_t = eachLine[index+1:] + prop_name = each_line[0:index] + prop_name_t = each_line[0:index+1] + prop_value_t = each_line[index+1:] print('name is: {}; value is: {}'.format(prop_name, prop_value_t)) prop_value = trailing_space_tabs(prop_value_t) prop_len = len(prop_value) - prop_value_v = prop_value[0:prop_len-1]# mv last letter + prop_value_v = prop_value[0:prop_len-1] print('prop value_v: {}'.format(prop_value_v)) if verify_property_name(prop_name) is False: print('manifest format invalid, please check it') - return (False, 0, 0, 0) + return (False, 0) if verify_property_value(prop_value_v) is False: print('manifest format invalid, please check it') - return (False, 0, 0, 0) + return (False, 0) # name:value to lowcase, and parse manifest prop_name_low = prop_name.lower() @@ -197,58 +209,54 @@ def parserManifest(manifest, manifestDataPath, mani_ext): if 'gpd.ta.appid' == prop_name_low: print("compare name is srv id") uuid_val = uuid.UUID(prop_value_v) - uuid_val_flag = 0 print('uuid str {}'.format(uuid_val)) print('val fields {}'.format(uuid_val.fields)) elif 'gpd.ta.singleinstance' == prop_name_low: prop_value_low = prop_value_v.lower() if 'true' == prop_value_low: - manifest_val.single_instance = 1; + manifest_val.single_instance = 1 elif 'false' == prop_value_low: - manifest_val.single_instance = 0; + manifest_val.single_instance = 0 else: print('single_instance value error!') elif 'gpd.ta.multisession' == prop_name_low: prop_value_low = prop_value_v.lower() if 'true' == prop_value_low: - manifest_val.multi_session = 1; + manifest_val.multi_session = 1 elif 'false' == prop_value_low: - manifest_val.multi_session = 0; + manifest_val.multi_session = 0 else: print('multi_session value error!') elif 'gpd.ta.multicommand' == prop_name_low: prop_value_low = prop_value_v.lower() if 'true' == prop_value_low: - manifest_val.multi_command = 1; + manifest_val.multi_command = 1 elif 'false' == prop_value_low: - manifest_val.multi_command = 0; + manifest_val.multi_command = 0 else: print('multi_command value error!') elif 'gpd.ta.instancekeepalive' == prop_name_low: prop_value_low = prop_value_v.lower() if 'true' == prop_value_low: - manifest_val.instancekeepalive = 1; + manifest_val.instancekeepalive = 1 elif 'false' == prop_value_low: - manifest_val.instancekeepalive = 0; + manifest_val.instancekeepalive = 0 else: print('instancekeepalive value error!') elif 'gpd.ta.datasize' == prop_name_low: - #manifest_val.heap_size = prop_value_v.atoi() manifest_val.heap_size = int(prop_value_v) print('b') elif 'gpd.ta.stacksize' == prop_name_low: - #manifest_val.stack_size = prop_value_v.atoi() manifest_val.stack_size = int(prop_value_v) print('b') elif 'gpd.ta.service_name' == prop_name_low: - #manifest_val.stack_size = prop_value_v.atoi() service_name = prop_value_v print('b') @@ -260,11 +268,11 @@ def parserManifest(manifest, manifestDataPath, mani_ext): if 'gpd.ta.is_tee_service' == prop_name_low: prop_value_low = prop_value_v.lower() if 'true' == prop_value_low: - targetType = PRODUCT_SERVICE_IMAGE + target_type = PRODUCT_SERVICE_IMAGE elif 'gpd.ta.is_lib' == prop_name_low: prop_value_low = prop_value_v.lower() if 'true' == prop_value_low: - targetType = PRODUCT_DYN_LIB + target_type = PRODUCT_DYN_LIB #write the whole parsed manifest into sample.manifest file @@ -277,14 +285,11 @@ def parserManifest(manifest, manifestDataPath, mani_ext): # get manifest string file len manifest_str_size = os.path.getsize(mani_ext) - if manifest_str_size > 152: - print("extra manifest string exceed MAX len 152") - raise RuntimeError print('manifest str size {}'.format(manifest_str_size)) # 2> manifest + service_name print("bytes len {}".format(len(uuid_val.bytes_le))) - print("bytes len {}".format(len(manifest_val.getPackedData()))) + print("bytes len {}".format(len(manifest_val.get_pack_data()))) print("bytes len {}".format(len(service_name))) # 3> unparsed manifest, string manifest @@ -294,23 +299,24 @@ def parserManifest(manifest, manifestDataPath, mani_ext): print("manifest strint: {}".format(manifest_string_buf)) #---- write manifest parse context to manifest file - with open(manifestDataPath, 'wb') as out_manifest_fp: + with open(manifest_data_path, 'wb') as out_manifest_fp: out_manifest_fp.write(uuid_val.bytes_le) out_manifest_fp.write(str.encode(service_name)) - out_manifest_fp.write(manifest_val.getPackedData()) + out_manifest_fp.write(manifest_val.get_pack_data()) - productName = str(uuid_val) - if targetType == PRODUCT_TA_IMAGE: + product_name = str(uuid_val) + if target_type == PRODUCT_TA_IMAGE: print("product type is ta image") - productName = "".join([productName, ".sec"]) - elif targetType == PRODUCT_SERVICE_IMAGE: + product_name = "".join([product_name, ".sec"]) + elif target_type == PRODUCT_SERVICE_IMAGE: print("product type is service") - productName = "".join([productName, service_name, "_svr.sec"]) - elif targetType == PRODUCT_DYN_LIB: + product_name = "".join([product_name, service_name, "_svr.sec"]) + elif target_type == PRODUCT_DYN_LIB: print("product type is dyn lib") - productName = "".join([productName, service_name, ".so.sec"]) + product_name = "".join([product_name, service_name, ".so.sec"]) else: print("invalid product type!") raise RuntimeError - return (True, productName, uuid_val_flag) + return (True, product_name) + diff --git a/tools/sign_tool/sign_tool.py b/tools/sign_tool/sign_tool.py deleted file mode 100644 index 1e6e37d..0000000 --- a/tools/sign_tool/sign_tool.py +++ /dev/null @@ -1,471 +0,0 @@ -#!/usr/bin/env python -# coding:utf-8 -#---------------------------------------------------------------------------- -# Copyright @ Huawei Technologies Co., Ltd. 2018-2019. All rights reserved. -# tools for generating a trusted application load image -#---------------------------------------------------------------------------- - -import struct -import sys -import os -import hashlib -import binascii -import subprocess -import shutil - -from manifest import * - -DEBUG = 0 -VERSION = 3 -TA_VERSION = 3 -# TA_TYPE 1 stand for v3.0 -# TA_TYPE 2 stand for v3.1(with config and cert) -TA_TYPE = 0 - -API_LEVEL = 1 -PRODUCT_NAME = "" - -# OTRP_FLAG 1 stand for otrp sec, and only can load sec by otrp mode -# OTRP_FLAG 0 stand for no-otrp sec, and only can load sec by tzdriver mode -OTRP_FLAG = 0 - -MAGIC1 = 0xA5A55A5A -MAGIC2 = 0x55AA - -# low 8 bits:key is derived from root key -# high 8 bits:key len is 3072, if value is 0 or 1, then key len is 2048 -KEY_VERSION = 0x0202 - -SIGN_ALG_V3 = 0x10002048 -SIGN_ALG_V4 = 0x10004096 - -HASH256_LEN = 256 -HASH512_LEN = 512 - -ENCRYPTED_KEYINFO_LEN =256 -SIGNATURE_LEN_256 = 256 -SIGNATURE_LEN_512 = 512 - -SUCCESS = 0 - -# ELF Definitions -ELF_TYPE = 32 -ELF_HDR_SIZE = 52 -ELF_PHDR_SIZE = 32 -ELF_INFO_MAGIC0_INDEX = 0 -ELF_INFO_MAGIC1_INDEX = 1 -ELF_INFO_MAGIC2_INDEX = 2 -ELF_INFO_MAGIC3_INDEX = 3 -ELF_INFO_MAGIC0 = 127 #'\x7f' -ELF_INFO_MAGIC1 = 69 #'E' -ELF_INFO_MAGIC2 = 76 #'L' -ELF_INFO_MAGIC3 = 70 #'F' -ELF_INFO_CLASS_INDEX = 4 -ELF_INFO_CLASS = 1 #'\x01' -ELF_INFO_VERSION_INDEX = 6 -ELF_INFO_VERSION_CURRENT = 1 #'\x01' -ELF_BLOCK_ALIGN = 0x1000 -ELF_HEAD_FORMAT = '' - -#---------------------------------------------------------------------------- -# ELF File Header Check -#---------------------------------------------------------------------------- -class Elf_Header: - def __init__(self, data): - # Algin data obj in ELF header - if(ELF_TYPE == 64): - self.s = struct.Struct('16sHHIQQQIHHHHHH') - else: - self.s = struct.Struct('16sHHIIIIIHHHHHH') - - unpacked_data = (self.s).unpack(data) - self.unpacked_data = unpacked_data - self.elf_ident = unpacked_data[0] - self.elf_type = unpacked_data[1] - self.elf_machine = unpacked_data[2] - self.elf_version = unpacked_data[3] - self.elf_entry = unpacked_data[4] - self.elf_phoff = unpacked_data[5] - self.elf_shoff = unpacked_data[6] - self.elf_flags = unpacked_data[7] - self.elf_ehsize = unpacked_data[8] - self.elf_phentsize = unpacked_data[9] - self.elf_phnum = unpacked_data[10] - self.elf_shentsize = unpacked_data[11] - self.elf_shnum = unpacked_data[12] - self.elf_shstrndx = unpacked_data[13] - - def printValues(self): - print("ATTRIBUTE / VALUE") - for attr, value in self.__dict__.items(): - print(attr, value) - - def getPackedData(self): - values = [self.elf_ident, - self.elf_type, - self.elf_machine, - self.elf_version, - self.elf_entry, - self.elf_phoff, - self.elf_shoff, - self.elf_flags, - self.elf_ehsize, - self.elf_phentsize, - self.elf_phnum, - self.elf_shentsize, - self.elf_shnum, - self.elf_shstrndx - ] - - return (self.s).pack(*values) - -#---------------------------------------------------------------------------- -# Verify ELF header contents from an input ELF file -#---------------------------------------------------------------------------- -def verify_elf_header(elf_header): - s = struct.unpack('BBBBBBBBBBBBBBBB', elf_header.elf_ident) - if (s[ELF_INFO_MAGIC0_INDEX] != ELF_INFO_MAGIC0) or \ - (s[ELF_INFO_MAGIC1_INDEX] != ELF_INFO_MAGIC1) or \ - (s[ELF_INFO_MAGIC2_INDEX] != ELF_INFO_MAGIC2) or \ - (s[ELF_INFO_MAGIC3_INDEX] != ELF_INFO_MAGIC3) or \ - (s[ELF_INFO_CLASS_INDEX] != ELF_INFO_CLASS) or \ - (s[ELF_INFO_VERSION_INDEX] != ELF_INFO_VERSION_CURRENT): - - return False - else: - return True - -def get_elf_type(elfFile): - EI_NIDENT = 16 - global ELF_TYPE - global ELF_HDR_SIZE - global ELF_HEAD_FORMAT - global ELF_INFO_CLASS - - elfFile.seek(0x0, 0) - elf_ident = elfFile.read(EI_NIDENT) - ''' check EI_CLASS, 32-bit or 64-bit''' - elfStr = bytes.decode(elf_ident) - s = struct.unpack('BBBBBBBBBBBBBBBB', elf_ident) - if s[4] == 2: - print("64 bit type") - ELF_TYPE = 64 - ELF_HDR_SIZE = 64 - ELF_HEAD_FORMAT = "HHIQQQIHHHHHH" - ELF_INFO_CLASS = 2 - elif s[4] == 1: - print("32 bit type") - ELF_TYPE = 32 - ELF_HDR_SIZE = 52 - ELF_HEAD_FORMAT = "HHIIIIIHHHHHH" - ELF_INFO_CLASS = 1 - else: - raise RuntimeError("Unknown ELF file type") - return - -def generateHeader(contentLen): - return struct.pack('IHHII', MAGIC1, MAGIC2, VERSION, contentLen, KEY_VERSION) - -def generateAesKeyInfo(ivFilePath, keyFilePath, outFilePath): - # Aes key is randomly generated and temporarily stored in the file in plaintext, please ensure security. - try: - subprocess.check_output(["openssl", "rand", "-out", format(ivFilePath), "16"], shell=False) - subprocess.check_output(["openssl", "rand", "-out", format(keyFilePath), "32"], shell=False) - except: - print("rand operation failed") - raise RuntimeError - - with open(outFilePath, 'wb') as outFile: - outFile.write(struct.pack('I', 32)) - outFile.write(struct.pack('I', 16)) - if DEBUG == 0 or TA_TYPE == 1: - outFile.write(struct.pack('I', SIGN_ALG_V3)) - elif TA_TYPE == 2: - outFile.write(struct.pack('I', SIGN_ALG_V4)) - else: - print("target sign type is not supported: {}".format(TA_TYPE)) - raise RuntimeError - - with open(keyFilePath, 'rb') as keyFile: - outFile.write(keyFile.read(32)) - - with open(ivFilePath, 'rb') as ivFile: - outFile.write(ivFile.read(16)) - - return - -def encryptAesKeyInfo(pubkeyFilePath, inFilePath, outFilePath): - try: - subprocess.check_output(["openssl", "rsautl", "-encrypt", "-pubin", "-oaep", \ - "-inkey", format(pubkeyFilePath), "-in", format(inFilePath), "-out", format(outFilePath)], shell=False) - except: - print("RSA encrypt operation failed") - raise RuntimeError - return - -def generateHash(hashLen, inFilePath, outFilePath): - inFileSize = os.path.getsize(inFilePath) - # Initialize a SHA256 object from the Python hash library - if hashLen == HASH256_LEN: - hashOp = hashlib.sha256() - elif hashLen == HASH512_LEN: - hashOp = hashlib.sha512() - # Set the input buffer and return the output digest - with open(inFilePath, 'rb') as inFile: - hashOp.update(inFile.read(inFileSize)) - - #-----hash file used for ras sign--- - with open(outFilePath, 'wb') as hash_fp: - # fixed hash prefix value - hash_fp.write(struct.pack('B'*19, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, - 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20)) - hash_fp.write(hashOp.digest()) - return - -def generateSignature(priKeyPath, inFilePath, outFilePath): - if TA_TYPE == 1: - print("generate dummy signature for DEBUG version") - with open(outFilePath, 'wb') as f: - f.write(str.encode('\0'*256, encoding='utf-8')) - elif TA_TYPE == 2: - try: - subprocess.check_output(["openssl", "rsautl", "-sign", "-inkey", format(priKeyPath), \ - "-in", format(inFilePath), " -out", format(outFilePath)], shell=False) - except: - print("sign operation failed") - raise RuntimeError - return - -def checkSignature(rawDataHashPath, inSignature, serverPubKey): - try: - subprocess.check_output(["openssl", "pkeyutl", "-verify", "-in", format(rawDataHashPath), \ - "-sigfile", format(inSignature), "-pubin", "-inkey", format(serverPubKey)], shell=False) - except: - print("check operation failed") - raise RuntimeError - return - -def generateRawData(manifestDataPath, manifestExtFilePath, elfFilePath, configFilePath, rawFilePath): - manifestDataSize = os.path.getsize(manifestDataPath) - manifestExtSize = os.path.getsize(manifestExtFilePath) - elfFileSize = os.path.getsize(elfFilePath) - configFileSize = 0 - - with open(rawFilePath, 'wb') as f: - header = "" - if TA_TYPE == 2: - configFileSize = os.path.getsize(configFilePath) - header = struct.pack('IIIII', TA_VERSION, manifestDataSize, manifestExtSize, elfFileSize, configFileSize) - f.write(header) - - with open(manifestDataPath, 'rb') as manifestData: - f.write(manifestData.read(manifestDataSize)) - - with open(manifestExtFilePath, 'rb') as manifestExt: - f.write(manifestExt.read(manifestExtSize)) - - with open(elfFilePath, 'rb') as elfFile: - get_elf_type(elfFile) - elfFile.seek(0x0, 0) - elfFileHaderBuf = elfFile.read(ELF_HDR_SIZE) - elfFileHader = Elf_Header(elfFileHaderBuf) - if verify_elf_header(elfFileHader) is False: - print("verify elf header failed") - raise RuntimeError - elfFile.seek(0x0, 0) - f.write(elfFile.read(elfFileSize)) - - if TA_TYPE == 2: - with open(configFilePath, 'rb') as configFile: - f.write(configFile.read(configFileSize)) - return - -def aesEncrypt(keyPath, ivPath, inFilePath, outfilePath): - keySize = os.path.getsize(keyPath) - with open(keyPath, 'rb') as key: - keyData = key.read(keySize) - hexKeyStr = binascii.b2a_hex(keyData) - - ivSize = os.path.getsize(ivPath) - with open(ivPath, 'rb') as iv: - ivData = iv.read(ivSize) - hexIvStr = binascii.b2a_hex(ivData) - - try: - subprocess.check_output(["openssl", "enc", "-aes-256-cbc", "-in", format(inFilePath), \ - "-out", format(outfilePath), "-K", format(bytes.decode(hexKeyStr)), \ - "-iv", format(bytes.decode(hexIvStr))], shell=False) - except: - print("AES encrypt operation failed") - raise RuntimeError - - return - -def updateManifestTaApiLevel(manifest): - line = "\ngpd.ta.api_level:{}\n".format(API_LEVEL) - with open(manifest, "w") as f: - f.writelines(line) - -def updateManifestTaOtrpFlag(manifest): - data = '' - with open(manifest, 'r') as f: - for line in f: - if line.startswith("#") or not "gpd.ta.otrp_flag" in line: - data += line - line = "\ngpd.ta.otrp_flag:{}\n".format('true') - data += line - with open(manifest, "w") as f: - f.writelines(data) - -def generateDataForSign(contentLen, key_info, raw_file, data_sign): - keyInfoLen = os.path.getsize(key_info) - rawFileLen = os.path.getsize(raw_file) - - with open(data_sign, 'wb') as data_fp, \ - open(key_info, 'rb') as key_fp, open(raw_file, 'rb') as raw_fp: - data_fp.write(generateHeader(contentLen)) - data_fp.write(key_fp.read(keyInfoLen)) - data_fp.write(raw_fp.read(rawFileLen)) - - -def generateDigest(enclavePath, manifestPath, deviceKeyPath, configFilePath, rawDataHashPath, encKeyInfoFilePath, \ - encRawFilePath): - inPath = os.getcwd() - ivFilePath = os.path.join(inPath, "iv.bin") - keyFilePath = os.path.join(inPath, "aeskey.bin") - keyInfoFilePath = os.path.join(inPath, "KeyInfo") - rawFilePath = os.path.join(inPath, "rawData") - manifestDataPath = os.path.join(inPath, "manifestData.bin") - manifestExtPath = os.path.join(inPath, "manifestExt.bin") - dataForSignPath = os.path.join(inPath, "dataForSign.bin") - - #mandentory input files - manifestFilePath = manifestPath - elfFilePath = enclavePath - pubkeyFilePath = deviceKeyPath - - (ret, PRODUCT_NAME, flag) = parserManifest(manifestFilePath, manifestDataPath, manifestExtPath) - updateManifestTaApiLevel(manifestExtPath) - - if OTRP_FLAG == 1: - print("package otrp sec file\n") - updateManifestTaOtrpFlag(manifestExtPath) - - generateRawData(manifestDataPath, manifestExtPath, elfFilePath, configFilePath, rawFilePath) - - #generate AES key info to encrypt raw data - generateAesKeyInfo(ivFilePath, keyFilePath, keyInfoFilePath) - encryptAesKeyInfo(pubkeyFilePath, keyInfoFilePath, encKeyInfoFilePath) - - aesEncrypt(keyFilePath, ivFilePath, rawFilePath, encRawFilePath) - - contentLen = 0 - if DEBUG == 0 or TA_TYPE == 1: - contentLen = os.path.getsize(encKeyInfoFilePath) + SIGNATURE_LEN_256 + os.path.getsize(encRawFilePath) - elif TA_TYPE == 2: - contentLen = os.path.getsize(encKeyInfoFilePath) + SIGNATURE_LEN_512 + os.path.getsize(encRawFilePath) - else: - print("target sign type is not supported: {}".format(TA_TYPE)) - raise RuntimeError - - generateDataForSign(contentLen, keyInfoFilePath, rawFilePath, dataForSignPath) - - generateHash(HASH256_LEN, dataForSignPath, rawDataHashPath) - - #remove temp files - os.remove(ivFilePath) - os.remove(keyFilePath) - os.remove(keyInfoFilePath) - os.remove(rawFilePath) - os.remove(manifestDataPath) - os.remove(manifestExtPath) - os.remove(dataForSignPath) - return - -def generateSecEnclave(priKeyPath, rawDataHashPath, encKeyInfoFilePath, encRawFilePath, inSignature, serverPubKey, \ - outFile): - inPath = os.getcwd() - signatureFilePath = inSignature - if DEBUG == 1: - signatureFilePath = os.path.join(inPath, "signature.bin") - generateSignature(priKeyPath, rawDataHashPath, signatureFilePath) - else: - checkSignature(rawDataHashPath, inSignature, serverPubKey) - - contentLen = 0 - if DEBUG == 0 or TA_TYPE == 1: - contentLen = os.path.getsize(encKeyInfoFilePath) + SIGNATURE_LEN_256 + os.path.getsize(encRawFilePath) - elif TA_TYPE == 2: - contentLen = os.path.getsize(encKeyInfoFilePath) + SIGNATURE_LEN_512 + os.path.getsize(encRawFilePath) - else: - print("target sign type is not supported: {}".format(TA_TYPE)) - raise RuntimeError - - # secImagePath = os.path.join(outPath, productName) - secImagePath = outFile - with open(secImagePath, 'wb') as secImage: - # write to sec file [1.header info] - secImage.write(generateHeader(contentLen)) - # write to sec file [2.AES key info] - encKeyInfoSize = os.path.getsize(encKeyInfoFilePath) - with open(encKeyInfoFilePath, 'rb') as encKeyInfo: - secImage.write(encKeyInfo.read(encKeyInfoSize)) - # write to sec file [3.signature] - signatureSize = os.path.getsize(signatureFilePath) - with open(signatureFilePath, 'rb') as signatureFile: - secImage.write(signatureFile.read(signatureSize)) - # write to sec file [4.encrypted raw data] - encRawDataSize = os.path.getsize(encRawFilePath) - with open(encRawFilePath, 'rb') as encRawData: - secImage.write(encRawData.read(encRawDataSize)) - - if DEBUG == 1: - os.remove(signatureFilePath) - - print("=========================SUCCESS============================") - print("generate TA(V3 format) load image success: ") - print(secImagePath) - print("============================================================") - return - -if __name__ == '__main__': - argvs = sys.argv - priKeyPath = "" - configFilePath = "" - cmd = argvs[1] - DEBUG = int(argvs[2]) - enclavePath = argvs[3] - outFile = argvs[4] - manifestPath = argvs[5] - OTRP_FLAG = int(argvs[6]) - TA_TYPE = int(argvs[7]) - API_LEVEL = int(argvs[8]) - DEVICE_PUBKEY = argvs[9] - configFilePath = argvs[10] - - os.umask(127) - inPath = os.getcwd() - encKeyInfoFilePath = os.path.join(inPath, "KeyInfo.enc") - encRawFilePath = os.path.join(inPath, "rawData.enc") - rawDataHashPath = os.path.join(inPath, "rawDataHash.bin") - - if cmd == "digest": - generateDigest(enclavePath, manifestPath, DEVICE_PUBKEY, configFilePath, rawDataHashPath, encKeyInfoFilePath, \ - encRawFilePath) - shutil.copy(rawDataHashPath, outFile) - elif cmd == "sign": - if DEBUG == 0: - inSignature = argvs[11] - serverPubKey = argvs[12] - else: - if TA_TYPE == 2: - priKeyPath = argvs[11] - inSignature = "" - serverPubKey = "" - generateDigest(enclavePath, manifestPath, DEVICE_PUBKEY, configFilePath, rawDataHashPath, \ - encKeyInfoFilePath, encRawFilePath) - generateSecEnclave(priKeyPath, rawDataHashPath, encKeyInfoFilePath, encRawFilePath, inSignature, \ - serverPubKey, outFile) - os.remove(rawDataHashPath) - os.remove(encKeyInfoFilePath) - os.remove(encRawFilePath) diff --git a/tools/sign_tool/sign_tool.sh b/tools/sign_tool/sign_tool.sh index 212db5d..5fd7d5b 100755 --- a/tools/sign_tool/sign_tool.sh +++ b/tools/sign_tool/sign_tool.sh @@ -10,39 +10,42 @@ #!/bin/bash VERSION=3 -TA_TYPE=1 -OTRP_FLAG=0 -API_LEVEL=1 -DEBUG=0 +API_LEVEL=2 +ONE_STEP_MODE=1 +A_CONFIG_FILE="NULL" localpath="$(cd "$(dirname "$0")"; pwd)" print_help(){ echo "sign tool usage: ./sign_tool.sh [options] ..." echo "[options]" - echo "-a <parameter> API_LEVEL, indicates trustzone GP API version, defalut is 1." echo "-c <file> basic config file." echo "-d <parameter> sign tool command, sign/digest." echo " The sign command is used to generate a signed enclave." echo " The digest command is used to generate a digest value." - echo "-f <parameter> OTRP_FLAG, indicates whether the OTRP standard protocol is supported, default is 0." echo "-i <file> enclave to be signed." - echo "-k <file> private key required for single-step method, required when trustzone TA_TYPE is 2 or sgx." - echo "-m <file> additional config for trustzone when TA_TYPE is 2." + echo "-k <file> private key required for single-step method" + echo "-m <file> additional config_cloud.ini for trustzone." echo "-o <file> output parameters, the sign command outputs sigend enclave, the digest command outputs" echo " digest value." echo "-p <file> signing server public key certificate, required for two-step method." echo "-s <file> the signed digest value required for two-step method, this parameter is empty to indicate" echo " single-step method." - echo "-t <parameter> trustzone TA_TYPE, default is 1." echo "-x <parameter> enclave type, sgx or trustzone." echo "-h printf help message." } -while getopts "d:i:x:m:a:f:t:c:k:p:s:o:h" opt +while getopts "c:d:i:k:m:o:p:s:x:h" opt do case $opt in + c) + if [[ $OPTARG == -* ]]; then + echo "Error: parameter for -c is missing or incorrect" + exit -1 + fi + CONFIG_FILE=$OPTARG + ;; d) if [[ $OPTARG == -* ]]; then echo "Error: parameter for -d is missing or incorrect" @@ -58,13 +61,12 @@ do fi IN_ENCLAVE=$OPTARG ;; - x) + k) if [[ $OPTARG == -* ]]; then - echo "Error: parameter for -x is missing or incorrect" + echo "Error: parameter for -k is missing or incorrect" exit -1 - fi - typeset -l ENCLAVE_TYPE - ENCLAVE_TYPE=$OPTARG + fi + SIG_KEY=$OPTARG ;; m) if [[ $OPTARG == -* ]]; then @@ -73,55 +75,12 @@ do fi A_CONFIG_FILE=$OPTARG ;; - a) - if [[ $OPTARG =~ ^[1-3]$ ]]; then - API_LEVEL=$OPTARG - else - if [[ $OPTARG == -* ]]; then - echo "Error: parameter for -a is missing or incorrect" - exit -1 - fi - echo "Error: illegal API LEVEL" - exit -1 - fi - ;; - f) - if [[ $OPTARG =~ ^[0-1]$ ]]; then - OTRP_FLAG=$OPTARG - else - if [[ $OPTARG == -* ]]; then - echo "Error: parameter for -f is missing or incorrect" - exit -1 - fi - echo "Error: illegal OTRP FLAG" - exit -1 - fi - ;; - t) - if [[ $OPTARG =~ ^[1-2]$ ]]; then - TA_TYPE=$OPTARG - else - if [[ $OPTARG == -* ]]; then - echo "Error: parameter for -t is missing or incorrect" - exit -1 - fi - echo "Error: illegal TA TYPE" - exit -1 - fi - ;; - c) - if [[ $OPTARG == -* ]]; then - echo "Error: parameter for -c is missing or incorrect" - exit -1 - fi - CONFIG_FILE=$OPTARG - ;; - k) + o) if [[ $OPTARG == -* ]]; then - echo "Error: parameter for -k is missing or incorrect" + echo "Error: parameter for -o is missing or incorrect" exit -1 fi - SIG_KEY=$OPTARG + OUT_FILE=$OPTARG ;; p) if [[ $OPTARG == -* ]]; then @@ -137,12 +96,13 @@ do fi SIGNATURE=$OPTARG ;; - o) + x) if [[ $OPTARG == -* ]]; then - echo "Error: parameter for -o is missing or incorrect" + echo "Error: parameter for -x is missing or incorrect" exit -1 - fi - OUT_FILE=$OPTARG + fi + typeset -l ENCLAVE_TYPE + ENCLAVE_TYPE=$OPTARG ;; h) print_help @@ -160,47 +120,48 @@ fi itrustee_start_sign(){ # check_native_sign - MANIFEST=$CONFIG_FILE - if [ -z $MANIFEST ]; then + if [ -z $A_CONFIG_FILE ]; then echo "Error: missing config file for signing iTrustee enclave" exit -1 fi - if [ ${TA_TYPE} == 2 ]; then - if [ -z $A_CONFIG_FILE]; then - echo "Error: TA TYPE = 2, missing additional config file for signing iTrustee enclave" - exit -1 - fi - else - A_CONFIG_FILE="NULL" - fi - DEVICE_PUBKEY=${localpath}/rsa_public_key_cloud.pem - if [ "${CMD}"x == "sign"x ]; then if [ -z $SIGNATURE ]; then - DEBUG=1 - if [ -z $SIG_KEY ] && [ ${TA_TYPE} == 2 ]; then - echo "missing the signature private key" + ONE_STEP_MODE=1 + if [ -z $CONFIG_FILE ]; then + echo "Error: missing config file for signing iTrustee enclave" exit -1 fi - python ${localpath}/sign_tool.py "sign" "${DEBUG}" "${IN_ENCLAVE}" "${OUT_FILE}" "${MANIFEST}" "${OTRP_FLAG}" "${TA_TYPE}" "${API_LEVEL}" "${DEVICE_PUBKEY}" "${A_CONFIG_FILE}" "${SIG_KEY}" - else - DEBUG=0 - if [ -z $SERVER_PUBKEY ]; then - echo "Error: missing server public key for verifying signature" + if [ -z $IN_ENCLAVE ]; then + echo "Error: missing enclave file" exit -1 fi - python ${localpath}/sign_tool.py "sign" "${DEBUG}" "${IN_ENCLAVE}" "${OUT_FILE}" "${MANIFEST}" "${OTRP_FLAG}" "${TA_TYPE}" "${API_LEVEL}" "${DEVICE_PUBKEY}" "${A_CONFIG_FILE}" "${SIGNATURE}" "${SERVER_PUBKEY}" + python ${localpath}/signtool_v3.py "sign" "${ONE_STEP_MODE}" "${IN_ENCLAVE}" "${OUT_FILE}" "${CONFIG_FILE}" "${A_CONFIG_FILE}" "${API_LEVEL}" + else + ONE_STEP_MODE=0 + python ${localpath}/signtool_v3.py "sign" "${ONE_STEP_MODE}" "NULL" "${OUT_FILE}" "NULL" "${A_CONFIG_FILE}" "${API_LEVEL}" "${SIGNATURE}" fi elif [ "${CMD}"x == "digest"x ]; then - DEBUG=0 - python ${localpath}/sign_tool.py "digest" "${DEBUG}" "${IN_ENCLAVE}" "${OUT_FILE}" "${MANIFEST}" "${OTRP_FLAG}" "${TA_TYPE}" "${API_LEVEL}" "${DEVICE_PUBKEY}" "${A_CONFIG_FILE}" + ONE_STEP_MODE=0 + if [ -z $CONFIG_FILE ]; then + echo "Error: missing config file for signing iTrustee enclave" + exit -1 + fi + if [ -z $IN_ENCLAVE ]; then + echo "Error: missing enclave file" + exit -1 + fi + python ${localpath}/signtool_v3.py "digest" "${ONE_STEP_MODE}" "${IN_ENCLAVE}" "${OUT_FILE}" "${CONFIG_FILE}" "${A_CONFIG_FILE}" "${API_LEVEL}" else echo "Error: illegal command" fi } sgx_start_sign(){ + if [ -z $IN_ENCLAVE ]; then + echo "Error: missing enclave file" + exit -1 + fi SIGDATA_FILE="signdata" if [ "${CMD}"x == "sign"x ]; then if [ -z $SIG_KEY ]; then @@ -246,10 +207,6 @@ if [ -z $ENCLAVE_TYPE ]; then echo "Error: missing enclave type" exit -1 fi -if [ -z $IN_ENCLAVE ]; then - echo "Error: missing enclave file" - exit -1 -fi if [ -z $OUT_FILE ]; then echo "Error: missing out file" exit -1 diff --git a/tools/sign_tool/signtool_v3.py b/tools/sign_tool/signtool_v3.py new file mode 100644 index 0000000..dae036f --- /dev/null +++ b/tools/sign_tool/signtool_v3.py @@ -0,0 +1,428 @@ +#!/usr/bin/env python +# coding:utf-8 +#---------------------------------------------------------------------------- +# Copyright (c) Huawei Technologies Co., Ltd. 2018-2020. All rights reserved. +# iTrustee licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan +# PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY +# KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO +# NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. +# Description: tools for generating a trusted application load image +# Author: Li mingjuan +# Create: 2018-02-20 +#---------------------------------------------------------------------------- + +import struct +import os +import sys +import stat +import hashlib +import binascii +import subprocess +import shutil +import getpass +import argparse + +try: + from configparser import SafeConfigParser +except ImportError: + from ConfigParser import SafeConfigParser + +from manifest import parser_manifest +from generate_signature import gen_ta_signature +from generate_signature import gen_hash + +# fixed value, {1, 2} version are abandoned. +VERSION = 3 +TA_VERSION = 3 + +MAX_EXT_PROP_LEN = 152 + +MAGIC1 = 0xA5A55A5A +MAGIC2 = 0x55AA + +# ELF Definitions +ELF_TYPE = 32 +ELF_HDR_SIZE = 52 +ELF_PHDR_SIZE = 32 +ELF_INFO_MAGIC0_INDEX = 0 +ELF_INFO_MAGIC1_INDEX = 1 +ELF_INFO_MAGIC2_INDEX = 2 +ELF_INFO_MAGIC3_INDEX = 3 +#'\x7f' +ELF_INFO_MAGIC0 = 127 +#'E' +ELF_INFO_MAGIC1 = 69 +#'L' +ELF_INFO_MAGIC2 = 76 +#'F' +ELF_INFO_MAGIC3 = 70 +ELF_INFO_CLASS_INDEX = 4 +ELF_INFO_CLASS_32 = 1 +ELF_INFO_CLASS_64 = 2 +ELF_INFO_VERSION_INDEX = 6 +ELF_INFO_VERSION_CURRENT = 1 +ELF_BLOCK_ALIGN = 0x1000 + + +#---------------------------------------------------------------------------- +# Verify ELF header contents from an input ELF file +#---------------------------------------------------------------------------- +def verify_elf_header(elf_path): + elf_type = 0 + with open(elf_path, 'rb') as elf: + elf_data = struct.unpack('B'*16, elf.read(16)) + elf_type = elf_data[4] + if ((elf_data[ELF_INFO_MAGIC0_INDEX] != ELF_INFO_MAGIC0) or \ + (elf_data[ELF_INFO_MAGIC1_INDEX] != ELF_INFO_MAGIC1) or \ + (elf_data[ELF_INFO_MAGIC2_INDEX] != ELF_INFO_MAGIC2) or \ + (elf_data[ELF_INFO_MAGIC3_INDEX] != ELF_INFO_MAGIC3) or \ + (elf_data[ELF_INFO_VERSION_INDEX] != \ + ELF_INFO_VERSION_CURRENT)): + print("invalid elf header info") + raise RuntimeError + + if ((elf_type == 1 and elf_data[ELF_INFO_CLASS_INDEX] != \ + ELF_INFO_CLASS_32) or \ + (elf_type == 2 and elf_data[ELF_INFO_CLASS_INDEX] != \ + ELF_INFO_CLASS_64) or \ + (elf_type != 1 and elf_type != 2)): + print("invliad elf format") + raise RuntimeError + return + + +class Configuration: + release_type = 0 + otrp_flag = 0 + sign_type = 0 + public_key = "" + pub_key_len = 0 + server_ip = "" + config_path = "" + sign_key = "" + sign_key_len = 2048 + hash_type = 0 + padding_type = 0 + + def __init__(self, file_name): + parser = SafeConfigParser() + parser.read(file_name) + self.release_type = parser.get("config", "releaseType") + self.otrp_flag = parser.get("config", "otrpFlag") + self.sign_type = parser.get("config", "signType") + self.public_key = parser.get("config", "encryptKey") + self.pub_key_len = parser.get("config", "encryptKeyLen") + self.server_ip = parser.get("config", "serverIp") + self.config_path = parser.get("config", "configPath") + self.sign_key = parser.get("config", "signKey") + self.sign_key_len = parser.get("config", "signKeyLen") + self.hash_type = parser.get("config", "hashType") + self.padding_type = parser.get("config", "paddingType") + + +def gen_header(content_len, key_version): + return struct.pack('IHHII', MAGIC1, MAGIC2, VERSION, content_len, \ + key_version) + + +def gen_aes_key_info(cfg, iv_file_path, key_file_path, out_file_path): + rand_iv_cmd = "openssl rand -out {} 16".format(iv_file_path) + rand_key_cmd = "openssl rand -out {} 32".format(key_file_path) + try: + subprocess.check_output(rand_iv_cmd.split(), shell=False) + subprocess.check_output(rand_key_cmd.split(), shell=False) + except Exception: + print("rand operation failed") + raise RuntimeError + + os.chmod(iv_file_path, stat.S_IWUSR | stat.S_IRUSR) + os.chmod(key_file_path, stat.S_IWUSR | stat.S_IRUSR) + + sign_alg = 0 + sign_alg = sign_alg | (int(cfg.release_type) << 28) + sign_alg = sign_alg | (int(cfg.padding_type) << 27) + sign_alg = sign_alg | (int(cfg.hash_type) << 26) + if cfg.sign_key_len == "2048": + sign_alg = sign_alg | 0x00002048 + elif cfg.sign_key_len == "4096": + sign_alg = sign_alg | 0x00004096 + + print("sign_alg value is 0x%x" % sign_alg) + with open(out_file_path, 'wb') as out_file: + out_file.write(struct.pack('I', 32)) + out_file.write(struct.pack('I', 16)) + out_file.write(struct.pack('I', sign_alg)) + + with open(key_file_path, 'rb') as key_file: + out_file.write(key_file.read(32)) + + with open(iv_file_path, 'rb') as iv_file: + out_file.write(iv_file.read(16)) + + os.chmod(out_file_path, stat.S_IWUSR | stat.S_IRUSR) + return + + +def encrypt_aes_key(pubkey_path, in_path, out_path): + cmd = "openssl rsautl -encrypt -pubin -oaep -inkey {} -in {} -out {}". \ + format(pubkey_path, in_path, out_path) + try: + subprocess.check_output(cmd.split(), shell=False) + except Exception: + print("RSA encrypt operation failed") + raise RuntimeError + os.chmod(out_path, stat.S_IWUSR | stat.S_IRUSR) + return + +def gen_signature(cfg, uuid_str, raw_data_path, hash_file_path, out_file_path): + gen_ta_signature(cfg, uuid_str, raw_data_path, hash_file_path, out_file_path) + os.chmod(out_file_path, stat.S_IWUSR | stat.S_IRUSR) + return + +def gen_raw_data(manifest_data_path, manifest_ext_path, elf_file_path, \ + config_path, raw_file_path): + manifest_size = os.path.getsize(manifest_data_path) + manifest_ext_size = os.path.getsize(manifest_ext_path) + elf_size = os.path.getsize(elf_file_path) + config_size = 0 + + if manifest_ext_size > MAX_EXT_PROP_LEN: + print("too much data in \"manifest.txt\" to be handled. \ + extra string len %d" \ + % manifest_ext_size) + raise RuntimeError + + verify_elf_header(elf_file_path) + + with open(raw_file_path, 'wb') as file_op: + header = "" + if os.path.isfile(config_path): + config_size = os.path.getsize(config_path) + header = struct.pack('IIIII', TA_VERSION, manifest_size, \ + manifest_ext_size, \ + elf_size, config_size) + file_op.write(header) + + with open(manifest_data_path, 'rb') as manifest_data: + file_op.write(manifest_data.read(manifest_size)) + + with open(manifest_ext_path, 'rb') as manifest_ext: + file_op.write(manifest_ext.read(manifest_ext_size)) + + with open(elf_file_path, 'rb') as elf: + file_op.write(elf.read(elf_size)) + if config_size != 0: + with open(config_path, 'rb') as config: + file_op.write(config.read(config_size)) + return + + +def aes_encrypt(key_path, iv_path, in_file_path, out_file_path): + key_size = os.path.getsize(key_path) + with open(key_path, 'rb') as key_file: + key_data = key_file.read(key_size) + hex_key_str = binascii.b2a_hex(key_data) + + iv_size = os.path.getsize(iv_path) + with open(iv_path, 'rb') as iv_file: + iv_data = iv_file.read(iv_size) + hex_iv_str = binascii.b2a_hex(iv_data) + + cmd = "openssl enc -aes-256-cbc -in {} -out {} -K {} -iv {}".\ + format(in_file_path, out_file_path, \ + bytes.decode(hex_key_str), bytes.decode(hex_iv_str)) + try: + subprocess.check_output(cmd.split(), shell=False) + except Exception: + print("AES encrypt operation failed") + raise RuntimeError + + os.chmod(out_file_path, stat.S_IWUSR | stat.S_IRUSR) + return + +def update_api_level(api_level, manifest): + data = '' + with open(manifest, 'r') as file_op: + for line in file_op: + if line.startswith("#") or not "gpd.ta.api_level" in line: + data += line + line = "\ngpd.ta.api_level:{}\n".format(api_level) + data += line + with open(manifest, "w") as file_op: + file_op.writelines(data) + + +def update_otrp_flag(manifest): + data = '' + with open(manifest, 'r') as file_op: + for line in file_op: + if line.startswith("#") or not "gpd.ta.otrp_flag" in line: + data += line + line = "\ngpd.ta.otrp_flag:{}\n".format('true') + data += line + with open(manifest, "w") as file_op: + file_op.writelines(data) + + +def gen_data_for_sign(header, key_info, raw_file, data_sign): + key_info_len = os.path.getsize(key_info) + raw_file_len = os.path.getsize(raw_file) + + with open(data_sign, 'wb') as data_fp, \ + open(key_info, 'rb') as key_fp, open(raw_file, 'rb') as raw_fp: + data_fp.write(header) + data_fp.write(key_fp.read(key_info_len)) + data_fp.write(raw_fp.read(raw_file_len)) + + +def gen_key_version(cfg): + if cfg.pub_key_len == '3072': + return int(0x0202) + if cfg.pub_key_len == '2048': + return int(0x0002) + print("unhandled pulic key len %s" % cfg.pub_key_len) + raise RuntimeError + + +def generate_digest(cfg, api_level, enclave_file, manifest_file, hash_path, enc_key_path, enc_raw_path): + # temporary files + in_path = os.path.dirname(os.path.abspath(manifest_file)) + temp_path = os.path.join(in_path, "temp") + shutil.rmtree(temp_path, ignore_errors=True) + os.mkdir(temp_path) + os.chmod(temp_path, stat.S_IRWXU) + iv_file_path = os.path.join(temp_path, "iv.bin") + key_file_path = os.path.join(temp_path, "aeskey.bin") + key_info_path = os.path.join(temp_path, "KeyInfo") + raw_file_path = os.path.join(temp_path, "rawData") + manifest_data_path = os.path.join(temp_path, "manifestData.bin") + manifest_ext_path = os.path.join(temp_path, "manifestExt.bin") + data_for_sign_path = os.path.join(temp_path, "dataForSign.bin") + signature_path = os.path.join(temp_path, "signature.bin") + + # mandentory input files + manifest_path = manifest_file + elf_file_path = enclave_file + + ret, product_name = parser_manifest(manifest_path, \ + manifest_data_path, manifest_ext_path) + if ret is False: + raise RuntimeError + + update_api_level(api_level, manifest_ext_path) + + if cfg.otrp_flag == 1: + print("package otrp sec file\n") + update_otrp_flag(manifest_ext_path) + + gen_raw_data(manifest_data_path, manifest_ext_path, elf_file_path, \ + cfg.config_path, raw_file_path) + + # generate AES key info to encrypt raw data + gen_aes_key_info(cfg, iv_file_path, key_file_path, key_info_path) + encrypt_aes_key(cfg.public_key, key_info_path, enc_key_path) + + aes_encrypt(key_file_path, iv_file_path, raw_file_path, enc_raw_path) + + # generate Main Header + content_len = os.path.getsize(enc_key_path) + \ + (int(cfg.sign_key_len) / 8) + \ + os.path.getsize(enc_raw_path) + key_version = gen_key_version(cfg) + header = gen_header(int(content_len), key_version) + + gen_data_for_sign(header, key_info_path, raw_file_path, data_for_sign_path) + + gen_hash(cfg.hash_type, data_for_sign_path, hash_path) + + #remove temp files + os.remove(iv_file_path) + os.remove(key_file_path) + os.remove(key_info_path) + os.remove(raw_file_path) + os.remove(manifest_data_path) + os.remove(manifest_ext_path) + os.remove(data_for_sign_path) + return + +def gen_sec_image(cfg, enc_raw_path, enc_key_path, signature_path, out_file): + content_len = os.path.getsize(enc_key_path) + \ + (int(cfg.sign_key_len) / 8) + \ + os.path.getsize(enc_raw_path) + key_version = gen_key_version(cfg) + header = gen_header(int(content_len), key_version) + sec_img_path = out_file + with open(sec_img_path, 'wb') as sec_image: + # write to sec file [1.header info] + sec_image.write(header) + # write to sec file [2.AES key info] + enc_key_size = os.path.getsize(enc_key_path) + with open(enc_key_path, 'rb') as enc_key_info: + sec_image.write(enc_key_info.read(enc_key_size)) + # write to sec file [3.signature] + signature_size = os.path.getsize(signature_path) + with open(signature_path, 'rb') as signature_file: + sec_image.write(signature_file.read(signature_size)) + # write to sec file [4.encrypted raw data] + enc_raw_size = os.path.getsize(enc_raw_path) + with open(enc_raw_path, 'rb') as enc_raw_data: + sec_image.write(enc_raw_data.read(enc_raw_size)) + + print("=========================SUCCESS============================") + print("generate TA(V3 format) load image success: ") + print(sec_img_path) + print("============================================================") + + return + + +def main(): + argvs = sys.argv + cmd = argvs[1] + one_step_mode = int(argvs[2]) + enclave_path = argvs[3] + out_file = argvs[4] + manifest_file = argvs[5] + cloud_config = argvs[6] + cfg = Configuration(cloud_config) + api_level = int(argvs[7]) + + os.umask(127) + + in_path = os.path.dirname(os.path.abspath(cloud_config)) + temp_path = os.path.join(in_path, "temp") + enc_key_path = os.path.join(temp_path, "KeyInfo.enc") + enc_raw_path = os.path.join(temp_path, "rawData.enc") + hash_path = os.path.join(temp_path, "rawDataHash.bin") + temp_signature = os.path.join(temp_path, "tempSignature") + + sign_tool_dir = os.path.dirname(os.path.abspath(__file__)) + os.chdir(sign_tool_dir) + if cmd == "digest": + generate_digest(cfg, api_level, enclave_path, manifest_file, hash_path, enc_key_path, enc_raw_path) + shutil.copy(hash_path, out_file) + elif cmd == "sign": + if one_step_mode == 0: + in_signature = argvs[8] + gen_sec_image(cfg, enc_raw_path, enc_key_path, in_signature, out_file) + else: + generate_digest(cfg, api_level, enclave_path, manifest_file, hash_path, enc_key_path, enc_raw_path) + gen_ta_signature(cfg, hash_path, temp_signature) + in_signature = temp_signature + gen_sec_image(cfg, enc_raw_path, enc_key_path, in_signature, out_file) + os.remove(temp_signature) + os.remove(enc_key_path) + os.remove(enc_raw_path) + os.remove(hash_path) + #remove temp files + shutil.rmtree(temp_path) + + +if __name__ == '__main__': + main() + -- 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