diff --git a/0060-supprot-kunpeng-remote-attestation.patch b/0060-supprot-kunpeng-remote-attestation.patch new file mode 100644 index 0000000000000000000000000000000000000000..5087850cbe0e0e8c469d2c1f1775ccac3eacb4d3 --- /dev/null +++ b/0060-supprot-kunpeng-remote-attestation.patch @@ -0,0 +1,5493 @@ +From 826207b3d8e51cf57af7e4f6a3df61b150561b60 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Wed, 17 May 2023 10:36:16 +0800 +Subject: [PATCH] supprot kunpeng remote attestation + +--- + CMakeLists.txt | 8 +- + component/CMakeLists.txt | 4 +- + component/remote_attest/CMakeLists.txt | 22 + + .../remote_attest/ra_report/CMakeLists.txt | 48 + + .../remote_attest/ra_report/gp_ra_helper.c | 136 + + .../remote_attest/ra_report/gp_ra_helper.h | 34 + + .../remote_attest/ra_report/gp_ra_report.c | 69 + + .../remote_attest/ra_report/gp_ra_report.h | 24 + + .../remote_attest/ra_report/sg_ra_report.c | 26 + + .../remote_attest/ra_report/sg_ra_report.h | 34 + + .../remote_attest/ra_verify/CMakeLists.txt | 44 + + .../ra_verify/gp_ra_report_verify.c | 50 + + .../ra_verify/gp_ra_report_verify.h | 30 + + .../ra_verify/sg_ra_report_verify.c | 20 + + .../ra_verify/sg_ra_report_verify.h | 30 + + component/remote_attest/sg_report_st.h | 43 + + inc/host_inc/status.h | 8 + + thirdparty/cjson/cJSON.bak | 3110 +++++++++++++++++ + thirdparty/cjson/cJSON.h | 293 ++ + .../kunpengsecl/verifier/custom_base64url.h | 20 + + thirdparty/kunpengsecl/verifier/teeverifier.h | 50 + + thirdparty/libqca/ra_client_api.h | 22 + + tools/sign_tool/generate_signature.py | 56 - + tools/sign_tool/manifest.py | 322 -- + tools/sign_tool/sign_tool.sh | 252 +- + tools/sign_tool/signtool_v3.py | 428 --- + 26 files changed, 4224 insertions(+), 959 deletions(-) + create mode 100644 component/remote_attest/CMakeLists.txt + create mode 100644 component/remote_attest/ra_report/CMakeLists.txt + create mode 100644 component/remote_attest/ra_report/gp_ra_helper.c + create mode 100644 component/remote_attest/ra_report/gp_ra_helper.h + create mode 100644 component/remote_attest/ra_report/gp_ra_report.c + create mode 100644 component/remote_attest/ra_report/gp_ra_report.h + create mode 100644 component/remote_attest/ra_report/sg_ra_report.c + create mode 100644 component/remote_attest/ra_report/sg_ra_report.h + create mode 100644 component/remote_attest/ra_verify/CMakeLists.txt + create mode 100644 component/remote_attest/ra_verify/gp_ra_report_verify.c + create mode 100644 component/remote_attest/ra_verify/gp_ra_report_verify.h + create mode 100644 component/remote_attest/ra_verify/sg_ra_report_verify.c + create mode 100644 component/remote_attest/ra_verify/sg_ra_report_verify.h + create mode 100644 component/remote_attest/sg_report_st.h + create mode 100644 thirdparty/cjson/cJSON.bak + create mode 100644 thirdparty/cjson/cJSON.h + create mode 100644 thirdparty/kunpengsecl/verifier/custom_base64url.h + create mode 100644 thirdparty/kunpengsecl/verifier/teeverifier.h + create mode 100644 thirdparty/libqca/ra_client_api.h + delete mode 100644 tools/sign_tool/generate_signature.py + delete mode 100644 tools/sign_tool/manifest.py + delete mode 100644 tools/sign_tool/signtool_v3.py + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 9c3c25b..079be3b 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -92,10 +92,4 @@ install(FILES ${LOCAL_ROOT_PATH}/conf/rsyslog.d/secgear.conf + install(FILES ${LOCAL_ROOT_PATH}/tools/sign_tool/sign_tool.sh + DESTINATION ${LOCAL_ROOT_PATH_INSTALL}/usr/bin/ + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +-set(SIGN_FILE +- ${LOCAL_ROOT_PATH}/tools/sign_tool/generate_signature.py +- ${LOCAL_ROOT_PATH}/tools/sign_tool/manifest.py +- ${LOCAL_ROOT_PATH}/tools/sign_tool/signtool_v3.py +-) +-install(FILES ${SIGN_FILE} +- DESTINATION ${LOCAL_ROOT_PATH_INSTALL}/lib/secGear/) ++ +diff --git a/component/CMakeLists.txt b/component/CMakeLists.txt +index 6cff34c..ee0a669 100644 +--- a/component/CMakeLists.txt ++++ b/component/CMakeLists.txt +@@ -9,6 +9,8 @@ + # See the Mulan PSL v2 for more details. + + ADD_SUBDIRECTORY(secure_channel) +- ++if(CC_GP) ++ ADD_SUBDIRECTORY(remote_attest) ++endif() + + +diff --git a/component/remote_attest/CMakeLists.txt b/component/remote_attest/CMakeLists.txt +new file mode 100644 +index 0000000..0b86c6f +--- /dev/null ++++ b/component/remote_attest/CMakeLists.txt +@@ -0,0 +1,22 @@ ++# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++# secGear is licensed under the Mulan PSL v2. ++# You can use this software according to the terms and conditions of the Mulan PSL v2. ++# You may obtain a copy of Mulan PSL v2 at: ++# http://license.coscl.org.cn/MulanPSL2 ++# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# PURPOSE. ++# See the Mulan PSL v2 for more details. ++ ++ADD_SUBDIRECTORY(ra_report) ++ADD_SUBDIRECTORY(ra_verify) ++ ++ ++file(GLOB RA_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/sg_report_st.h ++ ${CMAKE_CURRENT_SOURCE_DIR}/ra_report/sg_ra_report.h ++ ${CMAKE_CURRENT_SOURCE_DIR}/ra_report/gp_ra_helper.h ++ ${CMAKE_CURRENT_SOURCE_DIR}/ra_verify/sg_ra_report_verify.h) ++ ++install(FILES ${RA_HEADERS} ++ DESTINATION /usr/include/secGear ++ PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +diff --git a/component/remote_attest/ra_report/CMakeLists.txt b/component/remote_attest/ra_report/CMakeLists.txt +new file mode 100644 +index 0000000..6b459d7 +--- /dev/null ++++ b/component/remote_attest/ra_report/CMakeLists.txt +@@ -0,0 +1,48 @@ ++# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++# secGear is licensed under the Mulan PSL v2. ++# You can use this software according to the terms and conditions of the Mulan PSL v2. ++# You may obtain a copy of Mulan PSL v2 at: ++# http://license.coscl.org.cn/MulanPSL2 ++# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# PURPOSE. ++# See the Mulan PSL v2 for more details. ++ ++project(sg_ra_report C) ++ ++set(TARGET secgear_ra) ++aux_source_directory(. SRC_FILES) ++aux_source_directory(${LOCAL_ROOT_PATH}/thirdparty/cjson/ CJSON_SRC) ++ ++set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") ++ ++if(${CMAKE_VERSION} VERSION_LESS "3.13.0") ++ link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) ++endif() ++ ++include_directories( ++ ${CMAKE_CURRENT_BINARY_DIR} ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ${CMAKE_CURRENT_SOURCE_DIR}/.. ++ ${LOCAL_ROOT_PATH}/inc/host_inc ++ ${SDK_PATH}/include/CA ++ ${LOCAL_ROOT_PATH}/thirdparty/cjson ++ ${LOCAL_ROOT_PATH}/thirdparty/libqca ++ ${LOCAL_ROOT_PATH}/thirdparty/kunpengsecl/verifier ++) ++add_library(${TARGET} SHARED ${SRC_FILES} ${CJSON_SRC}) ++ ++if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") ++ target_link_directories(${TARGET} PRIVATE /usr/lib64) ++endif() ++ ++target_link_libraries(${TARGET} teec_adaptor) ++ ++set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) ++ ++install(TARGETS ${TARGET} ++ LIBRARY ++ DESTINATION ${LIBRARY_INSTALL} ++ PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) ++ ++ +diff --git a/component/remote_attest/ra_report/gp_ra_helper.c b/component/remote_attest/ra_report/gp_ra_helper.c +new file mode 100644 +index 0000000..80a01e9 +--- /dev/null ++++ b/component/remote_attest/ra_report/gp_ra_helper.c +@@ -0,0 +1,136 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#include "gp_ra_helper.h" ++ ++#include ++#include "cJSON.h" ++#include "custom_base64url.h" ++#include "enclave_log.h" ++ ++void free_gp_ra_buf(cc_ra_buf_t *ra_buf) ++{ ++ if (ra_buf->buf != NULL) { ++ free(ra_buf->buf); ++ } ++ if (ra_buf != NULL) { ++ free(ra_buf); ++ } ++} ++ ++/* caller need to free (cc_ra_buf_t **in) */ ++cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in) ++{ ++ cc_enclave_result_t ret = CC_SUCCESS; ++ cJSON *in_json = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_json, "handler", "provisioning-input"); ++ ++ cJSON *in_payload = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); ++ cJSON_AddStringToObject(in_payload, "scenario", "sce_no_as"); ++ cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); ++ ++ cJSON_AddItemToObject(in_json, "payload", in_payload); ++ ++ // char *in_buf = cJSON_PrintUnformatted(in_json); ++ char *in_buf = cJSON_Print(in_json); ++ uint32_t in_buf_len = strlen(in_buf) + 1; ++ ++ print_debug("provision input json buf:%s\n", in_buf); ++ ++ cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); ++ if (tmp_ra_buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ goto end; ++ } ++ tmp_ra_buf->buf = calloc(1, in_buf_len); ++ if (tmp_ra_buf->buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ free(tmp_ra_buf); ++ goto end; ++ } ++ (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); ++ tmp_ra_buf->len = in_buf_len; ++ ++ *in = tmp_ra_buf; ++end: ++ cJSON_free(in_buf); ++ cJSON_Delete(in_json); ++ return ret; ++} ++ ++/* caller need to free (cc_ra_buf_t **in) */ ++cc_enclave_result_t gen_ra_report_in_buff(gp_get_ra_report_input_t *param, cc_ra_buf_t **json_buf) ++{ ++ cc_enclave_result_t ret = CC_SUCCESS; ++ cJSON *in_json = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_json, "handler", "report-input"); ++ ++ char b64_nonce[MAX_NONCE_BUF_LEN] = {0}; ++ int b64_nonce_len = MAX_NONCE_BUF_LEN; ++ base64urlencode(param->nonce, param->nonce_len, (uint8_t *)b64_nonce, &b64_nonce_len); ++ print_debug("nonce_buf_len:%d, nonce_buf:%s\n", b64_nonce_len, b64_nonce); ++ ++ cJSON *in_payload = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); ++ cJSON_AddStringToObject(in_payload, "nonce", b64_nonce); ++ cJSON_AddStringToObject(in_payload, "uuid", (char *)param->uuid); ++ cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); ++ cJSON_AddBoolToObject(in_payload, "with_tcb", param->with_tcb); ++ ++ cJSON_AddItemToObject(in_json, "payload", in_payload); ++ ++ // char *in_buf = cJSON_PrintUnformatted(in_json); ++ char *in_buf = cJSON_Print(in_json); ++ uint32_t in_buf_len = strlen(in_buf) + 1; ++ ++ print_debug("get ra report input json buf:%s\n", in_buf); ++ ++ cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); ++ if (tmp_ra_buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ goto end; ++ } ++ tmp_ra_buf->buf = calloc(1, in_buf_len); ++ if (tmp_ra_buf->buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ free(tmp_ra_buf); ++ goto end; ++ } ++ (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); ++ tmp_ra_buf->len = in_buf_len; ++ ++ *json_buf = (cc_ra_buf_t *)tmp_ra_buf; ++end: ++ cJSON_free(in_buf); ++ cJSON_Delete(in_json); ++ return ret; ++} ++ ++void print_ra_report(cc_ra_buf_t *report) ++{ ++ cJSON *cj_report = cJSON_ParseWithLength((char *)report->buf, report->len); ++ if (cj_report == NULL) { ++ print_debug("cjson parse report error!\n"); ++ return; ++ } ++ char *str_report = cJSON_Print(cj_report); ++ ++ print_debug("report:%s\n", str_report); ++ ++ cJSON_free(str_report); ++ cJSON_Delete(cj_report); ++ return; ++} ++ ++ ++ +diff --git a/component/remote_attest/ra_report/gp_ra_helper.h b/component/remote_attest/ra_report/gp_ra_helper.h +new file mode 100644 +index 0000000..6bee143 +--- /dev/null ++++ b/component/remote_attest/ra_report/gp_ra_helper.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_RA_HELPER_H ++#define SECGEAR_RA_HELPER_H ++ ++#include ++#include ++#include "status.h" ++#include "sg_report_st.h" ++ ++#define MAX_NONCE_BUF_LEN 512 ++typedef struct { ++ uint8_t *uuid; ++ uint32_t nonce_len; ++ uint8_t nonce[MAX_NONCE_BUF_LEN]; ++ bool with_tcb; ++} gp_get_ra_report_input_t; ++ ++cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in); ++cc_enclave_result_t gen_ra_report_in_buff(gp_get_ra_report_input_t *param, cc_ra_buf_t **json_buf); ++void print_ra_report(cc_ra_buf_t *report); ++void free_gp_ra_buf(cc_ra_buf_t *ra_buf); ++#endif ++ +diff --git a/component/remote_attest/ra_report/gp_ra_report.c b/component/remote_attest/ra_report/gp_ra_report.c +new file mode 100644 +index 0000000..dd02d7d +--- /dev/null ++++ b/component/remote_attest/ra_report/gp_ra_report.c +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#include "gp_ra_report.h" ++ ++#include ++#include "gp_ra_helper.h" ++#include "ra_client_api.h" ++#include "enclave_log.h" ++ ++#define TEST_REPORT_OUT_LEN 0x3000 ++cc_enclave_result_t gp_ra_provision_no_as() ++{ ++ cc_ra_buf_t *in = NULL; ++ cc_enclave_result_t ret; ++ ++ ret = gen_provision_no_as_in_buff(&in); ++ if (ret != CC_SUCCESS) { ++ return ret; ++ } ++ uint8_t data[TEST_REPORT_OUT_LEN] = {0}; ++ cc_ra_buf_t report = {TEST_REPORT_OUT_LEN, data}; ++ ++ TEEC_Result gp_ret = RemoteAttest((struct ra_buffer_data *)in, (struct ra_buffer_data *)&report); ++ free_gp_ra_buf(in); ++ ++ if (gp_ret != TEEC_SUCCESS) { ++ print_error_term("gp ra provision no as failed ret:%x\n", gp_ret); ++ return CC_ERROR_RA_PROVISION_NO_AS; ++ } ++ ++ return CC_SUCCESS; ++} ++ ++cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario) ++{ ++ cc_enclave_result_t ret = CC_SUCCESS; ++ switch(scenario) { ++ case CC_RA_SCENARIO_NO_AS: ++ ret = gp_ra_provision_no_as(); ++ break; ++ default: ++ return CC_ERROR_RA_PRE_ENV_INVALID_SCENARIO; ++ } ++ return ret; ++} ++ ++cc_enclave_result_t gp_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report) ++{ ++ TEEC_Result gp_ret = RemoteAttest((struct ra_buffer_data *)in, (struct ra_buffer_data *)report); ++ if (gp_ret != TEEC_SUCCESS) { ++ print_error_term("get ra report failed, ret:%x\n", gp_ret); ++ return CC_ERROR_RA_GET_REPORT; ++ } ++ ++ return CC_SUCCESS; ++} ++ ++ ++ +diff --git a/component/remote_attest/ra_report/gp_ra_report.h b/component/remote_attest/ra_report/gp_ra_report.h +new file mode 100644 +index 0000000..9d02ce3 +--- /dev/null ++++ b/component/remote_attest/ra_report/gp_ra_report.h +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_GP_RA_REPORT_H ++#define SECGEAR_GP_RA_REPORT_H ++ ++#include "status.h" ++#include "sg_report_st.h" ++ ++cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario); ++ ++cc_enclave_result_t gp_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report); ++ ++#endif ++ +diff --git a/component/remote_attest/ra_report/sg_ra_report.c b/component/remote_attest/ra_report/sg_ra_report.c +new file mode 100644 +index 0000000..1cc4bdc +--- /dev/null ++++ b/component/remote_attest/ra_report/sg_ra_report.c +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#include "gp_ra_report.h" ++ ++cc_enclave_result_t cc_prepare_ra_env(cc_ra_scenario_t scenario) ++{ ++ return gp_prepare_ra_env(scenario); ++} ++ ++cc_enclave_result_t cc_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report) ++{ ++ return gp_get_ra_report(in, report); ++} ++ ++ ++ +diff --git a/component/remote_attest/ra_report/sg_ra_report.h b/component/remote_attest/ra_report/sg_ra_report.h +new file mode 100644 +index 0000000..960cb02 +--- /dev/null ++++ b/component/remote_attest/ra_report/sg_ra_report.h +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_REMOTE_REPORT_H ++#define SECGEAR_REMOTE_REPORT_H ++ ++#include ++#include "status.h" ++#include "secgear_defs.h" ++#include "sg_report_st.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++CC_API_SPEC cc_enclave_result_t cc_prepare_ra_env(cc_ra_scenario_t scenario); ++ ++CC_API_SPEC cc_enclave_result_t cc_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report); ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/component/remote_attest/ra_verify/CMakeLists.txt b/component/remote_attest/ra_verify/CMakeLists.txt +new file mode 100644 +index 0000000..fc92d9c +--- /dev/null ++++ b/component/remote_attest/ra_verify/CMakeLists.txt +@@ -0,0 +1,44 @@ ++# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++# secGear is licensed under the Mulan PSL v2. ++# You can use this software according to the terms and conditions of the Mulan PSL v2. ++# You may obtain a copy of Mulan PSL v2 at: ++# http://license.coscl.org.cn/MulanPSL2 ++# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# PURPOSE. ++# See the Mulan PSL v2 for more details. ++ ++project(sg_ra_verify C) ++ ++set(TARGET secgear_verify) ++aux_source_directory(. SRC_FILES) ++ ++set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") ++ ++if(${CMAKE_VERSION} VERSION_LESS "3.13.0") ++ link_directories(/usr/lib64) ++endif() ++ ++include_directories( ++ ${CMAKE_CURRENT_BINARY_DIR} ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ${CMAKE_CURRENT_SOURCE_DIR}/.. ++ ${LOCAL_ROOT_PATH}/inc/host_inc ++ ${LOCAL_ROOT_PATH}/thirdparty/kunpengsecl/verifier ++) ++add_library(${TARGET} SHARED ${SRC_FILES}) ++ ++if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") ++ target_link_directories(${TARGET} PRIVATE /usr/lib64) ++endif() ++ ++target_link_libraries(${TARGET}) ++ ++set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) ++ ++install(TARGETS ${TARGET} ++ LIBRARY ++ DESTINATION ${LIBRARY_INSTALL} ++ PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) ++ ++ +diff --git a/component/remote_attest/ra_verify/gp_ra_report_verify.c b/component/remote_attest/ra_verify/gp_ra_report_verify.c +new file mode 100644 +index 0000000..0917f7a +--- /dev/null ++++ b/component/remote_attest/ra_verify/gp_ra_report_verify.c +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#include "gp_ra_report_verify.h" ++ ++#include "teeverifier.h" ++#include "enclave_log.h" ++ ++int convert_cctype_to_gptype(cc_ra_verify_type_t type) ++{ ++ // gp type, 1: compare image hash; 2: compare mem hash; 3: compare image and mem hash ++ if (type == CC_RA_VERIFY_TYPE_LOOSE) { ++ return 1; ++ } else if (type == CC_RA_VERIFY_TYPE_STRICT) { ++ return 3; ++ } else { ++ return CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE; ++ } ++} ++ ++cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue) ++{ ++ int gp_type = convert_cctype_to_gptype(type); ++ if (gp_type == (int)CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE) { ++ return CC_FAIL; ++ } ++ int ret = tee_verify_report((buffer_data *)report, (buffer_data *)nonce, gp_type, basevalue); ++ switch (ret) { ++ case TVS_ALL_SUCCESSED: ++ return CC_SUCCESS; ++ case TVS_VERIFIED_NONCE_FAILED: ++ return CC_ERROR_RA_REPORT_VERIFY_NONCE; ++ case TVS_VERIFIED_SIGNATURE_FAILED: ++ return CC_ERROR_RA_REPORT_VERIFY_SIGNATURE; ++ case TVS_VERIFIED_HASH_FAILED: ++ return CC_ERROR_RA_REPORT_VERIFY_HASH; ++ default: ++ print_debug("verify report failed, unknown errorcode:%d!\n", ret); ++ } ++ return ret; ++} +\ No newline at end of file +diff --git a/component/remote_attest/ra_verify/gp_ra_report_verify.h b/component/remote_attest/ra_verify/gp_ra_report_verify.h +new file mode 100644 +index 0000000..ffd8387 +--- /dev/null ++++ b/component/remote_attest/ra_verify/gp_ra_report_verify.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_GP_VERIFY_REPORT_H ++#define SECGEAR_GP_VERIFY_REPORT_H ++ ++#include "status.h" ++#include "secgear_defs.h" ++#include "sg_report_st.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++CC_API_SPEC cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/component/remote_attest/ra_verify/sg_ra_report_verify.c b/component/remote_attest/ra_verify/sg_ra_report_verify.c +new file mode 100644 +index 0000000..63f26c4 +--- /dev/null ++++ b/component/remote_attest/ra_verify/sg_ra_report_verify.c +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#include "gp_ra_report_verify.h" ++ ++#include "enclave_log.h" ++ ++cc_enclave_result_t cc_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue) ++{ ++ return gp_verify_report(report, nonce, type, basevalue); ++} +\ No newline at end of file +diff --git a/component/remote_attest/ra_verify/sg_ra_report_verify.h b/component/remote_attest/ra_verify/sg_ra_report_verify.h +new file mode 100644 +index 0000000..92ca953 +--- /dev/null ++++ b/component/remote_attest/ra_verify/sg_ra_report_verify.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_VERIFY_REPORT_H ++#define SECGEAR_VERIFY_REPORT_H ++ ++#include "status.h" ++#include "secgear_defs.h" ++#include "sg_report_st.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++CC_API_SPEC cc_enclave_result_t cc_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/component/remote_attest/sg_report_st.h b/component/remote_attest/sg_report_st.h +new file mode 100644 +index 0000000..89ee25a +--- /dev/null ++++ b/component/remote_attest/sg_report_st.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_REPORT_STRUCT_H ++#define SECGEAR_REPORT_STRUCT_H ++ ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef struct cc_ra_buf { ++ uint32_t len; ++ uint8_t *buf; ++} cc_ra_buf_t; ++ ++typedef enum { ++ CC_RA_SCENARIO_NO_AS, ++ // CC_RA_SCENARIO_AS_NO_DAA, ++ // CC_RA_SCENARIO_AS_WITH_DAA ++} cc_ra_scenario_t; ++ ++typedef enum { ++ CC_RA_VERIFY_TYPE_LOOSE, ++ CC_RA_VERIFY_TYPE_STRICT, ++ CC_RA_VERIFY_TYPE_MAX ++} cc_ra_verify_type_t; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/inc/host_inc/status.h b/inc/host_inc/status.h +index 40e9f1c..ea7b93b 100644 +--- a/inc/host_inc/status.h ++++ b/inc/host_inc/status.h +@@ -78,6 +78,14 @@ typedef enum _enclave_result_t + CC_ERROR_ATT_KEY_UNINITIALIZED, /* attestation key is not initialized*/ + CC_ERROR_INVALID_ATT_KEY_CERT_DATA, /* attestation data is not valid*/ + CC_ERROR_PLATFORM_CERT_UNAVAILABLE, /* cert is not available*/ ++ CC_ERROR_RA_PRE_ENV_INVALID_SCENARIO, ++ CC_ERROR_RA_MEMORY, ++ CC_ERROR_RA_PROVISION_NO_AS, ++ CC_ERROR_RA_GET_REPORT, ++ CC_ERROR_RA_REPORT_VERIFY_NONCE, ++ CC_ERROR_RA_REPORT_VERIFY_SIGNATURE, ++ CC_ERROR_RA_REPORT_VERIFY_HASH, ++ CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE, + /* secure channel */ + CC_ERROR_SEC_CHL_INVALID_CONN, /* invalid connection */ + CC_ERROR_SEC_CHL_LEN_NOT_ENOUGH, /* the buf length to store secure channle encrypt/decrypt is not enough */ +diff --git a/thirdparty/cjson/cJSON.bak b/thirdparty/cjson/cJSON.bak +new file mode 100644 +index 0000000..3063f74 +--- /dev/null ++++ b/thirdparty/cjson/cJSON.bak +@@ -0,0 +1,3110 @@ ++/* ++ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors ++ ++ Permission is hereby granted, free of charge, to any person obtaining a copy ++ of this software and associated documentation files (the "Software"), to deal ++ in the Software without restriction, including without limitation the rights ++ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ copies of the Software, and to permit persons to whom the Software is ++ furnished to do so, subject to the following conditions: ++ ++ The above copyright notice and this permission notice shall be included in ++ all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ THE SOFTWARE. ++*/ ++ ++/* cJSON */ ++/* JSON parser in C. */ ++ ++/* disable warnings about old C89 functions in MSVC */ ++#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) ++#define _CRT_SECURE_NO_DEPRECATE ++#endif ++ ++#ifdef __GNUC__ ++#pragma GCC visibility push(default) ++#endif ++#if defined(_MSC_VER) ++#pragma warning (push) ++/* disable warning about single line comments in system headers */ ++#pragma warning (disable : 4001) ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifdef ENABLE_LOCALES ++#include ++#endif ++ ++#if defined(_MSC_VER) ++#pragma warning (pop) ++#endif ++#ifdef __GNUC__ ++#pragma GCC visibility pop ++#endif ++ ++#include "cJSON.h" ++ ++/* define our own boolean type */ ++#ifdef true ++#undef true ++#endif ++#define true ((cJSON_bool)1) ++ ++#ifdef false ++#undef false ++#endif ++#define false ((cJSON_bool)0) ++ ++/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ ++#ifndef isinf ++#define isinf(d) (isnan((d - d)) && !isnan(d)) ++#endif ++#ifndef isnan ++#define isnan(d) (d != d) ++#endif ++ ++#ifndef NAN ++#ifdef _WIN32 ++#define NAN sqrt(-1.0) ++#else ++#define NAN 0.0/0.0 ++#endif ++#endif ++ ++typedef struct { ++ const unsigned char *json; ++ size_t position; ++} error; ++static error global_error = { NULL, 0 }; ++ ++CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) ++{ ++ return (const char*) (global_error.json + global_error.position); ++} ++ ++CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) ++{ ++ if (!cJSON_IsString(item)) ++ { ++ return NULL; ++ } ++ ++ return item->valuestring; ++} ++ ++CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) ++{ ++ if (!cJSON_IsNumber(item)) ++ { ++ return (double) NAN; ++ } ++ ++ return item->valuedouble; ++} ++ ++/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ ++#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 15) ++ #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. ++#endif ++ ++CJSON_PUBLIC(const char*) cJSON_Version(void) ++{ ++ static char version[15]; ++ sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); ++ ++ return version; ++} ++ ++/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ ++static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) ++{ ++ if ((string1 == NULL) || (string2 == NULL)) ++ { ++ return 1; ++ } ++ ++ if (string1 == string2) ++ { ++ return 0; ++ } ++ ++ for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) ++ { ++ if (*string1 == '\0') ++ { ++ return 0; ++ } ++ } ++ ++ return tolower(*string1) - tolower(*string2); ++} ++ ++typedef struct internal_hooks ++{ ++ void *(CJSON_CDECL *allocate)(size_t size); ++ void (CJSON_CDECL *deallocate)(void *pointer); ++ void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); ++} internal_hooks; ++ ++#if defined(_MSC_VER) ++/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ ++static void * CJSON_CDECL internal_malloc(size_t size) ++{ ++ return malloc(size); ++} ++static void CJSON_CDECL internal_free(void *pointer) ++{ ++ free(pointer); ++} ++static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) ++{ ++ return realloc(pointer, size); ++} ++#else ++#define internal_malloc malloc ++#define internal_free free ++#define internal_realloc realloc ++#endif ++ ++/* strlen of character literals resolved at compile time */ ++#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) ++ ++static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; ++ ++static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) ++{ ++ size_t length = 0; ++ unsigned char *copy = NULL; ++ ++ if (string == NULL) ++ { ++ return NULL; ++ } ++ ++ length = strlen((const char*)string) + sizeof(""); ++ copy = (unsigned char*)hooks->allocate(length); ++ if (copy == NULL) ++ { ++ return NULL; ++ } ++ memcpy(copy, string, length); ++ ++ return copy; ++} ++ ++CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) ++{ ++ if (hooks == NULL) ++ { ++ /* Reset hooks */ ++ global_hooks.allocate = malloc; ++ global_hooks.deallocate = free; ++ global_hooks.reallocate = realloc; ++ return; ++ } ++ ++ global_hooks.allocate = malloc; ++ if (hooks->malloc_fn != NULL) ++ { ++ global_hooks.allocate = hooks->malloc_fn; ++ } ++ ++ global_hooks.deallocate = free; ++ if (hooks->free_fn != NULL) ++ { ++ global_hooks.deallocate = hooks->free_fn; ++ } ++ ++ /* use realloc only if both free and malloc are used */ ++ global_hooks.reallocate = NULL; ++ if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) ++ { ++ global_hooks.reallocate = realloc; ++ } ++} ++ ++/* Internal constructor. */ ++static cJSON *cJSON_New_Item(const internal_hooks * const hooks) ++{ ++ cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); ++ if (node) ++ { ++ memset(node, '\0', sizeof(cJSON)); ++ } ++ ++ return node; ++} ++ ++/* Delete a cJSON structure. */ ++CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) ++{ ++ cJSON *next = NULL; ++ while (item != NULL) ++ { ++ next = item->next; ++ if (!(item->type & cJSON_IsReference) && (item->child != NULL)) ++ { ++ cJSON_Delete(item->child); ++ } ++ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) ++ { ++ global_hooks.deallocate(item->valuestring); ++ } ++ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) ++ { ++ global_hooks.deallocate(item->string); ++ } ++ global_hooks.deallocate(item); ++ item = next; ++ } ++} ++ ++/* get the decimal point character of the current locale */ ++static unsigned char get_decimal_point(void) ++{ ++#ifdef ENABLE_LOCALES ++ struct lconv *lconv = localeconv(); ++ return (unsigned char) lconv->decimal_point[0]; ++#else ++ return '.'; ++#endif ++} ++ ++typedef struct ++{ ++ const unsigned char *content; ++ size_t length; ++ size_t offset; ++ size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ ++ internal_hooks hooks; ++} parse_buffer; ++ ++/* check if the given size is left to read in a given parse buffer (starting with 1) */ ++#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) ++/* check if the buffer can be accessed at the given index (starting with 0) */ ++#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) ++#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) ++/* get a pointer to the buffer at the position */ ++#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) ++ ++/* Parse the input text to generate a number, and populate the result into item. */ ++static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) ++{ ++ double number = 0; ++ unsigned char *after_end = NULL; ++ unsigned char number_c_string[64]; ++ unsigned char decimal_point = get_decimal_point(); ++ size_t i = 0; ++ ++ if ((input_buffer == NULL) || (input_buffer->content == NULL)) ++ { ++ return false; ++ } ++ ++ /* copy the number into a temporary buffer and replace '.' with the decimal point ++ * of the current locale (for strtod) ++ * This also takes care of '\0' not necessarily being available for marking the end of the input */ ++ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++) ++ { ++ switch (buffer_at_offset(input_buffer)[i]) ++ { ++ case '0': ++ case '1': ++ case '2': ++ case '3': ++ case '4': ++ case '5': ++ case '6': ++ case '7': ++ case '8': ++ case '9': ++ case '+': ++ case '-': ++ case 'e': ++ case 'E': ++ number_c_string[i] = buffer_at_offset(input_buffer)[i]; ++ break; ++ ++ case '.': ++ number_c_string[i] = decimal_point; ++ break; ++ ++ default: ++ goto loop_end; ++ } ++ } ++loop_end: ++ number_c_string[i] = '\0'; ++ ++ number = strtod((const char*)number_c_string, (char**)&after_end); ++ if (number_c_string == after_end) ++ { ++ return false; /* parse_error */ ++ } ++ ++ item->valuedouble = number; ++ ++ /* use saturation in case of overflow */ ++ if (number >= INT_MAX) ++ { ++ item->valueint = INT_MAX; ++ } ++ else if (number <= (double)INT_MIN) ++ { ++ item->valueint = INT_MIN; ++ } ++ else ++ { ++ item->valueint = (int)number; ++ } ++ ++ item->type = cJSON_Number; ++ ++ input_buffer->offset += (size_t)(after_end - number_c_string); ++ return true; ++} ++ ++/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ ++CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) ++{ ++ if (number >= INT_MAX) ++ { ++ object->valueint = INT_MAX; ++ } ++ else if (number <= (double)INT_MIN) ++ { ++ object->valueint = INT_MIN; ++ } ++ else ++ { ++ object->valueint = (int)number; ++ } ++ ++ return object->valuedouble = number; ++} ++ ++CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) ++{ ++ char *copy = NULL; ++ /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ ++ if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference)) ++ { ++ return NULL; ++ } ++ if (strlen(valuestring) <= strlen(object->valuestring)) ++ { ++ strcpy(object->valuestring, valuestring); ++ return object->valuestring; ++ } ++ copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); ++ if (copy == NULL) ++ { ++ return NULL; ++ } ++ if (object->valuestring != NULL) ++ { ++ cJSON_free(object->valuestring); ++ } ++ object->valuestring = copy; ++ ++ return copy; ++} ++ ++typedef struct ++{ ++ unsigned char *buffer; ++ size_t length; ++ size_t offset; ++ size_t depth; /* current nesting depth (for formatted printing) */ ++ cJSON_bool noalloc; ++ cJSON_bool format; /* is this print a formatted print */ ++ internal_hooks hooks; ++} printbuffer; ++ ++/* realloc printbuffer if necessary to have at least "needed" bytes more */ ++static unsigned char* ensure(printbuffer * const p, size_t needed) ++{ ++ unsigned char *newbuffer = NULL; ++ size_t newsize = 0; ++ ++ if ((p == NULL) || (p->buffer == NULL)) ++ { ++ return NULL; ++ } ++ ++ if ((p->length > 0) && (p->offset >= p->length)) ++ { ++ /* make sure that offset is valid */ ++ return NULL; ++ } ++ ++ if (needed > INT_MAX) ++ { ++ /* sizes bigger than INT_MAX are currently not supported */ ++ return NULL; ++ } ++ ++ needed += p->offset + 1; ++ if (needed <= p->length) ++ { ++ return p->buffer + p->offset; ++ } ++ ++ if (p->noalloc) { ++ return NULL; ++ } ++ ++ /* calculate new buffer size */ ++ if (needed > (INT_MAX / 2)) ++ { ++ /* overflow of int, use INT_MAX if possible */ ++ if (needed <= INT_MAX) ++ { ++ newsize = INT_MAX; ++ } ++ else ++ { ++ return NULL; ++ } ++ } ++ else ++ { ++ newsize = needed * 2; ++ } ++ ++ if (p->hooks.reallocate != NULL) ++ { ++ /* reallocate with realloc if available */ ++ newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); ++ if (newbuffer == NULL) ++ { ++ p->hooks.deallocate(p->buffer); ++ p->length = 0; ++ p->buffer = NULL; ++ ++ return NULL; ++ } ++ } ++ else ++ { ++ /* otherwise reallocate manually */ ++ newbuffer = (unsigned char*)p->hooks.allocate(newsize); ++ if (!newbuffer) ++ { ++ p->hooks.deallocate(p->buffer); ++ p->length = 0; ++ p->buffer = NULL; ++ ++ return NULL; ++ } ++ ++ memcpy(newbuffer, p->buffer, p->offset + 1); ++ p->hooks.deallocate(p->buffer); ++ } ++ p->length = newsize; ++ p->buffer = newbuffer; ++ ++ return newbuffer + p->offset; ++} ++ ++/* calculate the new length of the string in a printbuffer and update the offset */ ++static void update_offset(printbuffer * const buffer) ++{ ++ const unsigned char *buffer_pointer = NULL; ++ if ((buffer == NULL) || (buffer->buffer == NULL)) ++ { ++ return; ++ } ++ buffer_pointer = buffer->buffer + buffer->offset; ++ ++ buffer->offset += strlen((const char*)buffer_pointer); ++} ++ ++/* securely comparison of floating-point variables */ ++static cJSON_bool compare_double(double a, double b) ++{ ++ double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); ++ return (fabs(a - b) <= maxVal * DBL_EPSILON); ++} ++ ++/* Render the number nicely from the given item into a string. */ ++static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) ++{ ++ unsigned char *output_pointer = NULL; ++ double d = item->valuedouble; ++ int length = 0; ++ size_t i = 0; ++ unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ ++ unsigned char decimal_point = get_decimal_point(); ++ double test = 0.0; ++ ++ if (output_buffer == NULL) ++ { ++ return false; ++ } ++ ++ /* This checks for NaN and Infinity */ ++ if (isnan(d) || isinf(d)) ++ { ++ length = sprintf((char*)number_buffer, "null"); ++ } ++ else ++ { ++ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ ++ length = sprintf((char*)number_buffer, "%1.15g", d); ++ ++ /* Check whether the original double can be recovered */ ++ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) ++ { ++ /* If not, print with 17 decimal places of precision */ ++ length = sprintf((char*)number_buffer, "%1.17g", d); ++ } ++ } ++ ++ /* sprintf failed or buffer overrun occurred */ ++ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) ++ { ++ return false; ++ } ++ ++ /* reserve appropriate space in the output */ ++ output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); ++ if (output_pointer == NULL) ++ { ++ return false; ++ } ++ ++ /* copy the printed number to the output and replace locale ++ * dependent decimal point with '.' */ ++ for (i = 0; i < ((size_t)length); i++) ++ { ++ if (number_buffer[i] == decimal_point) ++ { ++ output_pointer[i] = '.'; ++ continue; ++ } ++ ++ output_pointer[i] = number_buffer[i]; ++ } ++ output_pointer[i] = '\0'; ++ ++ output_buffer->offset += (size_t)length; ++ ++ return true; ++} ++ ++/* parse 4 digit hexadecimal number */ ++static unsigned parse_hex4(const unsigned char * const input) ++{ ++ unsigned int h = 0; ++ size_t i = 0; ++ ++ for (i = 0; i < 4; i++) ++ { ++ /* parse digit */ ++ if ((input[i] >= '0') && (input[i] <= '9')) ++ { ++ h += (unsigned int) input[i] - '0'; ++ } ++ else if ((input[i] >= 'A') && (input[i] <= 'F')) ++ { ++ h += (unsigned int) 10 + input[i] - 'A'; ++ } ++ else if ((input[i] >= 'a') && (input[i] <= 'f')) ++ { ++ h += (unsigned int) 10 + input[i] - 'a'; ++ } ++ else /* invalid */ ++ { ++ return 0; ++ } ++ ++ if (i < 3) ++ { ++ /* shift left to make place for the next nibble */ ++ h = h << 4; ++ } ++ } ++ ++ return h; ++} ++ ++/* converts a UTF-16 literal to UTF-8 ++ * A literal can be one or two sequences of the form \uXXXX */ ++static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) ++{ ++ long unsigned int codepoint = 0; ++ unsigned int first_code = 0; ++ const unsigned char *first_sequence = input_pointer; ++ unsigned char utf8_length = 0; ++ unsigned char utf8_position = 0; ++ unsigned char sequence_length = 0; ++ unsigned char first_byte_mark = 0; ++ ++ if ((input_end - first_sequence) < 6) ++ { ++ /* input ends unexpectedly */ ++ goto fail; ++ } ++ ++ /* get the first utf16 sequence */ ++ first_code = parse_hex4(first_sequence + 2); ++ ++ /* check that the code is valid */ ++ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) ++ { ++ goto fail; ++ } ++ ++ /* UTF16 surrogate pair */ ++ if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) ++ { ++ const unsigned char *second_sequence = first_sequence + 6; ++ unsigned int second_code = 0; ++ sequence_length = 12; /* \uXXXX\uXXXX */ ++ ++ if ((input_end - second_sequence) < 6) ++ { ++ /* input ends unexpectedly */ ++ goto fail; ++ } ++ ++ if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) ++ { ++ /* missing second half of the surrogate pair */ ++ goto fail; ++ } ++ ++ /* get the second utf16 sequence */ ++ second_code = parse_hex4(second_sequence + 2); ++ /* check that the code is valid */ ++ if ((second_code < 0xDC00) || (second_code > 0xDFFF)) ++ { ++ /* invalid second half of the surrogate pair */ ++ goto fail; ++ } ++ ++ ++ /* calculate the unicode codepoint from the surrogate pair */ ++ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); ++ } ++ else ++ { ++ sequence_length = 6; /* \uXXXX */ ++ codepoint = first_code; ++ } ++ ++ /* encode as UTF-8 ++ * takes at maximum 4 bytes to encode: ++ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ ++ if (codepoint < 0x80) ++ { ++ /* normal ascii, encoding 0xxxxxxx */ ++ utf8_length = 1; ++ } ++ else if (codepoint < 0x800) ++ { ++ /* two bytes, encoding 110xxxxx 10xxxxxx */ ++ utf8_length = 2; ++ first_byte_mark = 0xC0; /* 11000000 */ ++ } ++ else if (codepoint < 0x10000) ++ { ++ /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ ++ utf8_length = 3; ++ first_byte_mark = 0xE0; /* 11100000 */ ++ } ++ else if (codepoint <= 0x10FFFF) ++ { ++ /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ ++ utf8_length = 4; ++ first_byte_mark = 0xF0; /* 11110000 */ ++ } ++ else ++ { ++ /* invalid unicode codepoint */ ++ goto fail; ++ } ++ ++ /* encode as utf8 */ ++ for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) ++ { ++ /* 10xxxxxx */ ++ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); ++ codepoint >>= 6; ++ } ++ /* encode first byte */ ++ if (utf8_length > 1) ++ { ++ (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); ++ } ++ else ++ { ++ (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); ++ } ++ ++ *output_pointer += utf8_length; ++ ++ return sequence_length; ++ ++fail: ++ return 0; ++} ++ ++/* Parse the input text into an unescaped cinput, and populate item. */ ++static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) ++{ ++ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; ++ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; ++ unsigned char *output_pointer = NULL; ++ unsigned char *output = NULL; ++ ++ /* not a string */ ++ if (buffer_at_offset(input_buffer)[0] != '\"') ++ { ++ goto fail; ++ } ++ ++ { ++ /* calculate approximate size of the output (overestimate) */ ++ size_t allocation_length = 0; ++ size_t skipped_bytes = 0; ++ while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) ++ { ++ /* is escape sequence */ ++ if (input_end[0] == '\\') ++ { ++ if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) ++ { ++ /* prevent buffer overflow when last input character is a backslash */ ++ goto fail; ++ } ++ skipped_bytes++; ++ input_end++; ++ } ++ input_end++; ++ } ++ if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) ++ { ++ goto fail; /* string ended unexpectedly */ ++ } ++ ++ /* This is at most how much we need for the output */ ++ allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; ++ output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); ++ if (output == NULL) ++ { ++ goto fail; /* allocation failure */ ++ } ++ } ++ ++ output_pointer = output; ++ /* loop through the string literal */ ++ while (input_pointer < input_end) ++ { ++ if (*input_pointer != '\\') ++ { ++ *output_pointer++ = *input_pointer++; ++ } ++ /* escape sequence */ ++ else ++ { ++ unsigned char sequence_length = 2; ++ if ((input_end - input_pointer) < 1) ++ { ++ goto fail; ++ } ++ ++ switch (input_pointer[1]) ++ { ++ case 'b': ++ *output_pointer++ = '\b'; ++ break; ++ case 'f': ++ *output_pointer++ = '\f'; ++ break; ++ case 'n': ++ *output_pointer++ = '\n'; ++ break; ++ case 'r': ++ *output_pointer++ = '\r'; ++ break; ++ case 't': ++ *output_pointer++ = '\t'; ++ break; ++ case '\"': ++ case '\\': ++ case '/': ++ *output_pointer++ = input_pointer[1]; ++ break; ++ ++ /* UTF-16 literal */ ++ case 'u': ++ sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); ++ if (sequence_length == 0) ++ { ++ /* failed to convert UTF16-literal to UTF-8 */ ++ goto fail; ++ } ++ break; ++ ++ default: ++ goto fail; ++ } ++ input_pointer += sequence_length; ++ } ++ } ++ ++ /* zero terminate the output */ ++ *output_pointer = '\0'; ++ ++ item->type = cJSON_String; ++ item->valuestring = (char*)output; ++ ++ input_buffer->offset = (size_t) (input_end - input_buffer->content); ++ input_buffer->offset++; ++ ++ return true; ++ ++fail: ++ if (output != NULL) ++ { ++ input_buffer->hooks.deallocate(output); ++ } ++ ++ if (input_pointer != NULL) ++ { ++ input_buffer->offset = (size_t)(input_pointer - input_buffer->content); ++ } ++ ++ return false; ++} ++ ++/* Render the cstring provided to an escaped version that can be printed. */ ++static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) ++{ ++ const unsigned char *input_pointer = NULL; ++ unsigned char *output = NULL; ++ unsigned char *output_pointer = NULL; ++ size_t output_length = 0; ++ /* numbers of additional characters needed for escaping */ ++ size_t escape_characters = 0; ++ ++ if (output_buffer == NULL) ++ { ++ return false; ++ } ++ ++ /* empty string */ ++ if (input == NULL) ++ { ++ output = ensure(output_buffer, sizeof("\"\"")); ++ if (output == NULL) ++ { ++ return false; ++ } ++ strcpy((char*)output, "\"\""); ++ ++ return true; ++ } ++ ++ /* set "flag" to 1 if something needs to be escaped */ ++ for (input_pointer = input; *input_pointer; input_pointer++) ++ { ++ switch (*input_pointer) ++ { ++ case '\"': ++ case '\\': ++ case '\b': ++ case '\f': ++ case '\n': ++ case '\r': ++ case '\t': ++ /* one character escape sequence */ ++ escape_characters++; ++ break; ++ default: ++ if (*input_pointer < 32) ++ { ++ /* UTF-16 escape sequence uXXXX */ ++ escape_characters += 5; ++ } ++ break; ++ } ++ } ++ output_length = (size_t)(input_pointer - input) + escape_characters; ++ ++ output = ensure(output_buffer, output_length + sizeof("\"\"")); ++ if (output == NULL) ++ { ++ return false; ++ } ++ ++ /* no characters have to be escaped */ ++ if (escape_characters == 0) ++ { ++ output[0] = '\"'; ++ memcpy(output + 1, input, output_length); ++ output[output_length + 1] = '\"'; ++ output[output_length + 2] = '\0'; ++ ++ return true; ++ } ++ ++ output[0] = '\"'; ++ output_pointer = output + 1; ++ /* copy the string */ ++ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) ++ { ++ if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) ++ { ++ /* normal character, copy */ ++ *output_pointer = *input_pointer; ++ } ++ else ++ { ++ /* character needs to be escaped */ ++ *output_pointer++ = '\\'; ++ switch (*input_pointer) ++ { ++ case '\\': ++ *output_pointer = '\\'; ++ break; ++ case '\"': ++ *output_pointer = '\"'; ++ break; ++ case '\b': ++ *output_pointer = 'b'; ++ break; ++ case '\f': ++ *output_pointer = 'f'; ++ break; ++ case '\n': ++ *output_pointer = 'n'; ++ break; ++ case '\r': ++ *output_pointer = 'r'; ++ break; ++ case '\t': ++ *output_pointer = 't'; ++ break; ++ default: ++ /* escape and print as unicode codepoint */ ++ sprintf((char*)output_pointer, "u%04x", *input_pointer); ++ output_pointer += 4; ++ break; ++ } ++ } ++ } ++ output[output_length + 1] = '\"'; ++ output[output_length + 2] = '\0'; ++ ++ return true; ++} ++ ++/* Invoke print_string_ptr (which is useful) on an item. */ ++static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) ++{ ++ return print_string_ptr((unsigned char*)item->valuestring, p); ++} ++ ++/* Predeclare these prototypes. */ ++static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); ++static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); ++static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); ++static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); ++static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); ++static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); ++ ++/* Utility to jump whitespace and cr/lf */ ++static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) ++{ ++ if ((buffer == NULL) || (buffer->content == NULL)) ++ { ++ return NULL; ++ } ++ ++ if (cannot_access_at_index(buffer, 0)) ++ { ++ return buffer; ++ } ++ ++ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) ++ { ++ buffer->offset++; ++ } ++ ++ if (buffer->offset == buffer->length) ++ { ++ buffer->offset--; ++ } ++ ++ return buffer; ++} ++ ++/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ ++static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) ++{ ++ if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) ++ { ++ return NULL; ++ } ++ ++ if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) ++ { ++ buffer->offset += 3; ++ } ++ ++ return buffer; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) ++{ ++ size_t buffer_length; ++ ++ if (NULL == value) ++ { ++ return NULL; ++ } ++ ++ /* Adding null character size due to require_null_terminated. */ ++ buffer_length = strlen(value) + sizeof(""); ++ ++ return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); ++} ++ ++/* Parse an object - create a new root, and populate. */ ++CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) ++{ ++ parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; ++ cJSON *item = NULL; ++ ++ /* reset error position */ ++ global_error.json = NULL; ++ global_error.position = 0; ++ ++ if (value == NULL || 0 == buffer_length) ++ { ++ goto fail; ++ } ++ ++ buffer.content = (const unsigned char*)value; ++ buffer.length = buffer_length; ++ buffer.offset = 0; ++ buffer.hooks = global_hooks; ++ ++ item = cJSON_New_Item(&global_hooks); ++ if (item == NULL) /* memory fail */ ++ { ++ goto fail; ++ } ++ ++ if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) ++ { ++ /* parse failure. ep is set. */ ++ goto fail; ++ } ++ ++ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ ++ if (require_null_terminated) ++ { ++ buffer_skip_whitespace(&buffer); ++ if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') ++ { ++ goto fail; ++ } ++ } ++ if (return_parse_end) ++ { ++ *return_parse_end = (const char*)buffer_at_offset(&buffer); ++ } ++ ++ return item; ++ ++fail: ++ if (item != NULL) ++ { ++ cJSON_Delete(item); ++ } ++ ++ if (value != NULL) ++ { ++ error local_error; ++ local_error.json = (const unsigned char*)value; ++ local_error.position = 0; ++ ++ if (buffer.offset < buffer.length) ++ { ++ local_error.position = buffer.offset; ++ } ++ else if (buffer.length > 0) ++ { ++ local_error.position = buffer.length - 1; ++ } ++ ++ if (return_parse_end != NULL) ++ { ++ *return_parse_end = (const char*)local_error.json + local_error.position; ++ } ++ ++ global_error = local_error; ++ } ++ ++ return NULL; ++} ++ ++/* Default options for cJSON_Parse */ ++CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) ++{ ++ return cJSON_ParseWithOpts(value, 0, 0); ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) ++{ ++ return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); ++} ++ ++#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) ++ ++static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) ++{ ++ static const size_t default_buffer_size = 256; ++ printbuffer buffer[1]; ++ unsigned char *printed = NULL; ++ ++ memset(buffer, 0, sizeof(buffer)); ++ ++ /* create buffer */ ++ buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); ++ buffer->length = default_buffer_size; ++ buffer->format = format; ++ buffer->hooks = *hooks; ++ if (buffer->buffer == NULL) ++ { ++ goto fail; ++ } ++ ++ /* print the value */ ++ if (!print_value(item, buffer)) ++ { ++ goto fail; ++ } ++ update_offset(buffer); ++ ++ /* check if reallocate is available */ ++ if (hooks->reallocate != NULL) ++ { ++ printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); ++ if (printed == NULL) { ++ goto fail; ++ } ++ buffer->buffer = NULL; ++ } ++ else /* otherwise copy the JSON over to a new buffer */ ++ { ++ printed = (unsigned char*) hooks->allocate(buffer->offset + 1); ++ if (printed == NULL) ++ { ++ goto fail; ++ } ++ memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); ++ printed[buffer->offset] = '\0'; /* just to be sure */ ++ ++ /* free the buffer */ ++ hooks->deallocate(buffer->buffer); ++ } ++ ++ return printed; ++ ++fail: ++ if (buffer->buffer != NULL) ++ { ++ hooks->deallocate(buffer->buffer); ++ } ++ ++ if (printed != NULL) ++ { ++ hooks->deallocate(printed); ++ } ++ ++ return NULL; ++} ++ ++/* Render a cJSON item/entity/structure to text. */ ++CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) ++{ ++ return (char*)print(item, true, &global_hooks); ++} ++ ++CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) ++{ ++ return (char*)print(item, false, &global_hooks); ++} ++ ++CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) ++{ ++ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; ++ ++ if (prebuffer < 0) ++ { ++ return NULL; ++ } ++ ++ p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); ++ if (!p.buffer) ++ { ++ return NULL; ++ } ++ ++ p.length = (size_t)prebuffer; ++ p.offset = 0; ++ p.noalloc = false; ++ p.format = fmt; ++ p.hooks = global_hooks; ++ ++ if (!print_value(item, &p)) ++ { ++ global_hooks.deallocate(p.buffer); ++ return NULL; ++ } ++ ++ return (char*)p.buffer; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) ++{ ++ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; ++ ++ if ((length < 0) || (buffer == NULL)) ++ { ++ return false; ++ } ++ ++ p.buffer = (unsigned char*)buffer; ++ p.length = (size_t)length; ++ p.offset = 0; ++ p.noalloc = true; ++ p.format = format; ++ p.hooks = global_hooks; ++ ++ return print_value(item, &p); ++} ++ ++/* Parser core - when encountering text, process appropriately. */ ++static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) ++{ ++ if ((input_buffer == NULL) || (input_buffer->content == NULL)) ++ { ++ return false; /* no input */ ++ } ++ ++ /* parse the different types of values */ ++ /* null */ ++ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) ++ { ++ item->type = cJSON_NULL; ++ input_buffer->offset += 4; ++ return true; ++ } ++ /* false */ ++ if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) ++ { ++ item->type = cJSON_False; ++ input_buffer->offset += 5; ++ return true; ++ } ++ /* true */ ++ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) ++ { ++ item->type = cJSON_True; ++ item->valueint = 1; ++ input_buffer->offset += 4; ++ return true; ++ } ++ /* string */ ++ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) ++ { ++ return parse_string(item, input_buffer); ++ } ++ /* number */ ++ if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) ++ { ++ return parse_number(item, input_buffer); ++ } ++ /* array */ ++ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) ++ { ++ return parse_array(item, input_buffer); ++ } ++ /* object */ ++ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) ++ { ++ return parse_object(item, input_buffer); ++ } ++ ++ return false; ++} ++ ++/* Render a value to text. */ ++static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) ++{ ++ unsigned char *output = NULL; ++ ++ if ((item == NULL) || (output_buffer == NULL)) ++ { ++ return false; ++ } ++ ++ switch ((item->type) & 0xFF) ++ { ++ case cJSON_NULL: ++ output = ensure(output_buffer, 5); ++ if (output == NULL) ++ { ++ return false; ++ } ++ strcpy((char*)output, "null"); ++ return true; ++ ++ case cJSON_False: ++ output = ensure(output_buffer, 6); ++ if (output == NULL) ++ { ++ return false; ++ } ++ strcpy((char*)output, "false"); ++ return true; ++ ++ case cJSON_True: ++ output = ensure(output_buffer, 5); ++ if (output == NULL) ++ { ++ return false; ++ } ++ strcpy((char*)output, "true"); ++ return true; ++ ++ case cJSON_Number: ++ return print_number(item, output_buffer); ++ ++ case cJSON_Raw: ++ { ++ size_t raw_length = 0; ++ if (item->valuestring == NULL) ++ { ++ return false; ++ } ++ ++ raw_length = strlen(item->valuestring) + sizeof(""); ++ output = ensure(output_buffer, raw_length); ++ if (output == NULL) ++ { ++ return false; ++ } ++ memcpy(output, item->valuestring, raw_length); ++ return true; ++ } ++ ++ case cJSON_String: ++ return print_string(item, output_buffer); ++ ++ case cJSON_Array: ++ return print_array(item, output_buffer); ++ ++ case cJSON_Object: ++ return print_object(item, output_buffer); ++ ++ default: ++ return false; ++ } ++} ++ ++/* Build an array from input text. */ ++static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) ++{ ++ cJSON *head = NULL; /* head of the linked list */ ++ cJSON *current_item = NULL; ++ ++ if (input_buffer->depth >= CJSON_NESTING_LIMIT) ++ { ++ return false; /* to deeply nested */ ++ } ++ input_buffer->depth++; ++ ++ if (buffer_at_offset(input_buffer)[0] != '[') ++ { ++ /* not an array */ ++ goto fail; ++ } ++ ++ input_buffer->offset++; ++ buffer_skip_whitespace(input_buffer); ++ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) ++ { ++ /* empty array */ ++ goto success; ++ } ++ ++ /* check if we skipped to the end of the buffer */ ++ if (cannot_access_at_index(input_buffer, 0)) ++ { ++ input_buffer->offset--; ++ goto fail; ++ } ++ ++ /* step back to character in front of the first element */ ++ input_buffer->offset--; ++ /* loop through the comma separated array elements */ ++ do ++ { ++ /* allocate next item */ ++ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); ++ if (new_item == NULL) ++ { ++ goto fail; /* allocation failure */ ++ } ++ ++ /* attach next item to list */ ++ if (head == NULL) ++ { ++ /* start the linked list */ ++ current_item = head = new_item; ++ } ++ else ++ { ++ /* add to the end and advance */ ++ current_item->next = new_item; ++ new_item->prev = current_item; ++ current_item = new_item; ++ } ++ ++ /* parse next value */ ++ input_buffer->offset++; ++ buffer_skip_whitespace(input_buffer); ++ if (!parse_value(current_item, input_buffer)) ++ { ++ goto fail; /* failed to parse value */ ++ } ++ buffer_skip_whitespace(input_buffer); ++ } ++ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); ++ ++ if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') ++ { ++ goto fail; /* expected end of array */ ++ } ++ ++success: ++ input_buffer->depth--; ++ ++ if (head != NULL) { ++ head->prev = current_item; ++ } ++ ++ item->type = cJSON_Array; ++ item->child = head; ++ ++ input_buffer->offset++; ++ ++ return true; ++ ++fail: ++ if (head != NULL) ++ { ++ cJSON_Delete(head); ++ } ++ ++ return false; ++} ++ ++/* Render an array to text */ ++static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) ++{ ++ unsigned char *output_pointer = NULL; ++ size_t length = 0; ++ cJSON *current_element = item->child; ++ ++ if (output_buffer == NULL) ++ { ++ return false; ++ } ++ ++ /* Compose the output array. */ ++ /* opening square bracket */ ++ output_pointer = ensure(output_buffer, 1); ++ if (output_pointer == NULL) ++ { ++ return false; ++ } ++ ++ *output_pointer = '['; ++ output_buffer->offset++; ++ output_buffer->depth++; ++ ++ while (current_element != NULL) ++ { ++ if (!print_value(current_element, output_buffer)) ++ { ++ return false; ++ } ++ update_offset(output_buffer); ++ if (current_element->next) ++ { ++ length = (size_t) (output_buffer->format ? 2 : 1); ++ output_pointer = ensure(output_buffer, length + 1); ++ if (output_pointer == NULL) ++ { ++ return false; ++ } ++ *output_pointer++ = ','; ++ if(output_buffer->format) ++ { ++ *output_pointer++ = ' '; ++ } ++ *output_pointer = '\0'; ++ output_buffer->offset += length; ++ } ++ current_element = current_element->next; ++ } ++ ++ output_pointer = ensure(output_buffer, 2); ++ if (output_pointer == NULL) ++ { ++ return false; ++ } ++ *output_pointer++ = ']'; ++ *output_pointer = '\0'; ++ output_buffer->depth--; ++ ++ return true; ++} ++ ++/* Build an object from the text. */ ++static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) ++{ ++ cJSON *head = NULL; /* linked list head */ ++ cJSON *current_item = NULL; ++ ++ if (input_buffer->depth >= CJSON_NESTING_LIMIT) ++ { ++ return false; /* to deeply nested */ ++ } ++ input_buffer->depth++; ++ ++ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) ++ { ++ goto fail; /* not an object */ ++ } ++ ++ input_buffer->offset++; ++ buffer_skip_whitespace(input_buffer); ++ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) ++ { ++ goto success; /* empty object */ ++ } ++ ++ /* check if we skipped to the end of the buffer */ ++ if (cannot_access_at_index(input_buffer, 0)) ++ { ++ input_buffer->offset--; ++ goto fail; ++ } ++ ++ /* step back to character in front of the first element */ ++ input_buffer->offset--; ++ /* loop through the comma separated array elements */ ++ do ++ { ++ /* allocate next item */ ++ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); ++ if (new_item == NULL) ++ { ++ goto fail; /* allocation failure */ ++ } ++ ++ /* attach next item to list */ ++ if (head == NULL) ++ { ++ /* start the linked list */ ++ current_item = head = new_item; ++ } ++ else ++ { ++ /* add to the end and advance */ ++ current_item->next = new_item; ++ new_item->prev = current_item; ++ current_item = new_item; ++ } ++ ++ /* parse the name of the child */ ++ input_buffer->offset++; ++ buffer_skip_whitespace(input_buffer); ++ if (!parse_string(current_item, input_buffer)) ++ { ++ goto fail; /* failed to parse name */ ++ } ++ buffer_skip_whitespace(input_buffer); ++ ++ /* swap valuestring and string, because we parsed the name */ ++ current_item->string = current_item->valuestring; ++ current_item->valuestring = NULL; ++ ++ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) ++ { ++ goto fail; /* invalid object */ ++ } ++ ++ /* parse the value */ ++ input_buffer->offset++; ++ buffer_skip_whitespace(input_buffer); ++ if (!parse_value(current_item, input_buffer)) ++ { ++ goto fail; /* failed to parse value */ ++ } ++ buffer_skip_whitespace(input_buffer); ++ } ++ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); ++ ++ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) ++ { ++ goto fail; /* expected end of object */ ++ } ++ ++success: ++ input_buffer->depth--; ++ ++ if (head != NULL) { ++ head->prev = current_item; ++ } ++ ++ item->type = cJSON_Object; ++ item->child = head; ++ ++ input_buffer->offset++; ++ return true; ++ ++fail: ++ if (head != NULL) ++ { ++ cJSON_Delete(head); ++ } ++ ++ return false; ++} ++ ++/* Render an object to text. */ ++static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) ++{ ++ unsigned char *output_pointer = NULL; ++ size_t length = 0; ++ cJSON *current_item = item->child; ++ ++ if (output_buffer == NULL) ++ { ++ return false; ++ } ++ ++ /* Compose the output: */ ++ length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ ++ output_pointer = ensure(output_buffer, length + 1); ++ if (output_pointer == NULL) ++ { ++ return false; ++ } ++ ++ *output_pointer++ = '{'; ++ output_buffer->depth++; ++ if (output_buffer->format) ++ { ++ *output_pointer++ = '\n'; ++ } ++ output_buffer->offset += length; ++ ++ while (current_item) ++ { ++ if (output_buffer->format) ++ { ++ size_t i; ++ output_pointer = ensure(output_buffer, output_buffer->depth); ++ if (output_pointer == NULL) ++ { ++ return false; ++ } ++ for (i = 0; i < output_buffer->depth; i++) ++ { ++ *output_pointer++ = '\t'; ++ } ++ output_buffer->offset += output_buffer->depth; ++ } ++ ++ /* print key */ ++ if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) ++ { ++ return false; ++ } ++ update_offset(output_buffer); ++ ++ length = (size_t) (output_buffer->format ? 2 : 1); ++ output_pointer = ensure(output_buffer, length); ++ if (output_pointer == NULL) ++ { ++ return false; ++ } ++ *output_pointer++ = ':'; ++ if (output_buffer->format) ++ { ++ *output_pointer++ = '\t'; ++ } ++ output_buffer->offset += length; ++ ++ /* print value */ ++ if (!print_value(current_item, output_buffer)) ++ { ++ return false; ++ } ++ update_offset(output_buffer); ++ ++ /* print comma if not last */ ++ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); ++ output_pointer = ensure(output_buffer, length + 1); ++ if (output_pointer == NULL) ++ { ++ return false; ++ } ++ if (current_item->next) ++ { ++ *output_pointer++ = ','; ++ } ++ ++ if (output_buffer->format) ++ { ++ *output_pointer++ = '\n'; ++ } ++ *output_pointer = '\0'; ++ output_buffer->offset += length; ++ ++ current_item = current_item->next; ++ } ++ ++ output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); ++ if (output_pointer == NULL) ++ { ++ return false; ++ } ++ if (output_buffer->format) ++ { ++ size_t i; ++ for (i = 0; i < (output_buffer->depth - 1); i++) ++ { ++ *output_pointer++ = '\t'; ++ } ++ } ++ *output_pointer++ = '}'; ++ *output_pointer = '\0'; ++ output_buffer->depth--; ++ ++ return true; ++} ++ ++/* Get Array size/item / object item. */ ++CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) ++{ ++ cJSON *child = NULL; ++ size_t size = 0; ++ ++ if (array == NULL) ++ { ++ return 0; ++ } ++ ++ child = array->child; ++ ++ while(child != NULL) ++ { ++ size++; ++ child = child->next; ++ } ++ ++ /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ ++ ++ return (int)size; ++} ++ ++static cJSON* get_array_item(const cJSON *array, size_t index) ++{ ++ cJSON *current_child = NULL; ++ ++ if (array == NULL) ++ { ++ return NULL; ++ } ++ ++ current_child = array->child; ++ while ((current_child != NULL) && (index > 0)) ++ { ++ index--; ++ current_child = current_child->next; ++ } ++ ++ return current_child; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) ++{ ++ if (index < 0) ++ { ++ return NULL; ++ } ++ ++ return get_array_item(array, (size_t)index); ++} ++ ++static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) ++{ ++ cJSON *current_element = NULL; ++ ++ if ((object == NULL) || (name == NULL)) ++ { ++ return NULL; ++ } ++ ++ current_element = object->child; ++ if (case_sensitive) ++ { ++ while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) ++ { ++ current_element = current_element->next; ++ } ++ } ++ else ++ { ++ while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) ++ { ++ current_element = current_element->next; ++ } ++ } ++ ++ if ((current_element == NULL) || (current_element->string == NULL)) { ++ return NULL; ++ } ++ ++ return current_element; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) ++{ ++ return get_object_item(object, string, false); ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) ++{ ++ return get_object_item(object, string, true); ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) ++{ ++ return cJSON_GetObjectItem(object, string) ? 1 : 0; ++} ++ ++/* Utility for array list handling. */ ++static void suffix_object(cJSON *prev, cJSON *item) ++{ ++ prev->next = item; ++ item->prev = prev; ++} ++ ++/* Utility for handling references. */ ++static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) ++{ ++ cJSON *reference = NULL; ++ if (item == NULL) ++ { ++ return NULL; ++ } ++ ++ reference = cJSON_New_Item(hooks); ++ if (reference == NULL) ++ { ++ return NULL; ++ } ++ ++ memcpy(reference, item, sizeof(cJSON)); ++ reference->string = NULL; ++ reference->type |= cJSON_IsReference; ++ reference->next = reference->prev = NULL; ++ return reference; ++} ++ ++static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) ++{ ++ cJSON *child = NULL; ++ ++ if ((item == NULL) || (array == NULL) || (array == item)) ++ { ++ return false; ++ } ++ ++ child = array->child; ++ /* ++ * To find the last item in array quickly, we use prev in array ++ */ ++ if (child == NULL) ++ { ++ /* list is empty, start new one */ ++ array->child = item; ++ item->prev = item; ++ item->next = NULL; ++ } ++ else ++ { ++ /* append to the end */ ++ if (child->prev) ++ { ++ suffix_object(child->prev, item); ++ array->child->prev = item; ++ } ++ } ++ ++ return true; ++} ++ ++/* Add item to array/object. */ ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) ++{ ++ return add_item_to_array(array, item); ++} ++ ++#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) ++ #pragma GCC diagnostic push ++#endif ++#ifdef __GNUC__ ++#pragma GCC diagnostic ignored "-Wcast-qual" ++#endif ++/* helper function to cast away const */ ++static void* cast_away_const(const void* string) ++{ ++ return (void*)string; ++} ++#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) ++ #pragma GCC diagnostic pop ++#endif ++ ++ ++static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) ++{ ++ char *new_key = NULL; ++ int new_type = cJSON_Invalid; ++ ++ if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) ++ { ++ return false; ++ } ++ ++ if (constant_key) ++ { ++ new_key = (char*)cast_away_const(string); ++ new_type = item->type | cJSON_StringIsConst; ++ } ++ else ++ { ++ new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); ++ if (new_key == NULL) ++ { ++ return false; ++ } ++ ++ new_type = item->type & ~cJSON_StringIsConst; ++ } ++ ++ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) ++ { ++ hooks->deallocate(item->string); ++ } ++ ++ item->string = new_key; ++ item->type = new_type; ++ ++ return add_item_to_array(object, item); ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) ++{ ++ return add_item_to_object(object, string, item, &global_hooks, false); ++} ++ ++/* Add an item to an object with constant string as key */ ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) ++{ ++ return add_item_to_object(object, string, item, &global_hooks, true); ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) ++{ ++ if (array == NULL) ++ { ++ return false; ++ } ++ ++ return add_item_to_array(array, create_reference(item, &global_hooks)); ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) ++{ ++ if ((object == NULL) || (string == NULL)) ++ { ++ return false; ++ } ++ ++ return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); ++} ++ ++CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) ++{ ++ cJSON *null = cJSON_CreateNull(); ++ if (add_item_to_object(object, name, null, &global_hooks, false)) ++ { ++ return null; ++ } ++ ++ cJSON_Delete(null); ++ return NULL; ++} ++ ++CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) ++{ ++ cJSON *true_item = cJSON_CreateTrue(); ++ if (add_item_to_object(object, name, true_item, &global_hooks, false)) ++ { ++ return true_item; ++ } ++ ++ cJSON_Delete(true_item); ++ return NULL; ++} ++ ++CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) ++{ ++ cJSON *false_item = cJSON_CreateFalse(); ++ if (add_item_to_object(object, name, false_item, &global_hooks, false)) ++ { ++ return false_item; ++ } ++ ++ cJSON_Delete(false_item); ++ return NULL; ++} ++ ++CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) ++{ ++ cJSON *bool_item = cJSON_CreateBool(boolean); ++ if (add_item_to_object(object, name, bool_item, &global_hooks, false)) ++ { ++ return bool_item; ++ } ++ ++ cJSON_Delete(bool_item); ++ return NULL; ++} ++ ++CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) ++{ ++ cJSON *number_item = cJSON_CreateNumber(number); ++ if (add_item_to_object(object, name, number_item, &global_hooks, false)) ++ { ++ return number_item; ++ } ++ ++ cJSON_Delete(number_item); ++ return NULL; ++} ++ ++CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) ++{ ++ cJSON *string_item = cJSON_CreateString(string); ++ if (add_item_to_object(object, name, string_item, &global_hooks, false)) ++ { ++ return string_item; ++ } ++ ++ cJSON_Delete(string_item); ++ return NULL; ++} ++ ++CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) ++{ ++ cJSON *raw_item = cJSON_CreateRaw(raw); ++ if (add_item_to_object(object, name, raw_item, &global_hooks, false)) ++ { ++ return raw_item; ++ } ++ ++ cJSON_Delete(raw_item); ++ return NULL; ++} ++ ++CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) ++{ ++ cJSON *object_item = cJSON_CreateObject(); ++ if (add_item_to_object(object, name, object_item, &global_hooks, false)) ++ { ++ return object_item; ++ } ++ ++ cJSON_Delete(object_item); ++ return NULL; ++} ++ ++CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) ++{ ++ cJSON *array = cJSON_CreateArray(); ++ if (add_item_to_object(object, name, array, &global_hooks, false)) ++ { ++ return array; ++ } ++ ++ cJSON_Delete(array); ++ return NULL; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) ++{ ++ if ((parent == NULL) || (item == NULL)) ++ { ++ return NULL; ++ } ++ ++ if (item != parent->child) ++ { ++ /* not the first element */ ++ item->prev->next = item->next; ++ } ++ if (item->next != NULL) ++ { ++ /* not the last element */ ++ item->next->prev = item->prev; ++ } ++ ++ if (item == parent->child) ++ { ++ /* first element */ ++ parent->child = item->next; ++ } ++ else if (item->next == NULL) ++ { ++ /* last element */ ++ parent->child->prev = item->prev; ++ } ++ ++ /* make sure the detached item doesn't point anywhere anymore */ ++ item->prev = NULL; ++ item->next = NULL; ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) ++{ ++ if (which < 0) ++ { ++ return NULL; ++ } ++ ++ return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); ++} ++ ++CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) ++{ ++ cJSON_Delete(cJSON_DetachItemFromArray(array, which)); ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) ++{ ++ cJSON *to_detach = cJSON_GetObjectItem(object, string); ++ ++ return cJSON_DetachItemViaPointer(object, to_detach); ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) ++{ ++ cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); ++ ++ return cJSON_DetachItemViaPointer(object, to_detach); ++} ++ ++CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) ++{ ++ cJSON_Delete(cJSON_DetachItemFromObject(object, string)); ++} ++ ++CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) ++{ ++ cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); ++} ++ ++/* Replace array/object items with new ones. */ ++CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) ++{ ++ cJSON *after_inserted = NULL; ++ ++ if (which < 0) ++ { ++ return false; ++ } ++ ++ after_inserted = get_array_item(array, (size_t)which); ++ if (after_inserted == NULL) ++ { ++ return add_item_to_array(array, newitem); ++ } ++ ++ newitem->next = after_inserted; ++ newitem->prev = after_inserted->prev; ++ after_inserted->prev = newitem; ++ if (after_inserted == array->child) ++ { ++ array->child = newitem; ++ } ++ else ++ { ++ newitem->prev->next = newitem; ++ } ++ return true; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) ++{ ++ if ((parent == NULL) || (replacement == NULL) || (item == NULL)) ++ { ++ return false; ++ } ++ ++ if (replacement == item) ++ { ++ return true; ++ } ++ ++ replacement->next = item->next; ++ replacement->prev = item->prev; ++ ++ if (replacement->next != NULL) ++ { ++ replacement->next->prev = replacement; ++ } ++ if (parent->child == item) ++ { ++ if (parent->child->prev == parent->child) ++ { ++ replacement->prev = replacement; ++ } ++ parent->child = replacement; ++ } ++ else ++ { /* ++ * To find the last item in array quickly, we use prev in array. ++ * We can't modify the last item's next pointer where this item was the parent's child ++ */ ++ if (replacement->prev != NULL) ++ { ++ replacement->prev->next = replacement; ++ } ++ if (replacement->next == NULL) ++ { ++ parent->child->prev = replacement; ++ } ++ } ++ ++ item->next = NULL; ++ item->prev = NULL; ++ cJSON_Delete(item); ++ ++ return true; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) ++{ ++ if (which < 0) ++ { ++ return false; ++ } ++ ++ return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); ++} ++ ++static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) ++{ ++ if ((replacement == NULL) || (string == NULL)) ++ { ++ return false; ++ } ++ ++ /* replace the name in the replacement */ ++ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) ++ { ++ cJSON_free(replacement->string); ++ } ++ replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); ++ replacement->type &= ~cJSON_StringIsConst; ++ ++ return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) ++{ ++ return replace_item_in_object(object, string, newitem, false); ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) ++{ ++ return replace_item_in_object(object, string, newitem, true); ++} ++ ++/* Create basic types: */ ++CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if(item) ++ { ++ item->type = cJSON_NULL; ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if(item) ++ { ++ item->type = cJSON_True; ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if(item) ++ { ++ item->type = cJSON_False; ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if(item) ++ { ++ item->type = boolean ? cJSON_True : cJSON_False; ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if(item) ++ { ++ item->type = cJSON_Number; ++ item->valuedouble = num; ++ ++ /* use saturation in case of overflow */ ++ if (num >= INT_MAX) ++ { ++ item->valueint = INT_MAX; ++ } ++ else if (num <= (double)INT_MIN) ++ { ++ item->valueint = INT_MIN; ++ } ++ else ++ { ++ item->valueint = (int)num; ++ } ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if(item) ++ { ++ item->type = cJSON_String; ++ item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); ++ if(!item->valuestring) ++ { ++ cJSON_Delete(item); ++ return NULL; ++ } ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if (item != NULL) ++ { ++ item->type = cJSON_String | cJSON_IsReference; ++ item->valuestring = (char*)cast_away_const(string); ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if (item != NULL) { ++ item->type = cJSON_Object | cJSON_IsReference; ++ item->child = (cJSON*)cast_away_const(child); ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if (item != NULL) { ++ item->type = cJSON_Array | cJSON_IsReference; ++ item->child = (cJSON*)cast_away_const(child); ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if(item) ++ { ++ item->type = cJSON_Raw; ++ item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); ++ if(!item->valuestring) ++ { ++ cJSON_Delete(item); ++ return NULL; ++ } ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if(item) ++ { ++ item->type=cJSON_Array; ++ } ++ ++ return item; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) ++{ ++ cJSON *item = cJSON_New_Item(&global_hooks); ++ if (item) ++ { ++ item->type = cJSON_Object; ++ } ++ ++ return item; ++} ++ ++/* Create Arrays: */ ++CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) ++{ ++ size_t i = 0; ++ cJSON *n = NULL; ++ cJSON *p = NULL; ++ cJSON *a = NULL; ++ ++ if ((count < 0) || (numbers == NULL)) ++ { ++ return NULL; ++ } ++ ++ a = cJSON_CreateArray(); ++ ++ for(i = 0; a && (i < (size_t)count); i++) ++ { ++ n = cJSON_CreateNumber(numbers[i]); ++ if (!n) ++ { ++ cJSON_Delete(a); ++ return NULL; ++ } ++ if(!i) ++ { ++ a->child = n; ++ } ++ else ++ { ++ suffix_object(p, n); ++ } ++ p = n; ++ } ++ ++ if (a && a->child) { ++ a->child->prev = n; ++ } ++ ++ return a; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) ++{ ++ size_t i = 0; ++ cJSON *n = NULL; ++ cJSON *p = NULL; ++ cJSON *a = NULL; ++ ++ if ((count < 0) || (numbers == NULL)) ++ { ++ return NULL; ++ } ++ ++ a = cJSON_CreateArray(); ++ ++ for(i = 0; a && (i < (size_t)count); i++) ++ { ++ n = cJSON_CreateNumber((double)numbers[i]); ++ if(!n) ++ { ++ cJSON_Delete(a); ++ return NULL; ++ } ++ if(!i) ++ { ++ a->child = n; ++ } ++ else ++ { ++ suffix_object(p, n); ++ } ++ p = n; ++ } ++ ++ if (a && a->child) { ++ a->child->prev = n; ++ } ++ ++ return a; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) ++{ ++ size_t i = 0; ++ cJSON *n = NULL; ++ cJSON *p = NULL; ++ cJSON *a = NULL; ++ ++ if ((count < 0) || (numbers == NULL)) ++ { ++ return NULL; ++ } ++ ++ a = cJSON_CreateArray(); ++ ++ for(i = 0; a && (i < (size_t)count); i++) ++ { ++ n = cJSON_CreateNumber(numbers[i]); ++ if(!n) ++ { ++ cJSON_Delete(a); ++ return NULL; ++ } ++ if(!i) ++ { ++ a->child = n; ++ } ++ else ++ { ++ suffix_object(p, n); ++ } ++ p = n; ++ } ++ ++ if (a && a->child) { ++ a->child->prev = n; ++ } ++ ++ return a; ++} ++ ++CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) ++{ ++ size_t i = 0; ++ cJSON *n = NULL; ++ cJSON *p = NULL; ++ cJSON *a = NULL; ++ ++ if ((count < 0) || (strings == NULL)) ++ { ++ return NULL; ++ } ++ ++ a = cJSON_CreateArray(); ++ ++ for (i = 0; a && (i < (size_t)count); i++) ++ { ++ n = cJSON_CreateString(strings[i]); ++ if(!n) ++ { ++ cJSON_Delete(a); ++ return NULL; ++ } ++ if(!i) ++ { ++ a->child = n; ++ } ++ else ++ { ++ suffix_object(p,n); ++ } ++ p = n; ++ } ++ ++ if (a && a->child) { ++ a->child->prev = n; ++ } ++ ++ return a; ++} ++ ++/* Duplication */ ++CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) ++{ ++ cJSON *newitem = NULL; ++ cJSON *child = NULL; ++ cJSON *next = NULL; ++ cJSON *newchild = NULL; ++ ++ /* Bail on bad ptr */ ++ if (!item) ++ { ++ goto fail; ++ } ++ /* Create new item */ ++ newitem = cJSON_New_Item(&global_hooks); ++ if (!newitem) ++ { ++ goto fail; ++ } ++ /* Copy over all vars */ ++ newitem->type = item->type & (~cJSON_IsReference); ++ newitem->valueint = item->valueint; ++ newitem->valuedouble = item->valuedouble; ++ if (item->valuestring) ++ { ++ newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); ++ if (!newitem->valuestring) ++ { ++ goto fail; ++ } ++ } ++ if (item->string) ++ { ++ newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); ++ if (!newitem->string) ++ { ++ goto fail; ++ } ++ } ++ /* If non-recursive, then we're done! */ ++ if (!recurse) ++ { ++ return newitem; ++ } ++ /* Walk the ->next chain for the child. */ ++ child = item->child; ++ while (child != NULL) ++ { ++ newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */ ++ if (!newchild) ++ { ++ goto fail; ++ } ++ if (next != NULL) ++ { ++ /* If newitem->child already set, then crosswire ->prev and ->next and move on */ ++ next->next = newchild; ++ newchild->prev = next; ++ next = newchild; ++ } ++ else ++ { ++ /* Set newitem->child and move to it */ ++ newitem->child = newchild; ++ next = newchild; ++ } ++ child = child->next; ++ } ++ if (newitem && newitem->child) ++ { ++ newitem->child->prev = newchild; ++ } ++ ++ return newitem; ++ ++fail: ++ if (newitem != NULL) ++ { ++ cJSON_Delete(newitem); ++ } ++ ++ return NULL; ++} ++ ++static void skip_oneline_comment(char **input) ++{ ++ *input += static_strlen("//"); ++ ++ for (; (*input)[0] != '\0'; ++(*input)) ++ { ++ if ((*input)[0] == '\n') { ++ *input += static_strlen("\n"); ++ return; ++ } ++ } ++} ++ ++static void skip_multiline_comment(char **input) ++{ ++ *input += static_strlen("/*"); ++ ++ for (; (*input)[0] != '\0'; ++(*input)) ++ { ++ if (((*input)[0] == '*') && ((*input)[1] == '/')) ++ { ++ *input += static_strlen("*/"); ++ return; ++ } ++ } ++} ++ ++static void minify_string(char **input, char **output) { ++ (*output)[0] = (*input)[0]; ++ *input += static_strlen("\""); ++ *output += static_strlen("\""); ++ ++ ++ for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { ++ (*output)[0] = (*input)[0]; ++ ++ if ((*input)[0] == '\"') { ++ (*output)[0] = '\"'; ++ *input += static_strlen("\""); ++ *output += static_strlen("\""); ++ return; ++ } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { ++ (*output)[1] = (*input)[1]; ++ *input += static_strlen("\""); ++ *output += static_strlen("\""); ++ } ++ } ++} ++ ++CJSON_PUBLIC(void) cJSON_Minify(char *json) ++{ ++ char *into = json; ++ ++ if (json == NULL) ++ { ++ return; ++ } ++ ++ while (json[0] != '\0') ++ { ++ switch (json[0]) ++ { ++ case ' ': ++ case '\t': ++ case '\r': ++ case '\n': ++ json++; ++ break; ++ ++ case '/': ++ if (json[1] == '/') ++ { ++ skip_oneline_comment(&json); ++ } ++ else if (json[1] == '*') ++ { ++ skip_multiline_comment(&json); ++ } else { ++ json++; ++ } ++ break; ++ ++ case '\"': ++ minify_string(&json, (char**)&into); ++ break; ++ ++ default: ++ into[0] = json[0]; ++ json++; ++ into++; ++ } ++ } ++ ++ /* and null-terminate. */ ++ *into = '\0'; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & 0xFF) == cJSON_Invalid; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & 0xFF) == cJSON_False; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & 0xff) == cJSON_True; ++} ++ ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & (cJSON_True | cJSON_False)) != 0; ++} ++CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & 0xFF) == cJSON_NULL; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & 0xFF) == cJSON_Number; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & 0xFF) == cJSON_String; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & 0xFF) == cJSON_Array; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & 0xFF) == cJSON_Object; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) ++{ ++ if (item == NULL) ++ { ++ return false; ++ } ++ ++ return (item->type & 0xFF) == cJSON_Raw; ++} ++ ++CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) ++{ ++ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) ++ { ++ return false; ++ } ++ ++ /* check if type is valid */ ++ switch (a->type & 0xFF) ++ { ++ case cJSON_False: ++ case cJSON_True: ++ case cJSON_NULL: ++ case cJSON_Number: ++ case cJSON_String: ++ case cJSON_Raw: ++ case cJSON_Array: ++ case cJSON_Object: ++ break; ++ ++ default: ++ return false; ++ } ++ ++ /* identical objects are equal */ ++ if (a == b) ++ { ++ return true; ++ } ++ ++ switch (a->type & 0xFF) ++ { ++ /* in these cases and equal type is enough */ ++ case cJSON_False: ++ case cJSON_True: ++ case cJSON_NULL: ++ return true; ++ ++ case cJSON_Number: ++ if (compare_double(a->valuedouble, b->valuedouble)) ++ { ++ return true; ++ } ++ return false; ++ ++ case cJSON_String: ++ case cJSON_Raw: ++ if ((a->valuestring == NULL) || (b->valuestring == NULL)) ++ { ++ return false; ++ } ++ if (strcmp(a->valuestring, b->valuestring) == 0) ++ { ++ return true; ++ } ++ ++ return false; ++ ++ case cJSON_Array: ++ { ++ cJSON *a_element = a->child; ++ cJSON *b_element = b->child; ++ ++ for (; (a_element != NULL) && (b_element != NULL);) ++ { ++ if (!cJSON_Compare(a_element, b_element, case_sensitive)) ++ { ++ return false; ++ } ++ ++ a_element = a_element->next; ++ b_element = b_element->next; ++ } ++ ++ /* one of the arrays is longer than the other */ ++ if (a_element != b_element) { ++ return false; ++ } ++ ++ return true; ++ } ++ ++ case cJSON_Object: ++ { ++ cJSON *a_element = NULL; ++ cJSON *b_element = NULL; ++ cJSON_ArrayForEach(a_element, a) ++ { ++ /* TODO This has O(n^2) runtime, which is horrible! */ ++ b_element = get_object_item(b, a_element->string, case_sensitive); ++ if (b_element == NULL) ++ { ++ return false; ++ } ++ ++ if (!cJSON_Compare(a_element, b_element, case_sensitive)) ++ { ++ return false; ++ } ++ } ++ ++ /* doing this twice, once on a and b to prevent true comparison if a subset of b ++ * TODO: Do this the proper way, this is just a fix for now */ ++ cJSON_ArrayForEach(b_element, b) ++ { ++ a_element = get_object_item(a, b_element->string, case_sensitive); ++ if (a_element == NULL) ++ { ++ return false; ++ } ++ ++ if (!cJSON_Compare(b_element, a_element, case_sensitive)) ++ { ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ ++ default: ++ return false; ++ } ++} ++ ++CJSON_PUBLIC(void *) cJSON_malloc(size_t size) ++{ ++ return global_hooks.allocate(size); ++} ++ ++CJSON_PUBLIC(void) cJSON_free(void *object) ++{ ++ global_hooks.deallocate(object); ++} +diff --git a/thirdparty/cjson/cJSON.h b/thirdparty/cjson/cJSON.h +new file mode 100644 +index 0000000..92907a2 +--- /dev/null ++++ b/thirdparty/cjson/cJSON.h +@@ -0,0 +1,293 @@ ++/* ++ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors ++ ++ Permission is hereby granted, free of charge, to any person obtaining a copy ++ of this software and associated documentation files (the "Software"), to deal ++ in the Software without restriction, including without limitation the rights ++ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ copies of the Software, and to permit persons to whom the Software is ++ furnished to do so, subject to the following conditions: ++ ++ The above copyright notice and this permission notice shall be included in ++ all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ THE SOFTWARE. ++*/ ++ ++#ifndef cJSON__h ++#define cJSON__h ++ ++#ifdef __cplusplus ++extern "C" ++{ ++#endif ++ ++#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) ++#define __WINDOWS__ ++#endif ++ ++#ifdef __WINDOWS__ ++ ++/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: ++ ++CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols ++CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) ++CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol ++ ++For *nix builds that support visibility attribute, you can define similar behavior by ++ ++setting default visibility to hidden by adding ++-fvisibility=hidden (for gcc) ++or ++-xldscope=hidden (for sun cc) ++to CFLAGS ++ ++then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does ++ ++*/ ++ ++#define CJSON_CDECL __cdecl ++#define CJSON_STDCALL __stdcall ++ ++/* export symbols by default, this is necessary for copy pasting the C and header file */ ++#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) ++#define CJSON_EXPORT_SYMBOLS ++#endif ++ ++#if defined(CJSON_HIDE_SYMBOLS) ++#define CJSON_PUBLIC(type) type CJSON_STDCALL ++#elif defined(CJSON_EXPORT_SYMBOLS) ++#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL ++#elif defined(CJSON_IMPORT_SYMBOLS) ++#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL ++#endif ++#else /* !__WINDOWS__ */ ++#define CJSON_CDECL ++#define CJSON_STDCALL ++ ++#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) ++#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type ++#else ++#define CJSON_PUBLIC(type) type ++#endif ++#endif ++ ++/* project version */ ++#define CJSON_VERSION_MAJOR 1 ++#define CJSON_VERSION_MINOR 7 ++#define CJSON_VERSION_PATCH 15 ++ ++#include ++ ++/* cJSON Types: */ ++#define cJSON_Invalid (0) ++#define cJSON_False (1 << 0) ++#define cJSON_True (1 << 1) ++#define cJSON_NULL (1 << 2) ++#define cJSON_Number (1 << 3) ++#define cJSON_String (1 << 4) ++#define cJSON_Array (1 << 5) ++#define cJSON_Object (1 << 6) ++#define cJSON_Raw (1 << 7) /* raw json */ ++ ++#define cJSON_IsReference 256 ++#define cJSON_StringIsConst 512 ++ ++/* The cJSON structure: */ ++typedef struct cJSON ++{ ++ /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ ++ struct cJSON *next; ++ struct cJSON *prev; ++ /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ ++ struct cJSON *child; ++ ++ /* The type of the item, as above. */ ++ int type; ++ ++ /* The item's string, if type==cJSON_String and type == cJSON_Raw */ ++ char *valuestring; ++ /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ ++ int valueint; ++ /* The item's number, if type==cJSON_Number */ ++ double valuedouble; ++ ++ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ ++ char *string; ++} cJSON; ++ ++typedef struct cJSON_Hooks ++{ ++ /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ ++ void *(CJSON_CDECL *malloc_fn)(size_t sz); ++ void (CJSON_CDECL *free_fn)(void *ptr); ++} cJSON_Hooks; ++ ++typedef int cJSON_bool; ++ ++/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. ++ * This is to prevent stack overflows. */ ++#ifndef CJSON_NESTING_LIMIT ++#define CJSON_NESTING_LIMIT 1000 ++#endif ++ ++/* returns the version of cJSON as a string */ ++CJSON_PUBLIC(const char*) cJSON_Version(void); ++ ++/* Supply malloc, realloc and free functions to cJSON */ ++CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); ++ ++/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ ++/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ ++CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); ++CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); ++/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ ++/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ ++CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); ++CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); ++ ++/* Render a cJSON entity to text for transfer/storage. */ ++CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); ++/* Render a cJSON entity to text for transfer/storage without any formatting. */ ++CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); ++/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ ++CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); ++/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ ++/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ ++CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); ++/* Delete a cJSON entity and all subentities. */ ++CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); ++ ++/* Returns the number of items in an array (or object). */ ++CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); ++/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ ++CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); ++/* Get item "string" from object. Case insensitive. */ ++CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); ++CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); ++CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); ++/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ ++CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); ++ ++/* Check item type and return its value */ ++CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); ++CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); ++ ++/* These functions check the type of an item */ ++CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); ++CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); ++CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); ++CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); ++CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); ++CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); ++CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); ++CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); ++CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); ++CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); ++ ++/* These calls create a cJSON item of the appropriate type. */ ++CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); ++CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); ++CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); ++CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); ++CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); ++CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); ++/* raw json */ ++CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); ++CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); ++CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); ++ ++/* Create a string where valuestring references a string so ++ * it will not be freed by cJSON_Delete */ ++CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); ++/* Create an object/array that only references it's elements so ++ * they will not be freed by cJSON_Delete */ ++CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); ++CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); ++ ++/* These utilities create an Array of count items. ++ * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ ++CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); ++CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); ++CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); ++CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); ++ ++/* Append item to the specified array/object. */ ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); ++/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. ++ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before ++ * writing to `item->string` */ ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); ++/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); ++CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); ++ ++/* Remove/Detach items from Arrays/Objects. */ ++CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); ++CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); ++CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); ++CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); ++CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); ++CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); ++CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); ++ ++/* Update array items. */ ++CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ ++CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); ++CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); ++CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); ++CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); ++ ++/* Duplicate a cJSON item */ ++CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); ++/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will ++ * need to be released. With recurse!=0, it will duplicate any children connected to the item. ++ * The item->next and ->prev pointers are always zero on return from Duplicate. */ ++/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. ++ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ ++CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); ++ ++/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. ++ * The input pointer json cannot point to a read-only address area, such as a string constant, ++ * but should point to a readable and writable address area. */ ++CJSON_PUBLIC(void) cJSON_Minify(char *json); ++ ++/* Helper functions for creating and adding items to an object at the same time. ++ * They return the added item or NULL on failure. */ ++CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); ++CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); ++CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); ++CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); ++CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); ++CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); ++CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); ++CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); ++CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); ++ ++/* When assigning an integer value, it needs to be propagated to valuedouble too. */ ++#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) ++/* helper for the cJSON_SetNumberValue macro */ ++CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); ++#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) ++/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ ++CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); ++ ++/* Macro for iterating over an array or object */ ++#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) ++ ++/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ ++CJSON_PUBLIC(void *) cJSON_malloc(size_t size); ++CJSON_PUBLIC(void) cJSON_free(void *object); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/thirdparty/kunpengsecl/verifier/custom_base64url.h b/thirdparty/kunpengsecl/verifier/custom_base64url.h +new file mode 100644 +index 0000000..1e003da +--- /dev/null ++++ b/thirdparty/kunpengsecl/verifier/custom_base64url.h +@@ -0,0 +1,20 @@ ++/* ++kunpengsecl licensed under the Mulan PSL v2. ++You can use this software according to the terms and conditions of ++the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: ++ http://license.coscl.org.cn/MulanPSL2 ++THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ++EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, ++MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++See the Mulan PSL v2 for more details. ++*/ ++ ++#ifndef CUSTOM_BASE64URL_H ++#define CUSTOM_BASE64URL_H ++ ++#include ++ ++void base64urlencode(const uint8_t *src, int src_len, uint8_t *cipher, int *dest_len); ++uint8_t *base64urldecode(const uint8_t *src, int src_len, int *dest_len); ++ ++#endif +diff --git a/thirdparty/kunpengsecl/verifier/teeverifier.h b/thirdparty/kunpengsecl/verifier/teeverifier.h +new file mode 100644 +index 0000000..4a311f6 +--- /dev/null ++++ b/thirdparty/kunpengsecl/verifier/teeverifier.h +@@ -0,0 +1,50 @@ ++/* ++kunpengsecl licensed under the Mulan PSL v2. ++You can use this software according to the terms and conditions of ++the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: ++ http://license.coscl.org.cn/MulanPSL2 ++THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ++EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, ++MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++See the Mulan PSL v2 for more details. ++*/ ++ ++#ifndef __VERIFIER_LIB__ ++#define __VERIFIER_LIB__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define UUID_SIZE 16 ++#define HASH_SIZE 32 ++//Attester will send the report by this type ++typedef struct{ ++ uint32_t size; ++ uint8_t *buf; ++} buffer_data; ++ ++typedef struct ++{ ++ uint8_t uuid[UUID_SIZE]; ++ uint8_t valueinfo[2][HASH_SIZE]; // valueinfo[0]=img measurement and valueinfo[1]=mem measurement ++} base_value; ++ ++enum error_status_code { ++ TVS_ALL_SUCCESSED = 0, ++ TVS_VERIFIED_NONCE_FAILED = -1, ++ TVS_VERIFIED_SIGNATURE_FAILED = -2, ++ TVS_VERIFIED_HASH_FAILED = -3, ++}; ++ ++int tee_verify_report(buffer_data *data_buf,buffer_data *nonce,int type, char *filename); ++int tee_validate_report(buffer_data *buf_data, buffer_data *nonce); ++int tee_verify_report2(buffer_data *buf_data, int type,base_value *baseval); ++bool tee_verify_akcert(buffer_data *akcert, int type, const char *refval); ++bool tee_get_akcert_data(buffer_data *akcert, buffer_data *akpub, buffer_data *drkcrt); ++ ++#endif +diff --git a/thirdparty/libqca/ra_client_api.h b/thirdparty/libqca/ra_client_api.h +new file mode 100644 +index 0000000..dd793a3 +--- /dev/null ++++ b/thirdparty/libqca/ra_client_api.h +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved. ++ * Licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++#ifndef LIBQCA_H ++#define LIBQCA_H ++#include ++ ++struct ra_buffer_data { ++ uint32_t size; ++ uint8_t *buf; ++}; ++ ++TEEC_Result RemoteAttest(struct ra_buffer_data *in, struct ra_buffer_data *out); ++#endif +diff --git a/tools/sign_tool/generate_signature.py b/tools/sign_tool/generate_signature.py +deleted file mode 100644 +index b3264ba..0000000 +--- a/tools/sign_tool/generate_signature.py ++++ /dev/null +@@ -1,56 +0,0 @@ +-#!/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 +deleted file mode 100644 +index 9cc2360..0000000 +--- a/tools/sign_tool/manifest.py ++++ /dev/null +@@ -1,322 +0,0 @@ +-#!/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 string +-import struct +-import uuid +-import os +- +-PRODUCT_TA_IMAGE = 1 +-PRODUCT_DYN_LIB = 2 +-PRODUCT_SERVICE_IMAGE = 3 +- +- +-class PackUuid: +- # Structure object to align and package the TEE_UUID +- data = struct.Struct('IHH8b') +- +- def __init__(self, data): +- unpacked_data = (PackUuid.data).unpack(str.encode(data)) +- self.unpacked_data = unpacked_data +- 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 print_values(self): +- print("ATTRIBUTE / VALUE") +- for attr, value in self.__dict__.items(): +- print(attr, value) +- +- def get_pack_data(self): +- values = [self.time_low, +- self.time_mid, +- self.time_hi_version, +- self.clock_seq_node, +- ] +- +- return (PackUuid.data).pack(*values) +- +- +-#---------------------------------------------------------------------------- +-# Manifest +-#---------------------------------------------------------------------------- +-class Manifest: +- +- # Structure object to align and package the Manifest +- data = struct.Struct('I' * 6) +- +- def __init__(self, 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] +- self.multi_command = unpacked_data[2] +- self.heap_size = unpacked_data[3] +- self.stack_size = unpacked_data[4] +- self.instancekeepalive = unpacked_data[5] +- +- def print_values(self): +- print("ATTRIBUTE / VALUE") +- for attr, value in self.__dict__.items(): +- print(attr, value) +- +- def get_pack_data(self): +- values = [self.single_instance, +- self.multi_session, +- self.multi_command, +- self.heap_size, +- self.stack_size, +- self.instancekeepalive, +- ] +- +- return (Manifest.data).pack(*values) +- +- +-#---------------------------------------------------------------------------- +-# verify property name in manifest file +-#---------------------------------------------------------------------------- +-def verify_property_name(str_line): +- print('verify property name') +- alphas = string.ascii_letters + string.digits +- cont = "".join([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 str_line[1:]: +- if otherchar not in cont: +- print('invalid char in property name') +- return False +- else: +- print('invalid property name') +- return False +- +- return True +- +- +-#---------------------------------------------------------------------------- +-# verify property value in manifest file +-#---------------------------------------------------------------------------- +-def verify_property_value(str_line): +- print('verify property value') +- 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(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) +- print('tab: {}'.format(space_tabs)) +- +- print('str in: {}'.format(str_line)) +- index = 0 +- for thechar in str_line: +- if thechar in space_tabs: +- index += 1 +- else: +- break +- headvalue = str_line[index:] +- +- strlen = len(headvalue) +- +- strlen -= 1 +- +- while strlen > 0: +- if headvalue[strlen] in space_tabs_newlines: +- strlen -= 1 +- else: +- break +- +- str_ret = headvalue[0:strlen+1] + chr(10) +- print('str ret: {}'.format(str_ret)) +- +- return str_ret +- +- +-#---------------------------------------------------------------------------- +-# verify manifest file, parse manifest file, generate a new manfiest file +-#---------------------------------------------------------------------------- +-def parser_manifest(manifest, manifest_data_path, mani_ext): +- print('verify manifest') +- target_type = PRODUCT_TA_IMAGE +- +- uuid_val = PackUuid('\0' * 16) +- +- #manifest default +- manifest_val = Manifest('\0'*24) +- +- manifest_val.single_instance = 1 +- manifest_val.multi_session = 0 +- manifest_val.multi_command = 0 +- manifest_val.instancekeepalive = 0 +- manifest_val.heap_size = 16384 +- manifest_val.stack_size = 2048 +- +- service_name = 'external_service' +- +- with open(manifest, 'r') as mani_fp, open(mani_ext, 'wb') as mani_ext_fp: +- for each_line in mani_fp: +- print(each_line) +- if each_line.startswith("#") or not len(each_line.strip()): +- continue +- index = each_line.find(':', 1, len(each_line)) +- +- 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] +- 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) +- +- if verify_property_value(prop_value_v) is False: +- print('manifest format invalid, please check it') +- return (False, 0) +- +- # name:value to lowcase, and parse manifest +- prop_name_low = prop_name.lower() +- print("name lower: {}".format(prop_name_low)) +- if 'gpd.ta.appid' == prop_name_low: +- print("compare name is srv id") +- uuid_val = uuid.UUID(prop_value_v) +- 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 +- elif 'false' == prop_value_low: +- 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 +- elif 'false' == prop_value_low: +- 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 +- elif 'false' == prop_value_low: +- 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 +- elif 'false' == prop_value_low: +- manifest_val.instancekeepalive = 0 +- else: +- print('instancekeepalive value error!') +- +- elif 'gpd.ta.datasize' == prop_name_low: +- manifest_val.heap_size = int(prop_value_v) +- print('b') +- +- elif 'gpd.ta.stacksize' == prop_name_low: +- manifest_val.stack_size = int(prop_value_v) +- print('b') +- +- elif 'gpd.ta.service_name' == prop_name_low: +- service_name = prop_value_v +- print('b') +- +- else: +- print('b') +- #write have not paresed manifest into sample.manifest file +- mani_ext_fp.write(str.encode(prop_name_t)) +- mani_ext_fp.write(str.encode(prop_value)) +- if 'gpd.ta.is_tee_service' == prop_name_low: +- prop_value_low = prop_value_v.lower() +- if 'true' == prop_value_low: +- 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: +- target_type = PRODUCT_DYN_LIB +- +- #write the whole parsed manifest into sample.manifest file +- +- service_name_len = len(service_name) +- print('service name: {}'.format(service_name)) +- print('service name len: {}'.format(service_name_len)) +- if service_name_len > 64: +- print("service name len exceed MAX value 27") +- raise RuntimeError +- +- # get manifest string file len +- manifest_str_size = os.path.getsize(mani_ext) +- 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.get_pack_data()))) +- print("bytes len {}".format(len(service_name))) +- +- # 3> unparsed manifest, string manifest +- with open(mani_ext, 'rb') as string_mani_fp: +- print("read manifest string size {}".format(manifest_str_size)) +- manifest_string_buf = string_mani_fp.read(manifest_str_size) +- print("manifest strint: {}".format(manifest_string_buf)) +- +- #---- write manifest parse context to manifest file +- 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.get_pack_data()) +- +- product_name = str(uuid_val) +- if target_type == PRODUCT_TA_IMAGE: +- print("product type is ta image") +- product_name = "".join([product_name, ".sec"]) +- elif target_type == PRODUCT_SERVICE_IMAGE: +- print("product type is service") +- product_name = "".join([product_name, service_name, "_svr.sec"]) +- elif target_type == PRODUCT_DYN_LIB: +- print("product type is dyn lib") +- product_name = "".join([product_name, service_name, ".so.sec"]) +- else: +- print("invalid product type!") +- raise RuntimeError +- +- return (True, product_name) +- +diff --git a/tools/sign_tool/sign_tool.sh b/tools/sign_tool/sign_tool.sh +index daca711..f150aed 100755 +--- a/tools/sign_tool/sign_tool.sh ++++ b/tools/sign_tool/sign_tool.sh +@@ -1,27 +1,10 @@ +-# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +-# secGear is licensed under the Mulan PSL v2. +-# You can use this software according to the terms and conditions of the Mulan PSL v2. +-# You may obtain a copy of Mulan PSL v2 at: +-# http://license.coscl.org.cn/MulanPSL2 +-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +-# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +-# PURPOSE. +-# See the Mulan PSL v2 for more details. +- + #!/bin/bash +-VERSION=3 + API_LEVEL=2 + ONE_STEP_MODE=1 + +-localpath="$(cd "$(dirname "$0")"; pwd)" +-pypath="/lib/secGear" +-if [ -f ${localpath}/signtool_v3.py ]; then +- signtoolpath=${localpath} +-else +- signtoolpath=${pypath} +-fi ++signtoolpath="/opt/itrustee_sdk/build/signtools/" + +-print_help(){ ++print_help() { + echo "sign tool usage: ./sign_tool.sh [options] ..." + echo "[options]" + echo "-c basic config file." +@@ -31,8 +14,8 @@ print_help(){ + echo " The dump command is used to generate metadata for sgx signed enclave." + echo "-i input parameter, which is enclave to be signed for digest/sign command, and signed enclave for" + echo " dump command." +- echo "-k private key required for single-step method. NOTE: single-step method is only for the dubug mode," +- echo " plaintext private key does exist in the production environment." ++ echo "-k private key required for single-step method. Note: single-step method is only for the debug mode," ++ echo "-k plaintext private key does exist in the production environment." + echo "-m additional config_cloud.ini for trustzone." + echo "-o output parameter, the sign command outputs signed enclave, the digest command outputs signing" + echo " material, the dump command outputs data containing the SIGStruct metadata for the SGX signed" +@@ -45,81 +28,81 @@ print_help(){ + + } + +-while getopts "c:d:i:k:m:o:p:s:x:h" opt +-do ++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 +- ;; ++ 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" +- exit -1 +- fi +- typeset -l CMD +- CMD=$OPTARG +- ;; ++ if [[ $OPTARG == -* ]]; then ++ echo "Error: parameter for -d is missing or incorrect" ++ exit 1 ++ fi ++ typeset -l CMD ++ CMD=$OPTARG ++ ;; + i) +- if [[ $OPTARG == -* ]]; then +- echo "Error: parameter for -i is missing or incorrect" +- exit -1 +- fi +- IN_ENCLAVE=$OPTARG +- ;; ++ if [[ $OPTARG == -* ]]; then ++ echo "Error: parameter for -i is missing or incorrect" ++ exit 1 ++ fi ++ IN_ENCLAVE=$OPTARG ++ ;; + k) +- if [[ $OPTARG == -* ]]; then +- echo "Error: parameter for -k is missing or incorrect" +- exit -1 +- fi +- SIG_KEY=$OPTARG +- ;; ++ if [[ $OPTARG == -* ]]; then ++ echo "Error: parameter for -k is missing or incorrect" ++ exit 1 ++ fi ++ SIG_KEY=$OPTARG ++ ;; + m) +- if [[ $OPTARG == -* ]]; then +- echo "Error: parameter for -m is missing or incorrect" +- exit -1 +- fi +- A_CONFIG_FILE=$OPTARG +- ;; ++ if [[ $OPTARG == -* ]]; then ++ echo "Error: parameter for -m is missing or incorrect" ++ exit 1 ++ fi ++ A_CONFIG_FILE=$OPTARG ++ ;; + o) +- if [[ $OPTARG == -* ]]; then +- echo "Error: parameter for -o is missing or incorrect" +- exit -1 +- fi +- OUT_FILE=$OPTARG +- ;; ++ if [[ $OPTARG == -* ]]; then ++ echo "Error: parameter for -o is missing or incorrect" ++ exit 1 ++ fi ++ OUT_FILE=$OPTARG ++ ;; + p) +- if [[ $OPTARG == -* ]]; then +- echo "Error: parameter for -p is missing or incorrect" +- exit -1 +- fi +- SERVER_PUBKEY=$OPTARG +- ;; ++ if [[ $OPTARG == -* ]]; then ++ echo "Error: parameter for -p is missing or incorrect" ++ exit 1 ++ fi ++ SERVER_PUBKEY=$OPTARG ++ ;; + s) +- if [[ $OPTARG == -* ]]; then +- echo "Error: parameter for -s is missing or incorrect" +- exit -1 +- fi +- SIGNATURE=$OPTARG +- ;; ++ if [[ $OPTARG == -* ]]; then ++ echo "Error: parameter for -s is missing or incorrect" ++ exit 1 ++ fi ++ SIGNATURE=$OPTARG ++ ;; + x) +- if [[ $OPTARG == -* ]]; then +- echo "Error: parameter for -x is missing or incorrect" +- exit -1 +- fi +- typeset -l ENCLAVE_TYPE +- ENCLAVE_TYPE=$OPTARG +- ;; ++ if [[ $OPTARG == -* ]]; then ++ echo "Error: parameter for -x is missing or incorrect" ++ exit 1 ++ fi ++ typeset -l ENCLAVE_TYPE ++ ENCLAVE_TYPE=$OPTARG ++ ;; + h) +- print_help +- exit 0 +- ;; ++ print_help ++ exit 0 ++ ;; + ?) +- print_help +- exit -1 ++ print_help ++ exit 1 ++ ;; + esac + done + if [ ${OPTIND} == 1 ]; then +@@ -127,103 +110,82 @@ if [ ${OPTIND} == 1 ]; then + exit 0 + fi + +-itrustee_start_sign(){ +-# check_native_sign +- if [ -z $A_CONFIG_FILE ]; then ++itrustee_start_sign() { ++ # check_native_sign ++ if [ -z "$A_CONFIG_FILE" ]; then + echo "Error: missing additional config_cloud.ini file for signing iTrustee enclave" +- exit -1 ++ exit 1 + fi + + if [ "${CMD}"x == "sign"x ]; then +- if [ -z $SIGNATURE ]; then +- ONE_STEP_MODE=1 +- if [ -z $CONFIG_FILE ]; then +- echo "Error: missing basic config file for signing iTrustee enclave" +- exit -1 +- fi +- if [ -z $IN_ENCLAVE ]; then +- echo "Error: missing enclave file" +- exit -1 +- fi +- python ${signtoolpath}/signtool_v3.py "sign" "${ONE_STEP_MODE}" "${IN_ENCLAVE}" "${OUT_FILE}" "${CONFIG_FILE}" "${A_CONFIG_FILE}" "${API_LEVEL}" +- else +- ONE_STEP_MODE=0 +- python ${signtoolpath}/signtool_v3.py "sign" "${ONE_STEP_MODE}" "NULL" "${OUT_FILE}" "NULL" "${A_CONFIG_FILE}" "${API_LEVEL}" "${SIGNATURE}" +- fi +- elif [ "${CMD}"x == "digest"x ]; then +- 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 ${signtoolpath}/signtool_v3.py "digest" "${ONE_STEP_MODE}" "${IN_ENCLAVE}" "${OUT_FILE}" "${CONFIG_FILE}" "${A_CONFIG_FILE}" "${API_LEVEL}" ++ IN_PATH=$(dirname ${CONFIG_FILE}) ++ cp ${IN_ENCLAVE} ${IN_PATH}/libcombine.so ++ OUT_PATH=$(dirname ${OUT_FILE}) ++ echo ${IN_PATH} ${OUT_PATH} ++ python -B ${signtoolpath}/signtool_v3.py ${IN_PATH} ${OUT_PATH} --privateCfg ${A_CONFIG_FILE} ++ #rm -rf ${IN_PATH}/libcombine.so + else + echo "Error: illegal command" + fi + } + +-sgx_start_sign(){ +- if [ -z $IN_ENCLAVE ]; then ++sgx_start_sign() { ++ if [ -z "$IN_ENCLAVE" ]; then + echo "Error: missing enclave file" +- exit -1 ++ exit 1 + fi + SIGDATA_FILE="signdata" + if [ "${CMD}"x == "sign"x ]; then +- if [ -z $SIGNATURE ]; then +- if [ -z $SIG_KEY ]; then +- echo "Error: missing sign key" +- exit -1 +- fi +- if [ -z $CONFIG_FILE ]; then +- sgx_sign sign -enclave ${IN_ENCLAVE} -key ${SIG_KEY} -out ${OUT_FILE} ++ if [ -z "$SIGNATURE" ]; then ++ if [ -z "$SIG_KEY" ]; then ++ echo "Error: missing sign key" ++ exit 1 ++ fi ++ if [ -z "$CONFIG_FILE" ]; then ++ sgx_sign sign -enclave "${IN_ENCLAVE}" -key "${SIG_KEY}" -out "${OUT_FILE}" + else +- sgx_sign sign -enclave ${IN_ENCLAVE} -key ${SIG_KEY} -out ${OUT_FILE} -config ${CONFIG_FILE} ++ sgx_sign sign -enclave "${IN_ENCLAVE}" -key "${SIG_KEY}" -out "${OUT_FILE}" -config "${CONFIG_FILE}" + fi + else +- if [ -z $SERVER_PUBKEY ]; then ++ if [ -z "$SERVER_PUBKEY" ]; then + echo "Error: missing server public key" +- exit -1 +- fi +- if [ -z $CONFIG_FILE ]; then +- sgx_sign catsig -enclave ${IN_ENCLAVE} -key ${SERVER_PUBKEY} -sig ${SIGNATURE} -unsigned ${SIGDATA_FILE} -out ${OUT_FILE} ++ exit 1 ++ fi ++ if [ -z "$CONFIG_FILE" ]; then ++ sgx_sign catsig -enclave "${IN_ENCLAVE}" -key "${SERVER_PUBKEY}" -sig "${SIGNATURE}" -unsigned "${SIGDATA_FILE}" -out "${OUT_FILE}" + else +- sgx_sign catsig -enclave ${IN_ENCLAVE} -key ${SERVER_PUBKEY} -sig ${SIGNATURE} -unsigned ${SIGDATA_FILE} -out ${OUT_FILE} -config ${CONFIG_FILE} ++ sgx_sign catsig -enclave "${IN_ENCLAVE}" -key "${SERVER_PUBKEY}" -sig "${SIGNATURE}" -unsigned "${SIGDATA_FILE}" -out "${OUT_FILE}" -config "${CONFIG_FILE}" + fi + rm -rf ${SIGDATA_FILE} + fi + elif [ "${CMD}"x == "digest"x ]; then +- if [ -z $CONFIG_FILE ]; then +- sgx_sign gendata -enclave ${IN_ENCLAVE} -out ${SIGDATA_FILE} ++ if [ -z "$CONFIG_FILE" ]; then ++ sgx_sign gendata -enclave "${IN_ENCLAVE}" -out "${SIGDATA_FILE}" + else +- sgx_sign gendata -enclave ${IN_ENCLAVE} -out ${SIGDATA_FILE} -config ${CONFIG_FILE} ++ sgx_sign gendata -enclave "${IN_ENCLAVE}" -out "${SIGDATA_FILE}" -config "${CONFIG_FILE}" + fi +- cp ${SIGDATA_FILE} ${OUT_FILE} ++ cp "${SIGDATA_FILE}" "${OUT_FILE}" + elif [ "${CMD}"x == "dump"x ]; then +- sgx_sign dump -enclave ${IN_ENCLAVE} -dumpfile ${OUT_FILE} ++ sgx_sign dump -enclave "${IN_ENCLAVE}" -dumpfile "${OUT_FILE}" + else + echo "Error: illegal command" + fi + } + +- +-if [ -z $CMD ]; then ++if [ -z "$CMD" ]; then + echo "Error: missing command" +- exit -1 ++ exit 1 + fi +-if [ -z $ENCLAVE_TYPE ]; then ++if [ -z "$ENCLAVE_TYPE" ]; then + echo "Error: missing enclave type" +- exit -1 ++ exit 1 + fi +-if [ -z $OUT_FILE ]; then ++if [ -z "$OUT_FILE" ]; then + echo "Error: missing out file" +- exit -1 ++ exit 1 + fi + umask 0077 +-check_results=`uname -m` ++check_results=$(uname -m) + if [ "${ENCLAVE_TYPE}"x == "sgx"x ]; then + if [ "${check_results}"x != "x86_64"x ]; then + echo "Warning: the enclave type does not comply with current architecture" +@@ -236,5 +198,5 @@ elif [ "${ENCLAVE_TYPE}"x == "trustzone"x ]; then + itrustee_start_sign + else + echo "Error: illegal enclave type" +- exit -1 ++ exit 1 + fi +diff --git a/tools/sign_tool/signtool_v3.py b/tools/sign_tool/signtool_v3.py +deleted file mode 100644 +index dae036f..0000000 +--- a/tools/sign_tool/signtool_v3.py ++++ /dev/null +@@ -1,428 +0,0 @@ +-#!/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.33.0 + diff --git a/0061-refactor-remote-attestation.patch b/0061-refactor-remote-attestation.patch new file mode 100644 index 0000000000000000000000000000000000000000..eaae063283f32e615ffaea2231995ec02e607922 --- /dev/null +++ b/0061-refactor-remote-attestation.patch @@ -0,0 +1,1745 @@ +From ef49daeec97c51beb3548b3caa6c160079f5ac8d Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Sat, 27 May 2023 14:22:13 +0800 +Subject: [PATCH 1/2] refactor remote attestation + +--- + component/CMakeLists.txt | 9 +- + component/remote_attest/CMakeLists.txt | 1 - + .../remote_attest/ra_report/CMakeLists.txt | 39 ++-- + .../remote_attest/ra_report/gp_ra_helper.c | 136 -------------- + .../remote_attest/ra_report/gp_ra_report.c | 169 ++++++++++++++++-- + .../remote_attest/ra_report/gp_ra_report.h | 2 +- + .../remote_attest/ra_report/sg_ra_report.c | 26 ++- + .../remote_attest/ra_report/sg_ra_report.h | 13 +- + .../remote_attest/ra_report/sgx_ra_report.c | 38 ++++ + .../remote_attest/ra_report/sgx_ra_report.h | 24 +++ + .../remote_attest/ra_report/uni_ree_agent.h | 44 +++++ + .../remote_attest/ra_verify/CMakeLists.txt | 21 ++- + .../ra_verify/gp_ra_report_verify.c | 19 +- + .../ra_verify/gp_ra_report_verify.h | 8 +- + .../ra_verify/sg_ra_report_verify.c | 18 +- + .../ra_verify/sg_ra_report_verify.h | 7 +- + .../ra_verify/sgx_ra_report_verify.c | 33 ++++ + .../ra_verify/sgx_ra_report_verify.h | 30 ++++ + .../uni_ra_verify_agent.h} | 31 ++-- + component/remote_attest/sg_report_st.h | 14 +- + inc/host_inc/enclave_internal.h | 1 + + inc/host_inc/status.h | 11 ++ + src/host_src/enclave_internal.c | 10 ++ + thirdparty/base64url/b64/LICENSE | 21 +++ + thirdparty/base64url/b64/README.md | 84 +++++++++ + thirdparty/base64url/b64/b64.h | 84 +++++++++ + thirdparty/base64url/b64/buffer.c | 33 ++++ + thirdparty/base64url/b64/decode.c | 117 ++++++++++++ + thirdparty/base64url/b64/encode.c | 93 ++++++++++ + thirdparty/base64url/b64/notes.md | 10 ++ + thirdparty/base64url/base64url.c | 74 ++++++++ + thirdparty/base64url/base64url.h | 32 ++++ + tools/sign_tool/sign_tool.sh | 4 +- + 33 files changed, 1036 insertions(+), 220 deletions(-) + delete mode 100644 component/remote_attest/ra_report/gp_ra_helper.c + create mode 100644 component/remote_attest/ra_report/sgx_ra_report.c + create mode 100644 component/remote_attest/ra_report/sgx_ra_report.h + create mode 100644 component/remote_attest/ra_report/uni_ree_agent.h + create mode 100644 component/remote_attest/ra_verify/sgx_ra_report_verify.c + create mode 100644 component/remote_attest/ra_verify/sgx_ra_report_verify.h + rename component/remote_attest/{ra_report/gp_ra_helper.h => ra_verify/uni_ra_verify_agent.h} (57%) + create mode 100644 thirdparty/base64url/b64/LICENSE + create mode 100644 thirdparty/base64url/b64/README.md + create mode 100644 thirdparty/base64url/b64/b64.h + create mode 100644 thirdparty/base64url/b64/buffer.c + create mode 100644 thirdparty/base64url/b64/decode.c + create mode 100644 thirdparty/base64url/b64/encode.c + create mode 100644 thirdparty/base64url/b64/notes.md + create mode 100644 thirdparty/base64url/base64url.c + create mode 100644 thirdparty/base64url/base64url.h + +diff --git a/component/CMakeLists.txt b/component/CMakeLists.txt +index ee0a669..7442334 100644 +--- a/component/CMakeLists.txt ++++ b/component/CMakeLists.txt +@@ -8,9 +8,12 @@ + # PURPOSE. + # See the Mulan PSL v2 for more details. + ++set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) ++ + ADD_SUBDIRECTORY(secure_channel) +-if(CC_GP) +- ADD_SUBDIRECTORY(remote_attest) +-endif() ++ ++ADD_SUBDIRECTORY(remote_attest) ++ ++ + + +diff --git a/component/remote_attest/CMakeLists.txt b/component/remote_attest/CMakeLists.txt +index 0b86c6f..f8ecac7 100644 +--- a/component/remote_attest/CMakeLists.txt ++++ b/component/remote_attest/CMakeLists.txt +@@ -14,7 +14,6 @@ ADD_SUBDIRECTORY(ra_verify) + + file(GLOB RA_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/sg_report_st.h + ${CMAKE_CURRENT_SOURCE_DIR}/ra_report/sg_ra_report.h +- ${CMAKE_CURRENT_SOURCE_DIR}/ra_report/gp_ra_helper.h + ${CMAKE_CURRENT_SOURCE_DIR}/ra_verify/sg_ra_report_verify.h) + + install(FILES ${RA_HEADERS} +diff --git a/component/remote_attest/ra_report/CMakeLists.txt b/component/remote_attest/ra_report/CMakeLists.txt +index 6b459d7..548e786 100644 +--- a/component/remote_attest/ra_report/CMakeLists.txt ++++ b/component/remote_attest/ra_report/CMakeLists.txt +@@ -8,37 +8,38 @@ + # PURPOSE. + # See the Mulan PSL v2 for more details. + +-project(sg_ra_report C) ++project(secgear_ra C) + + set(TARGET secgear_ra) +-aux_source_directory(. SRC_FILES) +-aux_source_directory(${LOCAL_ROOT_PATH}/thirdparty/cjson/ CJSON_SRC) + +-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") ++set(SRC_FILES sg_ra_report.c) ++if(CC_SGX) ++ set(SRC_FILES ${SRC_FILES} sgx_ra_report.c) ++endif() + +-if(${CMAKE_VERSION} VERSION_LESS "3.13.0") +- link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) ++if(CC_GP) ++ aux_source_directory(${LOCAL_ROOT_PATH}/thirdparty/cjson/ CJSON_SRC) ++ FILE (GLOB_RECURSE BASE64_SRC "${LOCAL_ROOT_PATH}/thirdparty/base64url/*.c") ++ set(SRC_FILES ${SRC_FILES} ${CJSON_SRC} ${BASE64_SRC} gp_ra_report.c) ++ set(INCLUDE_DIR ${SDK_PATH}/include/CA ++ ${LOCAL_ROOT_PATH}/thirdparty/cjson ++ ${LOCAL_ROOT_PATH}/thirdparty/libqca ++ ${LOCAL_ROOT_PATH}/thirdparty/base64url) ++ set(LINK_LIB teec_adaptor) + endif() + ++ ++set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") ++ + include_directories( +- ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${LOCAL_ROOT_PATH}/inc/host_inc +- ${SDK_PATH}/include/CA +- ${LOCAL_ROOT_PATH}/thirdparty/cjson +- ${LOCAL_ROOT_PATH}/thirdparty/libqca +- ${LOCAL_ROOT_PATH}/thirdparty/kunpengsecl/verifier +-) +-add_library(${TARGET} SHARED ${SRC_FILES} ${CJSON_SRC}) +- +-if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") +- target_link_directories(${TARGET} PRIVATE /usr/lib64) +-endif() ++ ${INCLUDE_DIR}) ++add_library(${TARGET} SHARED ${SRC_FILES}) + +-target_link_libraries(${TARGET} teec_adaptor) + +-set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) ++target_link_libraries(${TARGET} ${LINK_LIB}) + + install(TARGETS ${TARGET} + LIBRARY +diff --git a/component/remote_attest/ra_report/gp_ra_helper.c b/component/remote_attest/ra_report/gp_ra_helper.c +deleted file mode 100644 +index 80a01e9..0000000 +--- a/component/remote_attest/ra_report/gp_ra_helper.c ++++ /dev/null +@@ -1,136 +0,0 @@ +-/* +- * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +- * secGear is licensed under the Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +- * PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-#include "gp_ra_helper.h" +- +-#include +-#include "cJSON.h" +-#include "custom_base64url.h" +-#include "enclave_log.h" +- +-void free_gp_ra_buf(cc_ra_buf_t *ra_buf) +-{ +- if (ra_buf->buf != NULL) { +- free(ra_buf->buf); +- } +- if (ra_buf != NULL) { +- free(ra_buf); +- } +-} +- +-/* caller need to free (cc_ra_buf_t **in) */ +-cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in) +-{ +- cc_enclave_result_t ret = CC_SUCCESS; +- cJSON *in_json = cJSON_CreateObject(); +- cJSON_AddStringToObject(in_json, "handler", "provisioning-input"); +- +- cJSON *in_payload = cJSON_CreateObject(); +- cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); +- cJSON_AddStringToObject(in_payload, "scenario", "sce_no_as"); +- cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); +- +- cJSON_AddItemToObject(in_json, "payload", in_payload); +- +- // char *in_buf = cJSON_PrintUnformatted(in_json); +- char *in_buf = cJSON_Print(in_json); +- uint32_t in_buf_len = strlen(in_buf) + 1; +- +- print_debug("provision input json buf:%s\n", in_buf); +- +- cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); +- if (tmp_ra_buf == NULL) { +- ret = CC_ERROR_RA_MEMORY; +- goto end; +- } +- tmp_ra_buf->buf = calloc(1, in_buf_len); +- if (tmp_ra_buf->buf == NULL) { +- ret = CC_ERROR_RA_MEMORY; +- free(tmp_ra_buf); +- goto end; +- } +- (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); +- tmp_ra_buf->len = in_buf_len; +- +- *in = tmp_ra_buf; +-end: +- cJSON_free(in_buf); +- cJSON_Delete(in_json); +- return ret; +-} +- +-/* caller need to free (cc_ra_buf_t **in) */ +-cc_enclave_result_t gen_ra_report_in_buff(gp_get_ra_report_input_t *param, cc_ra_buf_t **json_buf) +-{ +- cc_enclave_result_t ret = CC_SUCCESS; +- cJSON *in_json = cJSON_CreateObject(); +- cJSON_AddStringToObject(in_json, "handler", "report-input"); +- +- char b64_nonce[MAX_NONCE_BUF_LEN] = {0}; +- int b64_nonce_len = MAX_NONCE_BUF_LEN; +- base64urlencode(param->nonce, param->nonce_len, (uint8_t *)b64_nonce, &b64_nonce_len); +- print_debug("nonce_buf_len:%d, nonce_buf:%s\n", b64_nonce_len, b64_nonce); +- +- cJSON *in_payload = cJSON_CreateObject(); +- cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); +- cJSON_AddStringToObject(in_payload, "nonce", b64_nonce); +- cJSON_AddStringToObject(in_payload, "uuid", (char *)param->uuid); +- cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); +- cJSON_AddBoolToObject(in_payload, "with_tcb", param->with_tcb); +- +- cJSON_AddItemToObject(in_json, "payload", in_payload); +- +- // char *in_buf = cJSON_PrintUnformatted(in_json); +- char *in_buf = cJSON_Print(in_json); +- uint32_t in_buf_len = strlen(in_buf) + 1; +- +- print_debug("get ra report input json buf:%s\n", in_buf); +- +- cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); +- if (tmp_ra_buf == NULL) { +- ret = CC_ERROR_RA_MEMORY; +- goto end; +- } +- tmp_ra_buf->buf = calloc(1, in_buf_len); +- if (tmp_ra_buf->buf == NULL) { +- ret = CC_ERROR_RA_MEMORY; +- free(tmp_ra_buf); +- goto end; +- } +- (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); +- tmp_ra_buf->len = in_buf_len; +- +- *json_buf = (cc_ra_buf_t *)tmp_ra_buf; +-end: +- cJSON_free(in_buf); +- cJSON_Delete(in_json); +- return ret; +-} +- +-void print_ra_report(cc_ra_buf_t *report) +-{ +- cJSON *cj_report = cJSON_ParseWithLength((char *)report->buf, report->len); +- if (cj_report == NULL) { +- print_debug("cjson parse report error!\n"); +- return; +- } +- char *str_report = cJSON_Print(cj_report); +- +- print_debug("report:%s\n", str_report); +- +- cJSON_free(str_report); +- cJSON_Delete(cj_report); +- return; +-} +- +- +- +diff --git a/component/remote_attest/ra_report/gp_ra_report.c b/component/remote_attest/ra_report/gp_ra_report.c +index dd02d7d..978127a 100644 +--- a/component/remote_attest/ra_report/gp_ra_report.c ++++ b/component/remote_attest/ra_report/gp_ra_report.c +@@ -13,12 +13,142 @@ + #include "gp_ra_report.h" + + #include +-#include "gp_ra_helper.h" ++#include + #include "ra_client_api.h" + #include "enclave_log.h" ++#include "cJSON.h" ++#include "base64url.h" + +-#define TEST_REPORT_OUT_LEN 0x3000 +-cc_enclave_result_t gp_ra_provision_no_as() ++#include "uni_ree_agent.h" ++ ++static void free_cc_ra_buf(cc_ra_buf_t *ra_buf) ++{ ++ if (ra_buf == NULL) { ++ return; ++ } ++ if (ra_buf->buf != NULL) { ++ free(ra_buf->buf); ++ } ++ ++ free(ra_buf); ++ return; ++} ++ ++/* caller need to free (cc_ra_buf_t **in) */ ++static cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in) ++{ ++ if (in == NULL) { ++ return CC_ERROR_BAD_PARAMETERS; ++ } ++ cc_enclave_result_t ret = CC_SUCCESS; ++ cJSON *in_json = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_json, "handler", "provisioning-input"); ++ ++ cJSON *in_payload = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); ++ cJSON_AddStringToObject(in_payload, "scenario", "sce_no_as"); ++ cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); ++ ++ cJSON_AddItemToObject(in_json, "payload", in_payload); ++ ++ char *in_buf = cJSON_PrintUnformatted(in_json); ++ uint32_t in_buf_len = strlen(in_buf) + 1; ++ ++ cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); ++ if (tmp_ra_buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ goto end; ++ } ++ tmp_ra_buf->buf = calloc(1, in_buf_len); ++ if (tmp_ra_buf->buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ free(tmp_ra_buf); ++ goto end; ++ } ++ (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); ++ tmp_ra_buf->len = in_buf_len; ++ ++ *in = tmp_ra_buf; ++end: ++ cJSON_free(in_buf); ++ cJSON_Delete(in_json); ++ return ret; ++} ++ ++/* caller need to free (cc_ra_buf_t **in) */ ++static cc_enclave_result_t gen_ra_report_in_buff(cc_get_ra_report_input_t *param, cc_ra_buf_t **json_buf) ++{ ++ if (param == NULL || param->taid == NULL || json_buf == NULL) { ++ return CC_ERROR_BAD_PARAMETERS; ++ } ++ cc_enclave_result_t ret = CC_SUCCESS; ++ cJSON *in_json = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_json, "handler", "report-input"); ++ ++ size_t b64_nonce_len = 0; ++ char *b64_nonce = kpsecl_base64urlencode(param->nonce, param->nonce_len, &b64_nonce_len); ++ ++ cJSON *in_payload = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); ++ cJSON_AddStringToObject(in_payload, "nonce", b64_nonce); ++ free(b64_nonce); ++ cJSON_AddStringToObject(in_payload, "uuid", (char *)param->taid); ++ cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); ++ cJSON_AddBoolToObject(in_payload, "with_tcb", param->with_tcb); ++ if (param->req_key) { ++ cJSON_AddBoolToObject(in_payload, "request_key", param->req_key); ++ } ++ ++ cJSON_AddItemToObject(in_json, "payload", in_payload); ++ ++ char *in_buf = cJSON_PrintUnformatted(in_json); ++ uint32_t in_buf_len = strlen(in_buf) + 1; ++ ++ print_debug("get ra report input json buf:%s\n", in_buf); ++ ++ cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); ++ if (tmp_ra_buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ goto end; ++ } ++ tmp_ra_buf->buf = calloc(1, in_buf_len); ++ if (tmp_ra_buf->buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ free(tmp_ra_buf); ++ goto end; ++ } ++ (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); ++ tmp_ra_buf->len = in_buf_len; ++ ++ *json_buf = (cc_ra_buf_t *)tmp_ra_buf; ++end: ++ cJSON_free(in_buf); ++ cJSON_Delete(in_json); ++ return ret; ++} ++ ++static void print_ra_report(cc_ra_buf_t *report) ++{ ++ if (report == NULL || report->buf == NULL) { ++ return; ++ } ++ cJSON *cj_report = cJSON_ParseWithLength((char *)report->buf, report->len); ++ if (cj_report == NULL) { ++ // print_debug("cjson parse report error!\n"); ++ return; ++ } ++ char *str_report = cJSON_Print(cj_report); ++ ++ print_debug("report:%s\n", str_report); ++ print_debug("report len:%u, str_len:%lu\n", report->len, strlen(str_report)); ++ ++ cJSON_free(str_report); ++ cJSON_Delete(cj_report); ++ return; ++} ++ ++#define PROVISION_OUT_LEN 0x3000 ++static cc_enclave_result_t gp_ra_provision_no_as() + { + cc_ra_buf_t *in = NULL; + cc_enclave_result_t ret; +@@ -27,11 +157,11 @@ cc_enclave_result_t gp_ra_provision_no_as() + if (ret != CC_SUCCESS) { + return ret; + } +- uint8_t data[TEST_REPORT_OUT_LEN] = {0}; +- cc_ra_buf_t report = {TEST_REPORT_OUT_LEN, data}; ++ uint8_t data[PROVISION_OUT_LEN] = {0}; ++ cc_ra_buf_t out = {PROVISION_OUT_LEN, data}; + +- TEEC_Result gp_ret = RemoteAttest((struct ra_buffer_data *)in, (struct ra_buffer_data *)&report); +- free_gp_ra_buf(in); ++ TEEC_Result gp_ret = RemoteAttest((struct ra_buffer_data *)in, (struct ra_buffer_data *)&out); ++ free_cc_ra_buf(in); + + if (gp_ret != TEEC_SUCCESS) { + print_error_term("gp ra provision no as failed ret:%x\n", gp_ret); +@@ -44,7 +174,7 @@ cc_enclave_result_t gp_ra_provision_no_as() + cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario) + { + cc_enclave_result_t ret = CC_SUCCESS; +- switch(scenario) { ++ switch (scenario) { + case CC_RA_SCENARIO_NO_AS: + ret = gp_ra_provision_no_as(); + break; +@@ -54,16 +184,31 @@ cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario) + return ret; + } + +-cc_enclave_result_t gp_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report) ++cc_enclave_result_t gp_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report) + { +- TEEC_Result gp_ret = RemoteAttest((struct ra_buffer_data *)in, (struct ra_buffer_data *)report); ++ cc_ra_buf_t *ra_buf_in = NULL; ++ cc_enclave_result_t ret = gen_ra_report_in_buff(in, &ra_buf_in); ++ if (ret != CC_SUCCESS) { ++ print_error_term("gen ra report ra buf in failed\n"); ++ return CC_FAIL; ++ } ++ TEEC_Result gp_ret = RemoteAttest((struct ra_buffer_data *)ra_buf_in, (struct ra_buffer_data *)report); ++ free_cc_ra_buf(ra_buf_in); + if (gp_ret != TEEC_SUCCESS) { + print_error_term("get ra report failed, ret:%x\n", gp_ret); + return CC_ERROR_RA_GET_REPORT; + } ++ print_ra_report(report); + + return CC_SUCCESS; + } + +- +- ++uni_ree_agent_t g_gp_agent = { ++ .tee_type = CC_TEE_TYPE_GP, ++ .prepare_ra_env = gp_prepare_ra_env, ++ .get_ra_report = gp_get_ra_report, ++}; ++static __attribute__((constructor)) void gp_register_ree_agent() ++{ ++ cc_register_ree_agent(&g_gp_agent); ++} +\ No newline at end of file +diff --git a/component/remote_attest/ra_report/gp_ra_report.h b/component/remote_attest/ra_report/gp_ra_report.h +index 9d02ce3..ed58bb0 100644 +--- a/component/remote_attest/ra_report/gp_ra_report.h ++++ b/component/remote_attest/ra_report/gp_ra_report.h +@@ -18,7 +18,7 @@ + + cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario); + +-cc_enclave_result_t gp_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report); ++cc_enclave_result_t gp_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report); + + #endif + +diff --git a/component/remote_attest/ra_report/sg_ra_report.c b/component/remote_attest/ra_report/sg_ra_report.c +index 1cc4bdc..21ad417 100644 +--- a/component/remote_attest/ra_report/sg_ra_report.c ++++ b/component/remote_attest/ra_report/sg_ra_report.c +@@ -9,18 +9,30 @@ + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ ++#include "sg_ra_report.h" ++#include "uni_ree_agent.h" + +-#include "gp_ra_report.h" +- ++static uni_ree_agent_t *g_ree_agent = NULL; + cc_enclave_result_t cc_prepare_ra_env(cc_ra_scenario_t scenario) + { +- return gp_prepare_ra_env(scenario); ++ if (g_ree_agent == NULL) { ++ return CC_ERROR_REE_AGENT_NOT_INIT; ++ } ++ return g_ree_agent->prepare_ra_env(scenario); + } + +-cc_enclave_result_t cc_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report) ++cc_enclave_result_t cc_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report) + { +- return gp_get_ra_report(in, report); ++ if (in == NULL || in->taid == NULL || report == NULL || report->buf == NULL) { ++ return CC_ERROR_BAD_PARAMETERS; ++ } ++ if (g_ree_agent == NULL) { ++ return CC_ERROR_REE_AGENT_NOT_INIT; ++ } ++ return g_ree_agent->get_ra_report(in, report); + } + +- +- ++void cc_register_ree_agent(uni_ree_agent_t *agent) ++{ ++ g_ree_agent = agent; ++} +diff --git a/component/remote_attest/ra_report/sg_ra_report.h b/component/remote_attest/ra_report/sg_ra_report.h +index 960cb02..f3294c5 100644 +--- a/component/remote_attest/ra_report/sg_ra_report.h ++++ b/component/remote_attest/ra_report/sg_ra_report.h +@@ -24,8 +24,17 @@ extern "C" { + + CC_API_SPEC cc_enclave_result_t cc_prepare_ra_env(cc_ra_scenario_t scenario); + +-CC_API_SPEC cc_enclave_result_t cc_get_ra_report(cc_ra_buf_t *in, cc_ra_buf_t *report); +- ++/** ++* get remote attestation report ++* ++* @param[in] in, bytes of input ++* ++* @param[out] report, remote attestion report, 0x3000 =< len < 0x100000 ++* ++* @retval, On success, return 0. ++* On error, cc_enclave_result_t errorno is returned. ++*/ ++CC_API_SPEC cc_enclave_result_t cc_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report); + + #ifdef __cplusplus + } +diff --git a/component/remote_attest/ra_report/sgx_ra_report.c b/component/remote_attest/ra_report/sgx_ra_report.c +new file mode 100644 +index 0000000..8d02fc3 +--- /dev/null ++++ b/component/remote_attest/ra_report/sgx_ra_report.c +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#include "sgx_ra_report.h" ++#include "uni_ree_agent.h" ++ ++cc_enclave_result_t sgx_prepare_ra_env(cc_ra_scenario_t scenario) ++{ ++ (void)scenario; ++ return CC_SUCCESS; ++} ++ ++cc_enclave_result_t sgx_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report) ++{ ++ (void)in; ++ (void)report; ++ ++ return CC_SUCCESS; ++} ++ ++uni_ree_agent_t g_sgx_agent = { ++ .tee_type = CC_TEE_TYPE_SGX, ++ .prepare_ra_env = sgx_prepare_ra_env, ++ .get_ra_report = sgx_get_ra_report, ++}; ++static __attribute__((constructor)) void sgx_register_ree_agent() ++{ ++ cc_register_ree_agent(&g_sgx_agent); ++} +\ No newline at end of file +diff --git a/component/remote_attest/ra_report/sgx_ra_report.h b/component/remote_attest/ra_report/sgx_ra_report.h +new file mode 100644 +index 0000000..d9a33cc +--- /dev/null ++++ b/component/remote_attest/ra_report/sgx_ra_report.h +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_SGX_RA_REPORT_H ++#define SECGEAR_SGX_RA_REPORT_H ++ ++#include "status.h" ++#include "sg_report_st.h" ++ ++cc_enclave_result_t sgx_prepare_ra_env(cc_ra_scenario_t scenario); ++ ++cc_enclave_result_t sgx_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report); ++ ++#endif ++ +diff --git a/component/remote_attest/ra_report/uni_ree_agent.h b/component/remote_attest/ra_report/uni_ree_agent.h +new file mode 100644 +index 0000000..65a46d1 +--- /dev/null ++++ b/component/remote_attest/ra_report/uni_ree_agent.h +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_UNI_REE_AGENT_H ++#define SECGEAR_UNI_REE_AGENT_H ++ ++#include ++#include "status.h" ++#include "sg_report_st.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef cc_enclave_result_t (*uni_prepare_ra_env_proc_t)(cc_ra_scenario_t scenario); ++typedef cc_enclave_result_t (*uni_get_ra_report_proc_t)(cc_get_ra_report_input_t *in, cc_ra_buf_t *report); ++ ++typedef enum { ++ CC_TEE_TYPE_GP, ++ CC_TEE_TYPE_SGX, ++} cc_tee_type_t; ++ ++typedef struct { ++ cc_tee_type_t tee_type; ++ uni_prepare_ra_env_proc_t prepare_ra_env; ++ uni_get_ra_report_proc_t get_ra_report; ++} uni_ree_agent_t; ++ ++void cc_register_ree_agent(uni_ree_agent_t *agent); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/component/remote_attest/ra_verify/CMakeLists.txt b/component/remote_attest/ra_verify/CMakeLists.txt +index fc92d9c..53707b1 100644 +--- a/component/remote_attest/ra_verify/CMakeLists.txt ++++ b/component/remote_attest/ra_verify/CMakeLists.txt +@@ -13,10 +13,21 @@ project(sg_ra_verify C) + set(TARGET secgear_verify) + aux_source_directory(. SRC_FILES) + ++set(SRC_FILES sg_ra_report_verify.c) ++if(CC_SGX) ++set(SRC_FILES ${SRC_FILES} sgx_ra_report_verify.c) ++endif() ++ ++if(CC_GP) ++ set(SRC_FILES ${SRC_FILES} gp_ra_report_verify.c) ++ set(INCLUDE_DIR ${LOCAL_ROOT_PATH}/thirdparty/kunpengsecl/verifier) ++ #set(LINK_LIB teeverifier) ++endif() ++ + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") +- link_directories(/usr/lib64) ++ link_directories(/usr/local/lib) + endif() + + include_directories( +@@ -24,17 +35,15 @@ include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${LOCAL_ROOT_PATH}/inc/host_inc +- ${LOCAL_ROOT_PATH}/thirdparty/kunpengsecl/verifier ++ ${INCLUDE_DIR} + ) + add_library(${TARGET} SHARED ${SRC_FILES}) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") +- target_link_directories(${TARGET} PRIVATE /usr/lib64) ++ target_link_directories(${TARGET} PRIVATE /usr/local/lib) + endif() + +-target_link_libraries(${TARGET}) +- +-set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) ++target_link_libraries(${TARGET} ${LINK_LIB}) + + install(TARGETS ${TARGET} + LIBRARY +diff --git a/component/remote_attest/ra_verify/gp_ra_report_verify.c b/component/remote_attest/ra_verify/gp_ra_report_verify.c +index 0917f7a..76debb4 100644 +--- a/component/remote_attest/ra_verify/gp_ra_report_verify.c ++++ b/component/remote_attest/ra_verify/gp_ra_report_verify.c +@@ -15,19 +15,22 @@ + #include "teeverifier.h" + #include "enclave_log.h" + ++#include "uni_ra_verify_agent.h" ++ + int convert_cctype_to_gptype(cc_ra_verify_type_t type) + { + // gp type, 1: compare image hash; 2: compare mem hash; 3: compare image and mem hash + if (type == CC_RA_VERIFY_TYPE_LOOSE) { +- return 1; ++ return 1; + } else if (type == CC_RA_VERIFY_TYPE_STRICT) { +- return 3; ++ return 3; // 3: compare image and mem hash + } else { + return CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE; + } + } + +-cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue) ++cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, ++ cc_ra_verify_type_t type, char *basevalue) + { + int gp_type = convert_cctype_to_gptype(type); + if (gp_type == (int)CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE) { +@@ -44,7 +47,15 @@ cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc + case TVS_VERIFIED_HASH_FAILED: + return CC_ERROR_RA_REPORT_VERIFY_HASH; + default: +- print_debug("verify report failed, unknown errorcode:%d!\n", ret); ++ printf("verify report failed, unknown errorcode:%d!\n", ret); + } + return ret; ++} ++ ++uni_ra_verify_agent_t g_gp_ra_verify_agent = { ++ .verify_ra_report = gp_verify_report, ++}; ++static __attribute__((constructor)) void gp_register_ra_agent() ++{ ++ cc_register_ra_verify_agent(&g_gp_ra_verify_agent); + } +\ No newline at end of file +diff --git a/component/remote_attest/ra_verify/gp_ra_report_verify.h b/component/remote_attest/ra_verify/gp_ra_report_verify.h +index ffd8387..68a7c38 100644 +--- a/component/remote_attest/ra_verify/gp_ra_report_verify.h ++++ b/component/remote_attest/ra_verify/gp_ra_report_verify.h +@@ -10,18 +10,18 @@ + * See the Mulan PSL v2 for more details. + */ + +-#ifndef SECGEAR_GP_VERIFY_REPORT_H +-#define SECGEAR_GP_VERIFY_REPORT_H ++#ifndef SECGEAR_GP_RA_REPORT_VERIFY_H ++#define SECGEAR_GP_RA_REPORT_VERIFY_H + + #include "status.h" +-#include "secgear_defs.h" + #include "sg_report_st.h" + + #ifdef __cplusplus + extern "C" { + #endif + +-CC_API_SPEC cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue); ++cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, ++ cc_ra_verify_type_t type, char *basevalue); + + #ifdef __cplusplus + } +diff --git a/component/remote_attest/ra_verify/sg_ra_report_verify.c b/component/remote_attest/ra_verify/sg_ra_report_verify.c +index 63f26c4..b85615b 100644 +--- a/component/remote_attest/ra_verify/sg_ra_report_verify.c ++++ b/component/remote_attest/ra_verify/sg_ra_report_verify.c +@@ -10,11 +10,23 @@ + * See the Mulan PSL v2 for more details. + */ + +-#include "gp_ra_report_verify.h" ++#include "sg_ra_report_verify.h" ++#include "uni_ra_verify_agent.h" + +-#include "enclave_log.h" ++static uni_ra_verify_agent_t *g_ra_agent = NULL; + + cc_enclave_result_t cc_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue) + { +- return gp_verify_report(report, nonce, type, basevalue); ++ if (report == NULL || report->buf == NULL || nonce == NULL || nonce->buf == NULL || basevalue == NULL) { ++ return CC_ERROR_BAD_PARAMETERS; ++ } ++ if (g_ra_agent == NULL) { ++ return CC_ERROR_RA_VERIFY_AGENT_NOT_INIT; ++ } ++ return g_ra_agent->verify_ra_report(report, nonce, type, basevalue); ++} ++ ++void cc_register_ra_verify_agent(uni_ra_verify_agent_t *agent) ++{ ++ g_ra_agent = agent; + } +\ No newline at end of file +diff --git a/component/remote_attest/ra_verify/sg_ra_report_verify.h b/component/remote_attest/ra_verify/sg_ra_report_verify.h +index 92ca953..b566cef 100644 +--- a/component/remote_attest/ra_verify/sg_ra_report_verify.h ++++ b/component/remote_attest/ra_verify/sg_ra_report_verify.h +@@ -10,8 +10,8 @@ + * See the Mulan PSL v2 for more details. + */ + +-#ifndef SECGEAR_VERIFY_REPORT_H +-#define SECGEAR_VERIFY_REPORT_H ++#ifndef SECGEAR_RA_VERIFY_REPORT_H ++#define SECGEAR_RA_VERIFY_REPORT_H + + #include "status.h" + #include "secgear_defs.h" +@@ -21,7 +21,8 @@ + extern "C" { + #endif + +-CC_API_SPEC cc_enclave_result_t cc_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, cc_ra_verify_type_t type, char *basevalue); ++CC_API_SPEC cc_enclave_result_t cc_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, ++ cc_ra_verify_type_t type, char *basevalue); + + #ifdef __cplusplus + } +diff --git a/component/remote_attest/ra_verify/sgx_ra_report_verify.c b/component/remote_attest/ra_verify/sgx_ra_report_verify.c +new file mode 100644 +index 0000000..0e2e81f +--- /dev/null ++++ b/component/remote_attest/ra_verify/sgx_ra_report_verify.c +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#include "sgx_ra_report_verify.h" ++ ++#include "uni_ra_verify_agent.h" ++ ++cc_enclave_result_t sgx_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, ++ cc_ra_verify_type_t type, char *basevalue) ++{ ++ (void)report; ++ (void)nonce; ++ (void)type; ++ (void)basevalue; ++ return CC_SUCCESS; ++} ++ ++uni_ra_verify_agent_t g_sgx_ra_verify_agent = { ++ .verify_ra_report = sgx_verify_report, ++}; ++static __attribute__((constructor)) void gp_register_ra_agent() ++{ ++ cc_register_ra_verify_agent(&g_sgx_ra_verify_agent); ++} +\ No newline at end of file +diff --git a/component/remote_attest/ra_verify/sgx_ra_report_verify.h b/component/remote_attest/ra_verify/sgx_ra_report_verify.h +new file mode 100644 +index 0000000..773f484 +--- /dev/null ++++ b/component/remote_attest/ra_verify/sgx_ra_report_verify.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_SGX_RA_REPORT_VERIFY_H ++#define SECGEAR_SGX_RA_REPORT_VERIFY_H ++ ++#include "status.h" ++#include "sg_report_st.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++cc_enclave_result_t sgx_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, ++ cc_ra_verify_type_t type, char *basevalue); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/component/remote_attest/ra_report/gp_ra_helper.h b/component/remote_attest/ra_verify/uni_ra_verify_agent.h +similarity index 57% +rename from component/remote_attest/ra_report/gp_ra_helper.h +rename to component/remote_attest/ra_verify/uni_ra_verify_agent.h +index 6bee143..d1e1995 100644 +--- a/component/remote_attest/ra_report/gp_ra_helper.h ++++ b/component/remote_attest/ra_verify/uni_ra_verify_agent.h +@@ -10,25 +10,28 @@ + * See the Mulan PSL v2 for more details. + */ + +-#ifndef SECGEAR_RA_HELPER_H +-#define SECGEAR_RA_HELPER_H ++#ifndef SECGEAR_UNI_RA_VERIFY_AGENT_H ++#define SECGEAR_UNI_RA_VERIFY_AGENT_H + + #include +-#include + #include "status.h" + #include "sg_report_st.h" + +-#define MAX_NONCE_BUF_LEN 512 ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef cc_enclave_result_t (*uni_ra_report_verify_proc_t)(cc_ra_buf_t *report, cc_ra_buf_t *nonce, ++ cc_ra_verify_type_t type, char *basevalue); ++ + typedef struct { +- uint8_t *uuid; +- uint32_t nonce_len; +- uint8_t nonce[MAX_NONCE_BUF_LEN]; +- bool with_tcb; +-} gp_get_ra_report_input_t; +- +-cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in); +-cc_enclave_result_t gen_ra_report_in_buff(gp_get_ra_report_input_t *param, cc_ra_buf_t **json_buf); +-void print_ra_report(cc_ra_buf_t *report); +-void free_gp_ra_buf(cc_ra_buf_t *ra_buf); ++ uni_ra_report_verify_proc_t verify_ra_report; ++} uni_ra_verify_agent_t; ++ ++void cc_register_ra_verify_agent(uni_ra_verify_agent_t *agent); ++ ++#ifdef __cplusplus ++} + #endif + ++#endif +diff --git a/component/remote_attest/sg_report_st.h b/component/remote_attest/sg_report_st.h +index 89ee25a..d15a7f9 100644 +--- a/component/remote_attest/sg_report_st.h ++++ b/component/remote_attest/sg_report_st.h +@@ -14,20 +14,19 @@ + #define SECGEAR_REPORT_STRUCT_H + + #include ++#include + + #ifdef __cplusplus + extern "C" { + #endif + +-typedef struct cc_ra_buf { ++typedef struct { + uint32_t len; + uint8_t *buf; + } cc_ra_buf_t; + + typedef enum { + CC_RA_SCENARIO_NO_AS, +- // CC_RA_SCENARIO_AS_NO_DAA, +- // CC_RA_SCENARIO_AS_WITH_DAA + } cc_ra_scenario_t; + + typedef enum { +@@ -36,6 +35,15 @@ typedef enum { + CC_RA_VERIFY_TYPE_MAX + } cc_ra_verify_type_t; + ++#define MAX_NONCE_BUF_LEN 512 ++typedef struct { ++ uint8_t *taid; ++ uint32_t nonce_len; ++ uint8_t nonce[MAX_NONCE_BUF_LEN]; ++ bool with_tcb; ++ bool req_key; ++} cc_get_ra_report_input_t; ++ + #ifdef __cplusplus + } + #endif +diff --git a/inc/host_inc/enclave_internal.h b/inc/host_inc/enclave_internal.h +index a66d1a3..fa0cbf4 100644 +--- a/inc/host_inc/enclave_internal.h ++++ b/inc/host_inc/enclave_internal.h +@@ -141,6 +141,7 @@ uint32_t check_node_exists_add(const struct list_ops_desc *node); + + cc_enclave_result_t conversion_res_status(uint32_t enclave_res, enclave_type_version_t type_version); + ++CC_API_SPEC bool is_support_remote_attest(cc_enclave_t *context); + # ifdef __cplusplus + } + # endif +diff --git a/inc/host_inc/status.h b/inc/host_inc/status.h +index ea7b93b..56f4da4 100644 +--- a/inc/host_inc/status.h ++++ b/inc/host_inc/status.h +@@ -86,6 +86,9 @@ typedef enum _enclave_result_t + CC_ERROR_RA_REPORT_VERIFY_SIGNATURE, + CC_ERROR_RA_REPORT_VERIFY_HASH, + CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE, ++ ++ CC_ERROR_REE_AGENT_NOT_INIT, ++ CC_ERROR_RA_VERIFY_AGENT_NOT_INIT, + /* secure channel */ + CC_ERROR_SEC_CHL_INVALID_CONN, /* invalid connection */ + CC_ERROR_SEC_CHL_LEN_NOT_ENOUGH, /* the buf length to store secure channle encrypt/decrypt is not enough */ +@@ -96,6 +99,7 @@ typedef enum _enclave_result_t + CC_ERROR_SEC_CHL_WAITING_RECV_MSG, + CC_ERROR_SEC_CHL_RECV_MSG_LEN_INVALID, + CC_ERROR_SEC_CHL_GET_SVR_PUBKEY, ++ CC_ERROR_SEC_CHL_PARSE_SVR_PUBKEY, + CC_ERROR_SEC_CHL_GET_PEER_EXCH_PARAM, + CC_ERROR_SEC_CHL_VERIFY_PEER_EXCH_BUF_SIGNATURE, + CC_ERROR_SEC_CHL_INVALID_EXCH_BUF, +@@ -110,6 +114,13 @@ typedef enum _enclave_result_t + CC_ERROR_SEC_CHL_SVR_INIT, + CC_ERROR_SEC_CHL_NOTREADY, + CC_ERROR_SEC_CHL_CLI_NUM_EXCEED_MAX_LIMIT, // client num exceed max limit ++ CC_ERROR_SEC_CHL_INIT_GET_TAID, ++ CC_ERROR_SEC_CHL_GET_RA_REPORT, ++ CC_ERROR_SEC_CHL_INIT_VERIFY_REPORT, ++ CC_ERROR_SEC_CHL_INVALID_REPORT, ++ CC_ERROR_SEC_CHL_ENCLAVE_UNSEAL_ENC_KEY, ++ CC_ERROR_SEC_CHL_INVALID_SESSION, ++ CC_ERROR_SEC_CHL_INIT_SESSEION, + + CC_ERROR_OTRP_BASE = 0x80000100, /* sec file config source is not inconsistent with the loading mode. */ + CC_ERROR_STORAGE_EIO = 0x80001001, /* *<安全存储I/O错误 */ +diff --git a/src/host_src/enclave_internal.c b/src/host_src/enclave_internal.c +index abe121e..24fb95d 100644 +--- a/src/host_src/enclave_internal.c ++++ b/src/host_src/enclave_internal.c +@@ -406,3 +406,13 @@ uint32_t check_node_exists_add(const struct list_ops_desc *node) + } + return res; + } ++ ++bool is_support_remote_attest(cc_enclave_t *context) ++{ ++ if (context->list_ops_node != NULL) { ++ if (context->list_ops_node->ops_desc->type_version == GP_ENCLAVE_TYPE_0) { ++ return true; ++ } ++ } ++ return false; ++} +diff --git a/thirdparty/base64url/b64/LICENSE b/thirdparty/base64url/b64/LICENSE +new file mode 100644 +index 0000000..78b34d5 +--- /dev/null ++++ b/thirdparty/base64url/b64/LICENSE +@@ -0,0 +1,21 @@ ++The MIT License (MIT) ++ ++Copyright (c) 2014 Little Star Media, Inc. ++ ++Permission is hereby granted, free of charge, to any person obtaining a copy ++of this software and associated documentation files (the "Software"), to deal ++in the Software without restriction, including without limitation the rights ++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++copies of the Software, and to permit persons to whom the Software is ++furnished to do so, subject to the following conditions: ++ ++The above copyright notice and this permission notice shall be included in all ++copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ++SOFTWARE. +\ No newline at end of file +diff --git a/thirdparty/base64url/b64/README.md b/thirdparty/base64url/b64/README.md +new file mode 100644 +index 0000000..0555c0d +--- /dev/null ++++ b/thirdparty/base64url/b64/README.md +@@ -0,0 +1,84 @@ ++b64.c ++===== ++ ++Base64 encode/decode ++ ++## install ++ ++```sh ++$ clib install jwerle/b64.c ++``` ++ ++## usage ++ ++```c ++#include ++``` ++ ++or ++ ++```c ++#include ++``` ++ ++## example ++ ++```c ++#include ++#include ++#include ++#include "b64.h" ++ ++int ++main (void) { ++ unsigned char *str = "brian the monkey and bradley the kinkajou are friends"; ++ char *enc = b64_encode(str, strlen(str)); ++ ++ printf("%s\n", enc); // YnJpYW4gdGhlIG1vbmtleSBhbmQgYnJhZGxleSB0aGUga2lua2Fqb3UgYXJlIGZyaWVuZHM= ++ ++ char *dec = b64_decode(enc, strlen(enc)); ++ ++ printf("%s\n", dec); // brian the monkey and bradley the kinkajou are friends ++ free(enc); ++ free(dec); ++ return 0; ++} ++``` ++ ++## api ++ ++Base64 index table ++ ++```c ++ ++static const char b64_table[] = { ++ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', ++ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', ++ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', ++ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', ++ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', ++ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', ++ 'w', 'x', 'y', 'z', '0', '1', '2', '3', ++ '4', '5', '6', '7', '8', '9', '+', '/' ++}; ++``` ++ ++Encode `unsigned char *` source with `size_t` size. ++Returns a `char *` base64 encoded string ++ ++```c ++char * ++b64_encode (const unsigned char *, size_t); ++``` ++ ++Decode `char *` source with `size_t` size. ++Returns a `unsigned char *` base64 decoded string ++ ++```c ++unsigned char * ++b64_decode (const char *, size_t); ++``` ++ ++## license ++ ++MIT +diff --git a/thirdparty/base64url/b64/b64.h b/thirdparty/base64url/b64/b64.h +new file mode 100644 +index 0000000..e39d746 +--- /dev/null ++++ b/thirdparty/base64url/b64/b64.h +@@ -0,0 +1,84 @@ ++ ++/** ++ * `b64.h' - b64 ++ * ++ * copyright (c) 2014 joseph werle ++ */ ++ ++#ifndef B64_H ++#define B64_H 1 ++ ++typedef struct b64_buffer { ++ char * ptr; ++ int bufc; ++} b64_buffer_t; ++ ++/** ++ * Memory allocation functions to use. You can define b64_malloc and ++ * b64_realloc to custom functions if you want. ++ */ ++ ++#ifndef b64_malloc ++# define b64_malloc(ptr) malloc(ptr) ++#endif ++#ifndef b64_realloc ++# define b64_realloc(ptr, size) realloc(ptr, size) ++#endif ++ ++ // How much memory to allocate per buffer ++#define B64_BUFFER_SIZE (1024 * 64) // 64K ++ ++ // Start buffered memory ++int b64_buf_malloc(b64_buffer_t * buffer); ++ ++// Update memory size. Returns the same pointer if we ++// have enough space in the buffer. Otherwise, we add ++// additional buffers. ++int b64_buf_realloc(b64_buffer_t * buffer, size_t size); ++ ++/** ++ * Base64 index table. ++ */ ++ ++static const char b64_table[] = { ++ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', ++ 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', ++ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', ++ 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', ++ 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', ++ 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', ++ 'w', 'x', 'y', 'z', '0', '1', '2', '3', ++ '4', '5', '6', '7', '8', '9', '+', '/' ++}; ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * Encode `unsigned char *' source with `size_t' size. ++ * Returns a `char *' base64 encoded string. ++ */ ++ ++char * ++b64_encode (const unsigned char *, size_t); ++ ++/** ++ * Decode `char *' source with `size_t' size. ++ * Returns a `unsigned char *' base64 decoded string. ++ */ ++unsigned char * ++b64_decode (const char *, size_t); ++ ++/** ++ * Decode `char *' source with `size_t' size. ++ * Returns a `unsigned char *' base64 decoded string + size of decoded string. ++ */ ++unsigned char * ++b64_decode_ex (const char *, size_t, size_t *); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/thirdparty/base64url/b64/buffer.c b/thirdparty/base64url/b64/buffer.c +new file mode 100644 +index 0000000..708c882 +--- /dev/null ++++ b/thirdparty/base64url/b64/buffer.c +@@ -0,0 +1,33 @@ ++#include ++#include ++#include "b64.h" ++ ++#ifdef b64_USE_CUSTOM_MALLOC ++extern void* b64_malloc(size_t); ++#endif ++ ++#ifdef b64_USE_CUSTOM_REALLOC ++extern void* b64_realloc(void*, size_t); ++#endif ++ ++int b64_buf_malloc(b64_buffer_t * buf) ++{ ++ buf->ptr = b64_malloc(B64_BUFFER_SIZE); ++ if(!buf->ptr) return -1; ++ ++ buf->bufc = 1; ++ ++ return 0; ++} ++ ++int b64_buf_realloc(b64_buffer_t* buf, size_t size) ++{ ++ if (size > (size_t)buf->bufc * B64_BUFFER_SIZE) ++ { ++ while (size > (size_t)buf->bufc * B64_BUFFER_SIZE) buf->bufc++; ++ buf->ptr = b64_realloc(buf->ptr, B64_BUFFER_SIZE * buf->bufc); ++ if (!buf->ptr) return -1; ++ } ++ ++ return 0; ++} +diff --git a/thirdparty/base64url/b64/decode.c b/thirdparty/base64url/b64/decode.c +new file mode 100644 +index 0000000..38093bb +--- /dev/null ++++ b/thirdparty/base64url/b64/decode.c +@@ -0,0 +1,117 @@ ++ ++/** ++ * `decode.c' - b64 ++ * ++ * copyright (c) 2014 joseph werle ++ */ ++ ++#include ++#include ++#include ++#include "b64.h" ++ ++#ifdef b64_USE_CUSTOM_MALLOC ++extern void* b64_malloc(size_t); ++#endif ++ ++#ifdef b64_USE_CUSTOM_REALLOC ++extern void* b64_realloc(void*, size_t); ++#endif ++ ++unsigned char * ++b64_decode (const char *src, size_t len) { ++ return b64_decode_ex(src, len, NULL); ++} ++ ++unsigned char * ++b64_decode_ex (const char *src, size_t len, size_t *decsize) { ++ int i = 0; ++ int j = 0; ++ int l = 0; ++ size_t size = 0; ++ b64_buffer_t decbuf; ++ unsigned char buf[3]; ++ unsigned char tmp[4]; ++ ++ // alloc ++ if (b64_buf_malloc(&decbuf) == -1) { return NULL; } ++ ++ // parse until end of source ++ while (len--) { ++ // break if char is `=' or not base64 char ++ if ('=' == src[j]) { break; } ++ if (!(isalnum(src[j]) || '+' == src[j] || '/' == src[j])) { break; } ++ ++ // read up to 4 bytes at a time into `tmp' ++ tmp[i++] = src[j++]; ++ ++ // if 4 bytes read then decode into `buf' ++ if (4 == i) { ++ // translate values in `tmp' from table ++ for (i = 0; i < 4; ++i) { ++ // find translation char in `b64_table' ++ for (l = 0; l < 64; ++l) { ++ if (tmp[i] == b64_table[l]) { ++ tmp[i] = l; ++ break; ++ } ++ } ++ } ++ ++ // decode ++ buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4); ++ buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2); ++ buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3]; ++ ++ // write decoded buffer to `decbuf.ptr' ++ if (b64_buf_realloc(&decbuf, size + 3) == -1) return NULL; ++ for (i = 0; i < 3; ++i) { ++ ((unsigned char*)decbuf.ptr)[size++] = buf[i]; ++ } ++ ++ // reset ++ i = 0; ++ } ++ } ++ ++ // remainder ++ if (i > 0) { ++ // fill `tmp' with `\0' at most 4 times ++ for (j = i; j < 4; ++j) { ++ tmp[j] = '\0'; ++ } ++ ++ // translate remainder ++ for (j = 0; j < 4; ++j) { ++ // find translation char in `b64_table' ++ for (l = 0; l < 64; ++l) { ++ if (tmp[j] == b64_table[l]) { ++ tmp[j] = l; ++ break; ++ } ++ } ++ } ++ ++ // decode remainder ++ buf[0] = (tmp[0] << 2) + ((tmp[1] & 0x30) >> 4); ++ buf[1] = ((tmp[1] & 0xf) << 4) + ((tmp[2] & 0x3c) >> 2); ++ buf[2] = ((tmp[2] & 0x3) << 6) + tmp[3]; ++ ++ // write remainer decoded buffer to `decbuf.ptr' ++ if (b64_buf_realloc(&decbuf, size + (i - 1)) == -1) return NULL; ++ for (j = 0; (j < i - 1); ++j) { ++ ((unsigned char*)decbuf.ptr)[size++] = buf[j]; ++ } ++ } ++ ++ // Make sure we have enough space to add '\0' character at end. ++ if (b64_buf_realloc(&decbuf, size + 1) == -1) return NULL; ++ ((unsigned char*)decbuf.ptr)[size] = '\0'; ++ ++ // Return back the size of decoded string if demanded. ++ if (decsize != NULL) { ++ *decsize = size; ++ } ++ ++ return (unsigned char*) decbuf.ptr; ++} +diff --git a/thirdparty/base64url/b64/encode.c b/thirdparty/base64url/b64/encode.c +new file mode 100644 +index 0000000..68e7924 +--- /dev/null ++++ b/thirdparty/base64url/b64/encode.c +@@ -0,0 +1,93 @@ ++ ++/** ++ * `encode.c' - b64 ++ * ++ * copyright (c) 2014 joseph werle ++ */ ++ ++#include ++#include ++#include "b64.h" ++ ++#ifdef b64_USE_CUSTOM_MALLOC ++extern void* b64_malloc(size_t); ++#endif ++ ++#ifdef b64_USE_CUSTOM_REALLOC ++extern void* b64_realloc(void*, size_t); ++#endif ++ ++char * ++b64_encode (const unsigned char *src, size_t len) { ++ int i = 0; ++ int j = 0; ++ b64_buffer_t encbuf; ++ size_t size = 0; ++ unsigned char buf[4]; ++ unsigned char tmp[3]; ++ ++ // alloc ++ if(b64_buf_malloc(&encbuf) == -1) { return NULL; } ++ ++ // parse until end of source ++ while (len--) { ++ // read up to 3 bytes at a time into `tmp' ++ tmp[i++] = *(src++); ++ ++ // if 3 bytes read then encode into `buf' ++ if (3 == i) { ++ buf[0] = (tmp[0] & 0xfc) >> 2; ++ buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4); ++ buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6); ++ buf[3] = tmp[2] & 0x3f; ++ ++ // allocate 4 new byts for `enc` and ++ // then translate each encoded buffer ++ // part by index from the base 64 index table ++ // into `encbuf.ptr' unsigned char array ++ if (b64_buf_realloc(&encbuf, size + 4) == -1) return NULL; ++ ++ for (i = 0; i < 4; ++i) { ++ encbuf.ptr[size++] = b64_table[buf[i]]; ++ } ++ ++ // reset index ++ i = 0; ++ } ++ } ++ ++ // remainder ++ if (i > 0) { ++ // fill `tmp' with `\0' at most 3 times ++ for (j = i; j < 3; ++j) { ++ tmp[j] = '\0'; ++ } ++ ++ // perform same codec as above ++ buf[0] = (tmp[0] & 0xfc) >> 2; ++ buf[1] = ((tmp[0] & 0x03) << 4) + ((tmp[1] & 0xf0) >> 4); ++ buf[2] = ((tmp[1] & 0x0f) << 2) + ((tmp[2] & 0xc0) >> 6); ++ buf[3] = tmp[2] & 0x3f; ++ ++ // perform same write to `encbuf->ptr` with new allocation ++ for (j = 0; (j < i + 1); ++j) { ++ if (b64_buf_realloc(&encbuf, size + 1) == -1) return NULL; ++ ++ encbuf.ptr[size++] = b64_table[buf[j]]; ++ } ++ ++ // while there is still a remainder ++ // append `=' to `encbuf.ptr' ++ while ((i++ < 3)) { ++ if (b64_buf_realloc(&encbuf, size + 1) == -1) return NULL; ++ ++ encbuf.ptr[size++] = '='; ++ } ++ } ++ ++ // Make sure we have enough space to add '\0' character at end. ++ if (b64_buf_realloc(&encbuf, size + 1) == -1) return NULL; ++ encbuf.ptr[size] = '\0'; ++ ++ return encbuf.ptr; ++} +diff --git a/thirdparty/base64url/b64/notes.md b/thirdparty/base64url/b64/notes.md +new file mode 100644 +index 0000000..63d23ba +--- /dev/null ++++ b/thirdparty/base64url/b64/notes.md +@@ -0,0 +1,10 @@ ++## b64.c ++ ++### Download ++ ++This library can be downloaded from address https://github.com/jwerle/b64.c. ++ ++### Version ++ ++The version of this library is **tag 0.1.0**. ++ +diff --git a/thirdparty/base64url/base64url.c b/thirdparty/base64url/base64url.c +new file mode 100644 +index 0000000..0cb5eb1 +--- /dev/null ++++ b/thirdparty/base64url/base64url.c +@@ -0,0 +1,74 @@ ++/* ++kunpengsecl 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. ++ ++Author: leezhenxiang ++Create: 2022-11-04 ++Description: ta authenticating module in kta. ++ 1. 2022-11-04 leezhenxiang ++ define the structures. ++*/ ++#include "base64url.h" ++ ++#include ++#include ++#include "b64/b64.h" ++ ++//Encode unsigned char source to base64url. ++//Neither of param source_len or dest_len include character '\0'. ++//Return the first address of encoded string. 【warning】caller need free return ptr ++char* kpsecl_base64urlencode(const uint8_t *source, size_t source_len, size_t *dest_len) { ++ char *dest = b64_encode(source, source_len); ++ *dest_len = strlen(dest); ++ //change "+" to "-", "/" to "_", remove "=". ++ for(int i = *(int *)dest_len; i >= 0; i--) { ++ if(*(dest + i) == '+') ++ *(dest + i) = '-'; ++ else if(*(dest + i) == '/') ++ *(dest + i) = '_'; ++ else if(*(dest + i) == '=') ++ *(dest + i) = *(dest + i + 1); ++ } ++ return dest; ++} ++ ++//Decode base64url string source to unsigned char. ++//Neither of param source_len or dest_len include character '\0'. ++//Return the first address of decoded unsigned string. 【warning】caller need free return ptr ++uint8_t* kpsecl_base64urldecode(const char *source, size_t source_len, size_t *dest_len) { ++ //change "-" to "+", "_" to "/", add back "=". ++ size_t i = 0; ++ char *tail1 = "="; ++ char *tail2 = "=="; ++ char *b64 = calloc(1, source_len + 3); ++ if (b64 == NULL) { ++ return NULL; ++ } ++ memcpy(b64, source, source_len); ++ for(i = 0; i < source_len; i++) { ++ if(*(b64 + i) == '-') ++ *(b64 + i) = '+'; ++ else if(*(b64 + i) == '_') ++ *(b64 + i) = '/'; ++ } ++ *(b64 + i) = '\0'; ++ if(source_len % 4 == 2) { ++ strcat(b64, tail2); ++ *dest_len = (source_len + 2) / 4 * 3 - 2; ++ } ++ else if(source_len % 4 == 3) { ++ strcat(b64, tail1); ++ *dest_len = (source_len + 1) / 4 * 3 - 1; ++ } ++ else if(source_len % 4 == 0) ++ *dest_len = source_len / 4 * 3; ++ uint8_t *dest = b64_decode(b64, strlen(b64)); ++ free(b64); ++ return dest; ++} +diff --git a/thirdparty/base64url/base64url.h b/thirdparty/base64url/base64url.h +new file mode 100644 +index 0000000..404621c +--- /dev/null ++++ b/thirdparty/base64url/base64url.h +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_BASE64URL_H ++#define SECGEAR_BASE64URL_H ++ ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++// warning, caller need free return ptr ++char* kpsecl_base64urlencode(const uint8_t *source, size_t source_len, size_t *dest_len); ++ ++// warning, caller need free return ptr ++uint8_t* kpsecl_base64urldecode(const char *source, size_t source_len, size_t *dest_len); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/tools/sign_tool/sign_tool.sh b/tools/sign_tool/sign_tool.sh +index f150aed..c567423 100755 +--- a/tools/sign_tool/sign_tool.sh ++++ b/tools/sign_tool/sign_tool.sh +@@ -122,8 +122,8 @@ itrustee_start_sign() { + cp ${IN_ENCLAVE} ${IN_PATH}/libcombine.so + OUT_PATH=$(dirname ${OUT_FILE}) + echo ${IN_PATH} ${OUT_PATH} +- python -B ${signtoolpath}/signtool_v3.py ${IN_PATH} ${OUT_PATH} --privateCfg ${A_CONFIG_FILE} +- #rm -rf ${IN_PATH}/libcombine.so ++ python3 -B ${signtoolpath}/signtool_v3.py ${IN_PATH} ${OUT_PATH} --privateCfg ${A_CONFIG_FILE} ++ rm -rf ${IN_PATH}/libcombine.so + else + echo "Error: illegal command" + fi +-- +2.33.0 + diff --git a/0062-secure-channel-support-authentication-by-remote-atte.patch b/0062-secure-channel-support-authentication-by-remote-atte.patch new file mode 100644 index 0000000000000000000000000000000000000000..d36a7cb4c680cb02eeb4a1f32a6d4ac794aaf028 --- /dev/null +++ b/0062-secure-channel-support-authentication-by-remote-atte.patch @@ -0,0 +1,1398 @@ +From e4af99705b611e702216a58a8ddf90254f8b1977 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Sat, 27 May 2023 14:26:56 +0800 +Subject: [PATCH 2/2] secure channel support authentication by remote + attestation + +--- + component/secure_channel/Readme.md | 6 +- + .../secure_channel/client/CMakeLists.txt | 13 +- + .../client/secure_channel_client.c | 362 +++++++++++++++--- + .../client/secure_channel_client.h | 1 + + .../secure_channel/enclave/CMakeLists.txt | 8 +- + .../enclave/secure_channel_enclave.c | 79 +++- + .../enclave/secure_channel_enclave.h | 2 + + component/secure_channel/host/CMakeLists.txt | 14 +- + .../secure_channel/host/secure_channel_host.c | 106 ++++- + component/secure_channel/secure_channel.edl | 2 + + .../secure_channel/secure_channel_common.c | 36 +- + .../secure_channel/secure_channel_common.h | 22 +- + examples/secure_channel/CMakeLists.txt | 25 +- + examples/secure_channel/Readme.md | 2 +- + examples/secure_channel/client/CMakeLists.txt | 4 +- + examples/secure_channel/client/client.c | 3 +- + .../secure_channel/enclave/CMakeLists.txt | 14 +- + .../secure_channel/enclave/config_cloud.ini | 70 ++-- + examples/secure_channel/host/CMakeLists.txt | 10 +- + examples/secure_channel/host/server.c | 2 +- + 20 files changed, 614 insertions(+), 167 deletions(-) + +diff --git a/component/secure_channel/Readme.md b/component/secure_channel/Readme.md +index 84ef98b..ea6201f 100644 +--- a/component/secure_channel/Readme.md ++++ b/component/secure_channel/Readme.md +@@ -11,7 +11,7 @@ + |------------|--------------------------|-----------------------|---------| + | 客户端 | secure_channel_client.h | libcsecure_channel.so | openssl | + | 服务端host | secure_channel_host.h | libusecure_channel.so | openssl | +-| 服务端enclave | secure_channel_enclave.h | libtsecure_channel.so | TEE及TEE软件栈 | ++| 服务端enclave | secure_channel_enclave.h | libtsecure_channel.a| TEE及TEE软件栈 | + + ### 接口 + | 接口名 | 所属头文件、库 | 功能 | 备注 | +@@ -25,8 +25,8 @@ + | cc_sec_chl_svr_init | secure_channel_host.h libusecure_channel.so | 安全通道服务端初始化 | 调用前需初始化ctx中enclave_ctx | + | cc_sec_chl_svr_fini | secure_channel_host.h libusecure_channel.so | 安全通道服务端销毁 | 销毁安全通道服务端以及所有客户端信息 | + | cc_sec_chl_svr_callback | secure_channel_host.h libusecure_channel.so | 安全通道协商消息处理函数 | 处理安全通道协商过程中,客户端发送给服务端的消息。在服务端消息接收处调用,调用前需初始化与客户端的网络连接和发送消息函数,详见[样例](https://gitee.com/openeuler/secGear/blob/master/examples/secure_channel/host/server.c#:~:text=conn_ctx.conn_kit.send)。 | +-| cc_sec_chl_enclave_encrypt | secure_channel_enclave.h libtsecure_channel.so | 安全通道enclave中的加密接口 | 无 | +-| cc_sec_chl_enclave_decrypt | secure_channel_enclave.h libtsecure_channel.so | 安全通道enclave中的解密接口 | 无 | ++| cc_sec_chl_enclave_encrypt | secure_channel_enclave.h libtsecure_channel.a | 安全通道enclave中的加密接口 | 无 | ++| cc_sec_chl_enclave_decrypt | secure_channel_enclave.h libtsecure_channel.a | 安全通道enclave中的解密接口 | 无 | + + ### 注意事项 + 安全通道仅封装密钥协商过程、加解密接口,不建立网络连接,协商过程复用业务的网络连接。其中客户端和服务端的网络连接由业务建立和维护,在安全通道客户端和服务端初始化时传入消息发送钩子函数和网络连接指针,详见[安全通道样例](https://gitee.com/openeuler/secGear/tree/master/examples/secure_channel)。 +diff --git a/component/secure_channel/client/CMakeLists.txt b/component/secure_channel/client/CMakeLists.txt +index 31c2ce9..e544312 100644 +--- a/component/secure_channel/client/CMakeLists.txt ++++ b/component/secure_channel/client/CMakeLists.txt +@@ -13,6 +13,9 @@ project(secure_channel_client C) + set(PREFIX secure_channel) + set(SOURCE_FILE secure_channel_client.c ${CMAKE_CURRENT_SOURCE_DIR}/../secure_channel_common.c) + ++aux_source_directory(${LOCAL_ROOT_PATH}/thirdparty/cjson/ CJSON_SRC) ++FILE (GLOB_RECURSE BASE64_SRC "${LOCAL_ROOT_PATH}/thirdparty/base64url/*.c") ++ + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") +@@ -24,16 +27,18 @@ include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/component/secure_channel ++ ${LOCAL_ROOT_PATH}/component/remote_attest/ ++ ${LOCAL_ROOT_PATH}/component/remote_attest/ra_verify ++ ${LOCAL_ROOT_PATH}/thirdparty/cjson ++ ${LOCAL_ROOT_PATH}/thirdparty/base64url + ) +-add_library(c${PREFIX} SHARED ${SOURCE_FILE}) ++add_library(c${PREFIX} SHARED ${SOURCE_FILE} ${CJSON_SRC} ${BASE64_SRC}) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(c${PREFIX} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() + +-target_link_libraries(c${PREFIX} ssl crypto) +- +-set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) ++target_link_libraries(c${PREFIX} ssl crypto secgear_verify) + + install(TARGETS c${PREFIX} + LIBRARY +diff --git a/component/secure_channel/client/secure_channel_client.c b/component/secure_channel/client/secure_channel_client.c +index 4ea4c43..27b0812 100644 +--- a/component/secure_channel/client/secure_channel_client.c ++++ b/component/secure_channel/client/secure_channel_client.c +@@ -14,31 +14,35 @@ + #include + #include + #include ++#include ++#include + + #include "status.h" + #include "enclave_log.h" + #include "secure_channel_common.h" ++#include "sg_ra_report_verify.h" ++#include "cJSON.h" ++#include "base64url.h" + +-#define SEC_CHL_RECV_BUF_MAX_LEN 1024 + ++#define SEC_CHL_RECV_BUF_MAX_LEN REPORT_OUT_LEN + struct cc_sec_chl_handle { + sec_chl_ecdh_ctx_t *ecdh_ctx; // key exchange context + pthread_mutex_t lock; // proctect recv_buf and recv_buf_len + uint8_t recv_buf[SEC_CHL_RECV_BUF_MAX_LEN]; // secure channel init msg max len + size_t recv_buf_len; // secure channel init msg real len +- uint8_t *svr_pubkey; +- size_t svr_pubkey_len; + cc_sec_chl_algo_t algo; ++ sec_chl_ra_req_t ra_req; ++ char *b64_enc_key; ++ RSA *rsa_svr_pubkey; + }; + + typedef enum { + STATE_ORIGIN = 0, + STATE_WAIT_SVRPUBKEY, + STATE_SVRPUBKEY_READY, +- STATE_WAIT_RA_REPORT, +- STATE_RA_REPORT_READY, +- STATE_VERIFY_RA_SUCCESS, +- STATE_VERIFY_SVRPUBKEY_SUCCESS, ++ STATE_WAIT_SET_ENC_KEY, ++ STATE_SET_ENC_KEY_SUCCESS, + STATE_WAIT_SVR_PARAM, + STATE_SVR_PARAM_READY, + STATE_LOCAL_PARAM_READY, +@@ -51,10 +55,8 @@ typedef enum { + typedef enum { + EVENT_GET_SVRPUBKEY = 0, + EVENT_RECV_SVRPUBKEY, +- EVENT_GET_RA_REPORT, +- EVENT_RECV_RA_REPORT, +- EVENT_VERIFY_RA_REPORT, +- EVENT_VERIFY_SVRPUBKEY, ++ EVENT_SET_ENC_KEY_TO_SVR, ++ EVENT_RECV_SET_ENC_KEY_RET, + EVENT_GET_SVR_PARAM, + EVENT_RECV_SVR_PARAM, + EVENT_GEN_LOCAL_PARAM, +@@ -66,9 +68,6 @@ typedef enum { + typedef cc_enclave_result_t (*sec_chl_init_fsm_action_t)(cc_sec_chl_ctx_t *ctx); + + typedef struct { +- sec_chl_init_fsm_state_t cur_state; +- sec_chl_init_fsm_event_id_t event_id; +- sec_chl_init_fsm_state_t next_state; + sec_chl_init_fsm_action_t action; + } sec_chl_fsm_state_transform_t; + +@@ -92,8 +91,11 @@ static void del_local_sec_chl_ctx(cc_sec_chl_ctx_t *ctx) + if (ctx->handle->ecdh_ctx != NULL) { + del_ecdh_ctx(ctx->handle->ecdh_ctx); + } +- if (ctx->handle->svr_pubkey != NULL) { +- free(ctx->handle->svr_pubkey); ++ if (ctx->handle->b64_enc_key != NULL) { ++ free(ctx->handle->b64_enc_key); ++ } ++ if (ctx->handle->rsa_svr_pubkey != NULL) { ++ RSA_free(ctx->handle->rsa_svr_pubkey); + } + free(ctx->handle); + ctx->handle = NULL; +@@ -180,11 +182,59 @@ cc_enclave_result_t cc_sec_chl_client_callback(cc_sec_chl_ctx_t *ctx, void *buf, + return CC_SUCCESS; + } + +-static cc_enclave_result_t get_svr_pubkey(cc_sec_chl_ctx_t *ctx) ++static cc_enclave_result_t get_taid_from_file(char *file, char *taid) + { +- sec_chl_msg_t msg = {0}; +- msg.msg_type = SEC_CHL_MSG_GET_SVR_PUBKEY; +- cc_enclave_result_t ret = sec_chl_send_request(&(ctx->conn_kit), &msg); ++ FILE *fp = fopen(file, "r"); ++ if (!fp) { ++ printf("secure channel init read taid failed\n"); ++ return CC_ERROR_SEC_CHL_INIT_GET_TAID; ++ } ++ ++ int ret = fscanf(fp, "%s", taid); // only read taid from line ++ ++ printf("read ret:%d, taid:%s\n", ret, taid); ++ ++ fclose(fp); ++ ++ return CC_SUCCESS; ++} ++ ++static cc_enclave_result_t request_report(cc_sec_chl_ctx_t *ctx, sec_chl_msg_type_t type, bool with_request_key) ++{ ++ cc_enclave_result_t ret; ++ sec_chl_msg_t *msg = NULL; ++ size_t data_len = 0; ++ ++ if (ctx->basevalue != NULL) { ++ data_len = sizeof(sec_chl_ra_req_t); ++ } ++ ++ msg = (sec_chl_msg_t *)calloc(1, sizeof(sec_chl_msg_t) + data_len); ++ if (msg == NULL) { ++ return CC_ERROR_SEC_CHL_MEMORY; ++ } ++ msg->msg_type = type; ++ ++ if (ctx->basevalue != NULL) { ++ sec_chl_ra_req_t *ra_req = (sec_chl_ra_req_t *)msg->data; ++ ra_req->with_tcb = false; ++ ra_req->req_key = with_request_key; ++ ++ ret = get_taid_from_file(ctx->basevalue, ra_req->taid); ++ if (ret != CC_SUCCESS) { ++ free(msg); ++ return ret; ++ } ++ if (RAND_priv_bytes(ra_req->nonce, SEC_CHL_REQ_NONCE_LEN) <= 0) { ++ free(msg); ++ return CC_FAIL; ++ } ++ memcpy(&ctx->handle->ra_req, ra_req, sizeof(sec_chl_ra_req_t)); ++ } ++ ++ msg->data_len = data_len; ++ ret = sec_chl_send_request(&(ctx->conn_kit), msg); ++ free(msg); + if (ret != CC_SUCCESS) { + return CC_ERROR_SEC_CHL_GET_SVR_PUBKEY; + } +@@ -192,7 +242,31 @@ static cc_enclave_result_t get_svr_pubkey(cc_sec_chl_ctx_t *ctx) + return CC_SUCCESS; + } + +-static cc_enclave_result_t recv_svr_pubkey(cc_sec_chl_ctx_t *ctx) ++static cc_enclave_result_t get_ra_report(cc_sec_chl_ctx_t *ctx) ++{ ++ return request_report(ctx, SEC_CHL_MSG_GET_RA_REPORT, false); ++} ++ ++static cc_enclave_result_t verify_report(cc_sec_chl_ctx_t *ctx, sec_chl_msg_t *msg) ++{ ++ cc_enclave_result_t ret = CC_SUCCESS; ++ if (msg->sub_type == GET_SVRPUBKEY_SUBTYPE_REPORT) { ++ cc_ra_buf_t report = {0}; ++ report.buf = msg->data; ++ report.len = msg->data_len; ++ cc_ra_buf_t nonce = {0}; ++ nonce.len = SEC_CHL_REQ_NONCE_LEN; ++ nonce.buf = ctx->handle->ra_req.nonce; ++ ret = cc_verify_report(&report, &nonce, CC_RA_VERIFY_TYPE_STRICT, ctx->basevalue); ++ if (ret != CC_SUCCESS) { ++ printf("verify report failed ret:%u\n", ret); ++ return CC_ERROR_SEC_CHL_INIT_VERIFY_REPORT; ++ } ++ } ++ return ret; ++} ++ ++static cc_enclave_result_t recv_ra_report(cc_sec_chl_ctx_t *ctx) + { + sec_chl_msg_t *msg = NULL; + +@@ -202,13 +276,12 @@ static cc_enclave_result_t recv_svr_pubkey(cc_sec_chl_ctx_t *ctx) + return CC_ERROR_SEC_CHL_WAITING_RECV_MSG; + } + msg = (sec_chl_msg_t *)ctx->handle->recv_buf; +- ctx->handle->svr_pubkey = calloc(1, msg->data_len); +- if (ctx->handle->svr_pubkey == NULL) { ++ cc_enclave_result_t ret = verify_report(ctx, msg); ++ if (ret != CC_SUCCESS) { + pthread_mutex_unlock(&ctx->handle->lock); +- return CC_ERROR_SEC_CHL_MEMORY; ++ return ret; + } +- memcpy(ctx->handle->svr_pubkey, msg->data, msg->data_len); +- ctx->handle->svr_pubkey_len = msg->data_len; ++ + ctx->session_id = msg->session_id; + ctx->handle->recv_buf_len = 0; + pthread_mutex_unlock(&ctx->handle->lock); +@@ -216,30 +289,219 @@ static cc_enclave_result_t recv_svr_pubkey(cc_sec_chl_ctx_t *ctx) + return CC_SUCCESS; + } + +-static cc_enclave_result_t get_ra_report(cc_sec_chl_ctx_t *ctx) ++static cc_enclave_result_t get_svr_pubkey(cc_sec_chl_ctx_t *ctx) + { +- (void)ctx; +- return CC_SUCCESS; ++ return request_report(ctx, SEC_CHL_MSG_GET_SVR_PUBKEY, true); + } + +-static cc_enclave_result_t recv_ra_report(cc_sec_chl_ctx_t *ctx) ++static cc_enclave_result_t get_svr_key_from_report(cc_sec_chl_ctx_t *ctx, cc_ra_buf_t *report) + { +- (void)ctx; +- return CC_SUCCESS; ++ cc_enclave_result_t ret = CC_ERROR_SEC_CHL_INVALID_REPORT; ++ uint8_t *n = NULL; ++ uint8_t *e = NULL; ++ ++ cJSON *cj_report = cJSON_ParseWithLength((char *)report->buf, report->len); ++ if (cj_report == NULL) { ++ printf("report to json failed\n"); ++ return CC_ERROR_SEC_CHL_INVALID_REPORT; ++ } ++ cJSON *cj_payload = cJSON_GetObjectItemCaseSensitive(cj_report, "payload"); ++ if (cj_payload == NULL) { ++ printf("report payload failed!\n"); ++ goto end; ++ } ++ cJSON *cj_nonce = cJSON_GetObjectItemCaseSensitive(cj_payload, "nonce"); ++ if(cj_nonce == NULL) { ++ printf("report nonce failed!\n"); ++ goto end; ++ } ++ // comput pubkey ++ cJSON *cj_pub_key = cJSON_GetObjectItemCaseSensitive(cj_nonce, "pub_key"); ++ if(cj_pub_key == NULL) { ++ printf("report pub_key failed!\n"); ++ goto end; ++ } ++ char *b64_n = cJSON_GetStringValue(cJSON_GetObjectItem(cj_pub_key, "n")); ++ if (b64_n == NULL) { ++ printf("parse n from json pub_key failed\n"); ++ goto end; ++ } ++ size_t n_len = 0; ++ n = kpsecl_base64urldecode(b64_n, strlen(b64_n), &n_len); ++ char *b64_e = cJSON_GetStringValue(cJSON_GetObjectItem(cj_pub_key, "e")); ++ if (b64_e == NULL) { ++ printf("parse e from json pub_key failed\n"); ++ goto end; ++ } ++ size_t e_len = 0; ++ e = kpsecl_base64urldecode(b64_e, strlen(b64_e), &e_len); ++ ++ RSA *svr_pub_key = RSA_new(); ++ BIGNUM *modulus = BN_new(); ++ BIGNUM *pub_exponent = BN_new(); ++ BN_hex2bn(&modulus, (char *)n); ++ BN_hex2bn(&pub_exponent, (char *)e); ++ RSA_set0_key(svr_pub_key, modulus, pub_exponent, NULL); ++ // svr pub key ++ ctx->handle->rsa_svr_pubkey = svr_pub_key; ++ ++ // save enc key to ctx ++ cJSON *cj_enc_key = cJSON_GetObjectItemCaseSensitive(cj_nonce, "enc_key"); ++ if(cj_enc_key == NULL) { ++ printf("report enc_key failed!\n"); ++ goto fail; ++ } ++ ctx->handle->b64_enc_key = calloc(1, strlen(cj_enc_key->valuestring) + 1); ++ if (ctx->handle->b64_enc_key == NULL) { ++ printf("malloc enc key buff failed\n"); ++ ret = CC_ERROR_SEC_CHL_MEMORY; ++ goto fail; ++ } ++ (void)memcpy(ctx->handle->b64_enc_key, cj_enc_key->valuestring, strlen(cj_enc_key->valuestring)); ++ ++ ret = CC_SUCCESS; ++ goto end; ++ ++fail: ++ if (svr_pub_key != NULL) { ++ RSA_free(svr_pub_key); ++ } ++end: ++ if (n != NULL) { ++ free(n); ++ } ++ if (e != NULL) { ++ free(e); ++ } ++ cJSON_Delete(cj_report); ++ ++ return ret; + } + +-static cc_enclave_result_t verify_ra_report(cc_sec_chl_ctx_t *ctx) ++RSA *get_rsakey_from_buffer(const uint8_t *rsa_key_buffer, size_t rsa_key_buffer_len, bool is_private_key) + { +- (void)ctx; +- return CC_SUCCESS; ++ BIO *r_key = NULL; ++ RSA *rsa_key = NULL; ++ r_key = BIO_new_mem_buf(rsa_key_buffer, rsa_key_buffer_len); ++ if (r_key == NULL) { ++ goto end; ++ } ++ if (is_private_key) { ++ rsa_key = PEM_read_bio_RSAPrivateKey(r_key, NULL, NULL, NULL); ++ } else { ++ rsa_key = PEM_read_bio_RSAPublicKey(r_key, NULL, NULL, NULL); ++ } ++ ++ if (rsa_key == NULL) { ++ goto end; ++ } ++ ++end: ++ BIO_free(r_key); ++ r_key = NULL; ++ return rsa_key; ++} ++ ++static cc_enclave_result_t parse_svrpubkey_from_recv_msg(cc_sec_chl_ctx_t *ctx, sec_chl_msg_t *msg) ++{ ++ cc_enclave_result_t ret; ++ if (msg->sub_type == GET_SVRPUBKEY_SUBTYPE_REPORT) { ++ cc_ra_buf_t report = {0}; ++ report.buf = msg->data; ++ report.len = msg->data_len; ++ ++ ret = get_svr_key_from_report(ctx, &report); ++ if (ret != CC_SUCCESS) { ++ return ret; ++ } ++ } else { ++ RSA *rsa_pubkey = get_rsakey_from_buffer(msg->data, msg->data_len, false); ++ if (rsa_pubkey == NULL) { ++ return CC_ERROR_SEC_CHL_PARSE_SVR_PUBKEY; ++ } ++ ctx->handle->rsa_svr_pubkey = rsa_pubkey; ++ ret = CC_SUCCESS; ++ } ++ ++ return ret; + } + +-static cc_enclave_result_t verify_svr_pubkey(cc_sec_chl_ctx_t *ctx) ++static cc_enclave_result_t recv_svr_pubkey(cc_sec_chl_ctx_t *ctx) + { +- (void)ctx; ++ sec_chl_msg_t *msg = NULL; ++ ++ pthread_mutex_lock(&ctx->handle->lock); ++ if (ctx->handle->recv_buf_len == 0) { ++ pthread_mutex_unlock(&ctx->handle->lock); ++ return CC_ERROR_SEC_CHL_WAITING_RECV_MSG; ++ } ++ msg = (sec_chl_msg_t *)ctx->handle->recv_buf; ++ cc_enclave_result_t ret = parse_svrpubkey_from_recv_msg(ctx, msg); ++ if (ret != CC_SUCCESS) { ++ pthread_mutex_unlock(&ctx->handle->lock); ++ return ret; ++ } ++ ++ ctx->session_id = msg->session_id; ++ ctx->handle->recv_buf_len = 0; ++ pthread_mutex_unlock(&ctx->handle->lock); ++ + return CC_SUCCESS; + } + ++static cc_enclave_result_t set_encrypt_key_to_server_ta(cc_sec_chl_ctx_t *ctx) ++{ ++ int ret; ++ sec_chl_msg_t *msg = NULL; ++ ++ if (ctx->handle->b64_enc_key == NULL) { ++ return CC_SUCCESS; ++ } ++ ++ char *b64_enc_key = ctx->handle->b64_enc_key; ++ size_t len = sizeof(sec_chl_msg_t) + strlen(b64_enc_key); ++ ++ msg = (sec_chl_msg_t *)calloc(1, len); ++ if (msg == NULL) { ++ return CC_ERROR_SEC_CHL_MEMORY; ++ } ++ ++ memcpy(msg->data, b64_enc_key, strlen(b64_enc_key)); ++ msg->data_len = strlen(b64_enc_key); ++ ++ msg->session_id = ctx->session_id; ++ msg->msg_type = SEC_CHL_MSG_SET_ENC_KEY_TO_SVR; ++ ++ ret = sec_chl_send_request(&ctx->conn_kit, msg); ++ free(msg); ++ if (ret != CC_SUCCESS) { ++ ret = CC_ERROR_SEC_CHL_SET_PARAM_TO_PEER; ++ } ++ return ret; ++} ++ ++static cc_enclave_result_t recv_set_enc_key_ret(cc_sec_chl_ctx_t *ctx) ++{ ++ sec_chl_msg_t *msg = NULL; ++ cc_enclave_result_t ret; ++ ++ if (ctx->handle->b64_enc_key == NULL) { ++ return CC_SUCCESS; ++ } ++ ++ pthread_mutex_lock(&ctx->handle->lock); ++ if (ctx->handle->recv_buf_len == 0) { ++ pthread_mutex_unlock(&ctx->handle->lock); ++ return CC_ERROR_SEC_CHL_WAITING_RECV_MSG; ++ } ++ msg = (sec_chl_msg_t *)ctx->handle->recv_buf; ++ ret = msg->ret; ++ ctx->handle->recv_buf_len = 0; ++ pthread_mutex_unlock(&ctx->handle->lock); ++ ++ return ret; ++} ++ + static cc_enclave_result_t get_svr_param(cc_sec_chl_ctx_t *ctx) + { + sec_chl_msg_t msg = {0}; +@@ -266,7 +528,7 @@ static cc_enclave_result_t recv_svr_param(cc_sec_chl_ctx_t *ctx) + msg = (sec_chl_msg_t *)ctx->handle->recv_buf; + memcpy(&ec_nid, msg->data + RANDOM_LEN, sizeof(int)); + +- ret = verify_signature(ctx->handle->svr_pubkey, ctx->handle->svr_pubkey_len, msg->data, msg->data_len); ++ ret = verify_signature(ctx->handle->rsa_svr_pubkey, msg->data, msg->data_len); + if (ret != CC_SUCCESS) { + pthread_mutex_unlock(&ctx->handle->lock); + return ret; +@@ -372,18 +634,18 @@ static cc_enclave_result_t sec_chl_compute_session_key(cc_sec_chl_ctx_t *ctx) + } + + static sec_chl_fsm_state_transform_t g_state_transform_table[] = { +- {STATE_ORIGIN, EVENT_GET_SVRPUBKEY, STATE_WAIT_SVRPUBKEY, get_svr_pubkey}, +- {STATE_WAIT_SVRPUBKEY, EVENT_RECV_SVRPUBKEY, STATE_SVRPUBKEY_READY, recv_svr_pubkey}, +- {STATE_SVRPUBKEY_READY, EVENT_GET_RA_REPORT, STATE_WAIT_RA_REPORT, get_ra_report}, +- {STATE_WAIT_RA_REPORT, EVENT_RECV_RA_REPORT, STATE_RA_REPORT_READY, recv_ra_report}, +- {STATE_RA_REPORT_READY, EVENT_VERIFY_RA_REPORT, STATE_VERIFY_RA_SUCCESS, verify_ra_report}, +- {STATE_VERIFY_RA_SUCCESS, EVENT_VERIFY_SVRPUBKEY, STATE_VERIFY_SVRPUBKEY_SUCCESS, verify_svr_pubkey}, +- {STATE_VERIFY_SVRPUBKEY_SUCCESS, EVENT_GET_SVR_PARAM, STATE_WAIT_SVR_PARAM, get_svr_param}, +- {STATE_WAIT_SVR_PARAM, EVENT_RECV_SVR_PARAM, STATE_SVR_PARAM_READY, recv_svr_param}, +- {STATE_SVR_PARAM_READY, EVENT_GEN_LOCAL_PARAM, STATE_LOCAL_PARAM_READY, gen_local_param}, +- {STATE_LOCAL_PARAM_READY, EVENT_SET_PARAM_TO_PEER, STATE_WAIT_SET_PARAM_RET, set_local_param_to_peer}, +- {STATE_WAIT_SET_PARAM_RET, EVENT_RECV_SET_PARAM_RET, STATE_ALL_READY, recv_set_param_ret}, +- {STATE_ALL_READY, EVENT_COMPUTE_SESSIONKEY, STATE_SUCCESS, sec_chl_compute_session_key}, ++ {get_ra_report}, ++ {recv_ra_report}, ++ {get_svr_pubkey}, ++ {recv_svr_pubkey}, ++ {set_encrypt_key_to_server_ta}, ++ {recv_set_enc_key_ret}, ++ {get_svr_param}, ++ {recv_svr_param}, ++ {gen_local_param}, ++ {set_local_param_to_peer}, ++ {recv_set_param_ret}, ++ {sec_chl_compute_session_key}, + }; + + #define RECV_MSG_TIMEOUT_CNT 1000 +diff --git a/component/secure_channel/client/secure_channel_client.h b/component/secure_channel/client/secure_channel_client.h +index a77973a..e2d0b7e 100644 +--- a/component/secure_channel/client/secure_channel_client.h ++++ b/component/secure_channel/client/secure_channel_client.h +@@ -41,6 +41,7 @@ typedef struct cc_sec_chl_ctx { + size_t session_id; // unique value return by server + cc_conn_kit_t conn_kit; // network transmission connection kit need register by user + cc_sec_chl_handle_t *handle; ++ char *basevalue; // target ta basevalue file path + } cc_sec_chl_ctx_t; + + typedef enum { +diff --git a/component/secure_channel/enclave/CMakeLists.txt b/component/secure_channel/enclave/CMakeLists.txt +index 0c651f5..a84de8a 100644 +--- a/component/secure_channel/enclave/CMakeLists.txt ++++ b/component/secure_channel/enclave/CMakeLists.txt +@@ -12,6 +12,7 @@ project(secure_channel_enclave C) + set(PREFIX secure_channel) + + set(SOURCE_FILES secure_channel_enclave.c ${CMAKE_CURRENT_SOURCE_DIR}/../secure_channel_common.c) ++FILE (GLOB_RECURSE BASE64_SRC "${LOCAL_ROOT_PATH}/thirdparty/base64url/*.c") + + set(PRINT_LEVEL 3) + add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) +@@ -73,8 +74,9 @@ if(CC_GP) + ${ITRUSTEE_LIBC}/arch/arm/bits + ${ITRUSTEE_LIBC}/arch/generic + ${ITRUSTEE_LIBC}/arch/arm +- ${SSL_PATH}/include) +- add_library(t${PREFIX} ${SOURCE_FILES} ${AUTO_FILES} ${LOCAL_ROOT_PATH}/src/enclave_src/gp/gp.c) ++ ${SSL_PATH}/include ++ ${LOCAL_ROOT_PATH}/thirdparty/base64url) ++ add_library(t${PREFIX} ${SOURCE_FILES} ${AUTO_FILES} ${LOCAL_ROOT_PATH}/src/enclave_src/gp/gp.c ${BASE64_SRC}) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(t${PREFIX} PRIVATE +@@ -125,8 +127,6 @@ else() + endif() + endif() + +-set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) +- + install(TARGETS t${PREFIX} + ARCHIVE + DESTINATION ${LIBRARY_INSTALL} +diff --git a/component/secure_channel/enclave/secure_channel_enclave.c b/component/secure_channel/enclave/secure_channel_enclave.c +index 2867be4..fa0b935 100644 +--- a/component/secure_channel/enclave/secure_channel_enclave.c ++++ b/component/secure_channel/enclave/secure_channel_enclave.c +@@ -9,13 +9,9 @@ + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ +- +-#ifdef SGX_ENCLAVE +-#include "tsgxsslio.h" +-#endif ++#include "secure_channel_enclave.h" + + #include +- + #include "status.h" + #include "secgear_log.h" + #include "secgear_random.h" +@@ -23,9 +19,12 @@ + #include "secure_channel_t.h" + + #ifdef SGX_ENCLAVE ++ #include "tsgxsslio.h" + #include "sgx_thread.h" + typedef sgx_thread_rwlock_t sc_lock_t; + #else ++ #include "base64url.h" ++ #include "tee_ra_api.h" + typedef pthread_rwlock_t sc_lock_t; + #endif + +@@ -251,7 +250,7 @@ static int add_to_sec_chl_list(SEC_CHL_NODE *node) + return CC_SUCCESS; + } + +-static int gen_sec_chl_node(size_t *session_id) ++int init_session(size_t *session_id) + { + size_t random_id = 0; + int ret = cc_enclave_generate_random(&random_id, sizeof(size_t)); +@@ -302,7 +301,7 @@ int get_enclave_pubkey(size_t *session_id, uint8_t *pubkey, size_t *pubkey_len) + return CC_ERROR_BAD_PARAMETERS; + } + // 添加到g_sec_chl_manager +- ret = gen_sec_chl_node(session_id); ++ ret = init_session(session_id); + if (ret != CC_SUCCESS) { + PrintInfo(PRINT_ERROR, "get enclave pubkey add node failed\n"); + return ret; +@@ -378,6 +377,72 @@ int get_enclave_exch_param(size_t session_id, uint8_t *exch_param, size_t exch_p + return ret; + } + ++#define RSA_MAX_LEN 1024 ++int set_enc_key(size_t session_id, uint8_t* data, size_t data_len) ++{ ++ cc_enclave_result_t ret = CC_SUCCESS; ++ ++#ifdef GP_ENCLAVE ++ // decode base64rul enc_key ++ size_t enc_key_len = 0; ++ uint8_t *enc_key = kpsecl_base64urldecode((char *)data, data_len, &enc_key_len); ++ ++ // unseal enc_key ++ size_t dec_key_len = enc_key_len; ++ uint8_t *dec_key = (uint8_t *)calloc(1, dec_key_len); ++ if (dec_key == NULL) { ++ ret = CC_ERROR_SEC_CHL_MEMORY; ++ goto end; ++ } ++ TEE_Result gp_ret = ra_unseal(enc_key, enc_key_len, dec_key, &dec_key_len, TEE_ALG_AES_GCM); ++ if (gp_ret != TEE_SUCCESS) { ++ PrintInfo(PRINT_ERROR, "unseal enc key failed\n"); ++ ret = CC_ERROR_SEC_CHL_ENCLAVE_UNSEAL_ENC_KEY; ++ goto end; ++ } ++ ++ // compute private_key ++ // dec_key组成形式为:d_len | d | n_len | n | e_len | e ,其中d_len/n_len/e_len分别为四个字节 ++ uint32_t d_len = *(uint32_t *)dec_key; ++ uint32_t n_len = *(uint32_t *)(dec_key + sizeof(uint32_t) + d_len); ++ uint32_t e_len = *(uint32_t *)(dec_key + sizeof(uint32_t) + d_len + sizeof(uint32_t) + n_len); ++ PrintInfo(PRINT_STRACE, "rsa param len d_len:%u, n_len:%u, e_len:%u\n", d_len, n_len, e_len); ++ ++ uint8_t d[RSA_MAX_LEN] = {0}; ++ uint8_t n[RSA_MAX_LEN] = {0}; ++ uint8_t e[RSA_MAX_LEN] = {0}; ++ memcpy(d, dec_key + sizeof(uint32_t), d_len); ++ memcpy(n, dec_key + sizeof(uint32_t) + d_len + sizeof(uint32_t), n_len); ++ memcpy(e, dec_key + sizeof(uint32_t) + d_len + sizeof(uint32_t) + n_len + sizeof(uint32_t), e_len); ++ ++ RSA *rsa_key = RSA_new(); ++ BIGNUM *modulus = BN_new(); ++ BIGNUM *pub_exponent = BN_new(); ++ BIGNUM *pri_exponent = BN_new(); ++ BN_hex2bn(&modulus, (char *)n); ++ BN_hex2bn(&pub_exponent, (char *)e); ++ BN_hex2bn(&pri_exponent, (char *)d); ++ RSA_set0_key(rsa_key, modulus, pub_exponent, pri_exponent); ++ ++ sc_wtlock(&g_sec_chl_manager.sec_chl_list_lock); ++ sec_chl_ecdh_ctx_t *ecdh_ctx = get_ecdh_ctx_by_session_id(session_id); ++ if (ecdh_ctx == NULL) { ++ sc_wtunlock(&g_sec_chl_manager.sec_chl_list_lock); ++ RSA_free(rsa_key); ++ ret = CC_ERROR_SEC_CHL_INVALID_SESSION; ++ PrintInfo(PRINT_ERROR, "get ecdh ctx by session id\n"); ++ goto end; ++ } ++ ecdh_ctx->svr_rsa_key = rsa_key; ++ sc_wtunlock(&g_sec_chl_manager.sec_chl_list_lock); ++end: ++ free(enc_key); ++ free(dec_key); ++ ++#endif ++ return ret; ++} ++ + int set_peer_exch_param(size_t session_id, uint8_t* data, size_t data_len) + { + int ret; +diff --git a/component/secure_channel/enclave/secure_channel_enclave.h b/component/secure_channel/enclave/secure_channel_enclave.h +index 65bd205..8922337 100644 +--- a/component/secure_channel/enclave/secure_channel_enclave.h ++++ b/component/secure_channel/enclave/secure_channel_enclave.h +@@ -13,6 +13,8 @@ + #ifndef SECURE_CHANNEL_ENCLAVE_H + #define SECURE_CHANNEL_ENCLAVE_H + ++#include ++ + #ifdef __cplusplus + extern "C" { + #endif +diff --git a/component/secure_channel/host/CMakeLists.txt b/component/secure_channel/host/CMakeLists.txt +index 5c60b3f..8ecbc99 100644 +--- a/component/secure_channel/host/CMakeLists.txt ++++ b/component/secure_channel/host/CMakeLists.txt +@@ -48,13 +48,16 @@ if(CC_GP) + ${LOCAL_ROOT_PATH}/component/secure_channel + ${SDK_PATH}/include/CA + ${LOCAL_ROOT_PATH}/inc/host_inc +- ${LOCAL_ROOT_PATH}/inc/host_inc/gp) ++ ${LOCAL_ROOT_PATH}/inc/host_inc/gp ++ ${LOCAL_ROOT_PATH}/component/remote_attest ++ ${LOCAL_ROOT_PATH}/component/remote_attest/ra_report) + add_library(u${PREFIX} SHARED ${SOURCE_FILE} ${AUTO_FILES}) + + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(u${PREFIX} PRIVATE + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() ++ target_link_libraries(u${PREFIX} secgear_ra) + endif() + + if(CC_SGX) +@@ -65,7 +68,7 @@ if(CC_SGX) + else() + set(Urts_Library_Name sgx_urts_sim) + endif() +- set(host_C_Flags "${COMMON_CFLAGS} -fPIC -Wno-attributes -pthread") ++ set(host_C_Flags "${COMMON_CFLAGS} -fPIC -Wno-attributes -lz -pthread") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY} +@@ -79,7 +82,9 @@ if(CC_SGX) + ${LOCAL_ROOT_PATH}/inc/host_inc + ${LOCAL_ROOT_PATH}/inc/host_inc/sgx + ${OPENSSL_PATH}/include +- ${SGX_SDK_PATH}/include) ++ ${SGX_SDK_PATH}/include ++ ${LOCAL_ROOT_PATH}/component/remote_attest ++ ${LOCAL_ROOT_PATH}/component/remote_attest/ra_report) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${host_C_Flags}") + add_library(u${PREFIX} SHARED ${SOURCE_FILE} ${AUTO_FILES}) + +@@ -88,10 +93,9 @@ if(CC_SGX) + ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + ${CMAKE_BINARY_DIR}/lib/) + endif() ++ target_link_libraries(u${PREFIX} secgear_ra) + endif() + +-set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) +- + install(TARGETS u${PREFIX} + LIBRARY + DESTINATION ${LIBRARY_INSTALL} +diff --git a/component/secure_channel/host/secure_channel_host.c b/component/secure_channel/host/secure_channel_host.c +index 6edaef6..e7adf3c 100644 +--- a/component/secure_channel/host/secure_channel_host.c ++++ b/component/secure_channel/host/secure_channel_host.c +@@ -25,9 +25,11 @@ + #include "enclave_log.h" + #include "secure_channel_u.h" + #include "secure_channel_common.h" ++#include "sg_ra_report.h" ++#include "enclave_internal.h" + + #define RSA_PUBKEY_LEN 640 +-static int sec_chl_get_pubkey(cc_enclave_t *context, sec_chl_msg_t *msg, sec_chl_msg_t **rsp_msg, size_t *rsp_msg_len) ++static int sec_chl_gen_pubkey(cc_enclave_t *context, sec_chl_msg_t *msg, sec_chl_msg_t **rsp_msg, size_t *rsp_msg_len) + { + int res; + cc_enclave_result_t ret_val; +@@ -49,6 +51,7 @@ static int sec_chl_get_pubkey(cc_enclave_t *context, sec_chl_msg_t *msg, sec_chl + } + rsp->session_id = session_id; + rsp->data_len = rsa_pubkey_len; ++ rsp->sub_type = GET_SVRPUBKEY_SUBTYPE_SVR_GEN; + memcpy(rsp->data, rsa_pubkey, rsa_pubkey_len); + *rsp_msg = rsp; + *rsp_msg_len = sizeof(sec_chl_msg_t) + rsa_pubkey_len; +@@ -56,6 +59,94 @@ static int sec_chl_get_pubkey(cc_enclave_t *context, sec_chl_msg_t *msg, sec_chl + return CC_SUCCESS; + } + ++static int sec_chl_get_ra_report(cc_enclave_t *context, sec_chl_msg_t *msg, ++ sec_chl_msg_t **rsp_msg, size_t *rsp_msg_len) ++{ ++ (void)context; ++ cc_enclave_result_t ret_val; ++ sec_chl_msg_t *rsp = NULL; ++ ++ sec_chl_ra_req_t *ra_req = (sec_chl_ra_req_t *)(msg->data); ++ ++ cc_get_ra_report_input_t ra_input = {0}; ++ ra_input.taid = (uint8_t *)ra_req->taid; ++ (void)memcpy(ra_input.nonce, ra_req->nonce, SEC_CHL_REQ_NONCE_LEN); ++ ra_input.nonce_len = SEC_CHL_REQ_NONCE_LEN + 1; ++ ra_input.with_tcb = ra_req->with_tcb; ++ ra_input.req_key = ra_req->req_key; ++ ++ uint8_t data[REPORT_OUT_LEN] = {0}; ++ cc_ra_buf_t report = {REPORT_OUT_LEN, data}; ++ ++ ret_val = cc_get_ra_report(&ra_input, &report); ++ ++ if (ret_val != CC_SUCCESS) { ++ print_error_term("secure channel host get ra report failed\n"); ++ return CC_ERROR_SEC_CHL_GET_RA_REPORT; ++ } ++ rsp = (sec_chl_msg_t *)calloc(1, sizeof(sec_chl_msg_t) + report.len); ++ (void)memcpy(rsp->data, report.buf, report.len); ++ rsp->data_len = report.len; ++ rsp->sub_type = GET_SVRPUBKEY_SUBTYPE_REPORT; ++ rsp->session_id = msg->session_id; ++ ++ *rsp_msg = rsp; ++ *rsp_msg_len = sizeof(sec_chl_msg_t) + report.len; ++ ++ return CC_SUCCESS; ++} ++ ++static int sec_chl_get_ra_report_ex(cc_enclave_t *context, sec_chl_msg_t *msg, ++ sec_chl_msg_t **rsp_msg, size_t *rsp_msg_len) ++{ ++ if (is_support_remote_attest(context)) { ++ return sec_chl_get_ra_report(context, msg, rsp_msg, rsp_msg_len); ++ } ++ return CC_SUCCESS; ++} ++ ++static int sec_chl_get_pubkey(cc_enclave_t *context, sec_chl_msg_t *msg, sec_chl_msg_t **rsp_msg, size_t *rsp_msg_len) ++{ ++ if (is_support_remote_attest(context)) { ++ int ret; ++ cc_enclave_result_t ret_val; ++ size_t session_id = 0; ++ ret_val = init_session(context, &ret, &session_id); ++ if (ret_val != CC_SUCCESS || ret != CC_SUCCESS) { ++ print_error_term("init session failed\n"); ++ return CC_ERROR_SEC_CHL_INIT_SESSEION; ++ } ++ msg->session_id = session_id; ++ return sec_chl_get_ra_report(context, msg, rsp_msg, rsp_msg_len); ++ } else { ++ return sec_chl_gen_pubkey(context, msg, rsp_msg, rsp_msg_len); ++ } ++} ++ ++static int sec_chl_set_enc_key(cc_enclave_t *context, sec_chl_msg_t *msg, ++ sec_chl_msg_t **rsp_msg, size_t *rsp_msg_len) ++{ ++ int res; ++ cc_enclave_result_t ret_val; ++ size_t session_id = msg->session_id; ++ ++ ret_val = set_enc_key(context, &res, session_id, msg->data, msg->data_len); ++ if (ret_val != CC_SUCCESS || res != (int)CC_SUCCESS) { ++ print_error_term("set enc key error!\n"); ++ return CC_FAIL; ++ } ++ ++ sec_chl_msg_t *rsp = (sec_chl_msg_t *)calloc(1, sizeof(sec_chl_msg_t)); ++ if (rsp == NULL) { ++ return CC_ERROR_SEC_CHL_MEMORY; ++ } ++ ++ *rsp_msg = rsp; ++ *rsp_msg_len = sizeof(sec_chl_msg_t); ++ ++ return CC_SUCCESS; ++} ++ + static int sec_chl_get_svr_exch_param(cc_enclave_t *context, sec_chl_msg_t *msg, + sec_chl_msg_t **rsp_msg, size_t *rsp_msg_len) + { +@@ -290,6 +381,13 @@ cc_enclave_result_t cc_sec_chl_svr_init(cc_sec_chl_svr_ctx_t *ctx) + print_warning("secure channel already started\n"); + return CC_SUCCESS; + } ++ if (is_support_remote_attest(ctx->enclave_ctx)) { ++ cc_enclave_result_t ret = cc_prepare_ra_env(CC_RA_SCENARIO_NO_AS); ++ if (ret != CC_SUCCESS) { ++ print_error_term("prepare ra env error, ret:%x!\n", ret); ++ return -1; ++ } ++ } + + ret_val = enclave_start_sec_chl(ctx->enclave_ctx, &res); + if (ret_val != CC_SUCCESS || res != CC_SUCCESS) { +@@ -325,9 +423,15 @@ static cc_enclave_result_t handle_recv_msg(cc_enclave_t *context, sec_chl_msg_t + { + cc_enclave_result_t ret = CC_FAIL; + switch (msg->msg_type) { ++ case SEC_CHL_MSG_GET_RA_REPORT: ++ ret = sec_chl_get_ra_report_ex(context, msg, rsp_msg, rsp_msg_len); ++ break; + case SEC_CHL_MSG_GET_SVR_PUBKEY: + ret = sec_chl_get_pubkey(context, msg, rsp_msg, rsp_msg_len); + break; ++ case SEC_CHL_MSG_SET_ENC_KEY_TO_SVR: ++ ret = sec_chl_set_enc_key(context, msg, rsp_msg, rsp_msg_len); ++ break; + case SEC_CHL_MSG_GET_SVR_EXCH_PARAM: + ret = sec_chl_get_svr_exch_param(context, msg, rsp_msg, rsp_msg_len); + break; +diff --git a/component/secure_channel/secure_channel.edl b/component/secure_channel/secure_channel.edl +index cf2a139..4c6f04c 100644 +--- a/component/secure_channel/secure_channel.edl ++++ b/component/secure_channel/secure_channel.edl +@@ -19,6 +19,8 @@ enclave { + trusted { + // #define RSA_PUBKEY_LEN 640 + public int get_enclave_pubkey([in, out] size_t* session_id, [out, size = 640] uint8_t* pubkey, [in, out] size_t* pubkey_len); ++ public int init_session([in, out] size_t* session_id); ++ public int set_enc_key(size_t session_id, [in, size = data_len] uint8_t* data, size_t data_len); + public int get_enclave_exch_param_len(size_t session_id, [in, out] size_t* exch_param_len); + public int get_enclave_exch_param(size_t session_id, [out, size = exch_param_len] uint8_t* exch_param, size_t exch_param_len); + public int set_peer_exch_param(size_t session_id, [in, size = data_len] uint8_t* data, size_t data_len); +diff --git a/component/secure_channel/secure_channel_common.c b/component/secure_channel/secure_channel_common.c +index 5800fd6..d8bc93f 100644 +--- a/component/secure_channel/secure_channel_common.c ++++ b/component/secure_channel/secure_channel_common.c +@@ -56,42 +56,16 @@ void num_to_buf(size_t num, uint8_t *buf, size_t len) + return; + } + +-static RSA *get_rsakey_from_buffer(const uint8_t *rsa_key_buffer, size_t rsa_key_buffer_len, bool is_private_key) +-{ +- BIO *r_key = NULL; +- RSA *rsa_key = NULL; +- r_key = BIO_new_mem_buf(rsa_key_buffer, rsa_key_buffer_len); +- if (r_key == NULL) { +- goto end; +- } +- if (is_private_key) { +- rsa_key = PEM_read_bio_RSAPrivateKey(r_key, NULL, NULL, NULL); +- } else { +- rsa_key = PEM_read_bio_RSAPublicKey(r_key, NULL, NULL, NULL); +- } +- +- if (rsa_key == NULL) { +- goto end; +- } +- +-end: +- BIO_free(r_key); +- r_key = NULL; +- return rsa_key; +-} +- +-int verify_rsa_signature(const uint8_t *rsa_pubkey, size_t rsa_pubkey_len, const uint8_t *signature, size_t sig_len, ++int verify_rsa_signature(RSA *rsa_pubkey, const uint8_t *signature, size_t sig_len, + const uint8_t *buf, size_t buf_len) + { +- RSA *sign_rsa = NULL; + EVP_PKEY *evp_sign_key = NULL; + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + int ret_val = CC_FAIL; + +- sign_rsa = get_rsakey_from_buffer(rsa_pubkey, rsa_pubkey_len, 0); + evp_sign_key = EVP_PKEY_new(); +- if (evp_sign_key == NULL || !EVP_PKEY_set1_RSA(evp_sign_key, sign_rsa) || ((size_t)RSA_size(sign_rsa) != sig_len)) { ++ if (evp_sign_key == NULL || !EVP_PKEY_set1_RSA(evp_sign_key, rsa_pubkey) || ((size_t)RSA_size(rsa_pubkey) != sig_len)) { + goto end; + } + md_ctx = EVP_MD_CTX_new(); +@@ -116,8 +90,6 @@ end: + pctx = NULL; + EVP_PKEY_free(evp_sign_key); + evp_sign_key = NULL; +- RSA_free(sign_rsa); +- sign_rsa = NULL; + return ret_val; + } + +@@ -771,7 +743,7 @@ cc_enclave_result_t get_exch_param_from_buf(uint8_t *exch_buf, size_t buf_len, s + return CC_SUCCESS; + } + +-cc_enclave_result_t verify_signature(uint8_t *pubkey, size_t pubkey_len, uint8_t *exch_buf, size_t buf_len) ++cc_enclave_result_t verify_signature(RSA *rsa_pubkey, uint8_t *exch_buf, size_t buf_len) + { + size_t ecdh_pubkey_len; + size_t signature_len; +@@ -802,7 +774,7 @@ cc_enclave_result_t verify_signature(uint8_t *pubkey, size_t pubkey_len, uint8_t + + // verify signature + size_t data_len = p_buf - exch_buf - sizeof(signature_len); +- int ret = verify_rsa_signature(pubkey, pubkey_len, p_buf, signature_len, exch_buf, data_len); ++ int ret = verify_rsa_signature(rsa_pubkey, p_buf, signature_len, exch_buf, data_len); + if (ret != CC_SUCCESS) { + return CC_ERROR_SEC_CHL_VERIFY_PEER_EXCH_BUF_SIGNATURE; + } +diff --git a/component/secure_channel/secure_channel_common.h b/component/secure_channel/secure_channel_common.h +index e81c1e4..4250e60 100644 +--- a/component/secure_channel/secure_channel_common.h ++++ b/component/secure_channel/secure_channel_common.h +@@ -12,6 +12,7 @@ + + #ifndef SECURE_CHANNEL_COMMON_H + #define SECURE_CHANNEL_COMMON_H ++#include + #include + #include + #include +@@ -46,7 +47,8 @@ typedef enum { + SEC_CHL_MSG_GET_SVR_PUBKEY = 1, + SEC_CHL_MSG_GET_SVR_PUBKEY_RSP, + SEC_CHL_MSG_GET_RA_REPORT, +- SEC_CHL_MSG_VERIFY_SVR_PUBKEY, ++ SEC_CHL_MSG_GET_RA_REPORT_RSP, ++ SEC_CHL_MSG_SET_ENC_KEY_TO_SVR, + SEC_CHL_MSG_GET_SVR_EXCH_PARAM, + SEC_CHL_MSG_GET_SVR_EXCH_PARAM_RSP, + SEC_CHL_MSG_GEN_LOCAL_EXCH_PARAM, +@@ -57,9 +59,25 @@ typedef enum { + SEC_CHL_MSG_MAX, + } sec_chl_msg_type_t; + ++#define REPORT_OUT_LEN 0x3000 ++typedef enum { ++ GET_SVRPUBKEY_SUBTYPE_SVR_GEN, ++ GET_SVRPUBKEY_SUBTYPE_REPORT, ++} sec_chl_get_svrpubkey_subtype_t; ++ ++#define CC_TAID_LEN 36 ++#define SEC_CHL_REQ_NONCE_LEN 32 ++typedef struct { ++ char taid[CC_TAID_LEN + 1]; ++ uint8_t nonce[SEC_CHL_REQ_NONCE_LEN + 1]; ++ bool with_tcb; ++ bool req_key; ++} sec_chl_ra_req_t; ++ + #define RSP_BUF_LEN 640 + typedef struct sec_chl_msg { + sec_chl_msg_type_t msg_type; ++ sec_chl_get_svrpubkey_subtype_t sub_type; + size_t session_id; + int32_t ret; + size_t data_len; +@@ -84,7 +102,7 @@ void del_ecdh_ctx(sec_chl_ecdh_ctx_t *ecdh_ctx); + cc_enclave_result_t compute_session_key(sec_chl_ecdh_ctx_t *ecdh_ctx, sec_chl_exch_param_t *local_exch_param, + sec_chl_exch_param_t *peer_exch_param); + cc_enclave_result_t get_exch_param_from_buf(uint8_t *exch_buf, size_t buf_len, sec_chl_exch_param_t **exch_param); +-cc_enclave_result_t verify_signature(uint8_t *pubkey, size_t pubkey_len, uint8_t *exch_buf, size_t buf_len); ++cc_enclave_result_t verify_signature(RSA *rsa_pubkey, uint8_t *exch_buf, size_t buf_len); + int get_exch_buf_len(sec_chl_ecdh_ctx_t *ecdh_ctx); + int get_exch_buf(sec_chl_ecdh_ctx_t *ecdh_ctx, uint8_t *exch_param, size_t exch_param_len); + void del_exch_param(sec_chl_exch_param_t *exch_param); +diff --git a/examples/secure_channel/CMakeLists.txt b/examples/secure_channel/CMakeLists.txt +index 7594577..7b1d723 100644 +--- a/examples/secure_channel/CMakeLists.txt ++++ b/examples/secure_channel/CMakeLists.txt +@@ -14,33 +14,34 @@ set(SGX_SDK_DEFAULT_PATH /opt/intel/sgxsdk) + set(GP_SDK_DEFAULT_PATH /opt/itrustee_sdk) + set(PL_SDK_DEFAULT_PATH /root/dev/sdk) + +-set(SGX_SSL_DEFAULT_PATH /opt/intel/sgxssl) +-set(GP_SSL_DEFAULT_PATH /opt/itrustee_sdk/include/TA/openssl/) ++if (NOT DEFINED SSL_PATH) ++set(SSL_PATH /opt/intel/sgxssl) ++endif() + + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + + if(${ENCLAVE} STREQUAL "GP") + if (NOT DEFINED SDK_PATH) +-set(iTrusteeSDK ${GP_SDK_DEFAULT_PATH}) ++set(SDK_PATH ${GP_SDK_DEFAULT_PATH}) + else() +-set(iTrusteeSDK ${SDK_PATH}) ++set(SDK_PATH ${SDK_PATH}) + endif() +-message("Current Platform: ARM Trustzone, iTrustee SDK PATH:${iTrusteeSDK}") +-if(NOT IS_DIRECTORY ${iTrusteeSDK}) +-message(FATAL_ERROR "Please provide the correct iTrusteeSDK path") ++message("Current Platform: ARM Trustzone, iTrustee SDK PATH:${SDK_PATH}") ++if(NOT IS_DIRECTORY ${SDK_PATH}) ++message(FATAL_ERROR "Please provide the correct SDK_PATH path") + endif() + set(CC_GP ON) + endif() + + if(${ENCLAVE} STREQUAL "SGX") + if (NOT DEFINED SDK_PATH) +-set(SGXSDK ${SGX_SDK_DEFAULT_PATH}) ++set(SDK_PATH ${SGX_SDK_DEFAULT_PATH}) + else() +-set(SGXSDK ${SDK_PATH}) ++set(SDK_PATH ${SDK_PATH}) + endif() +-message("Current Platform: Intel SGX, SGX SDK PATH:${SGXSDK}") +-if(NOT IS_DIRECTORY ${SGXSDK}) +-message(FATAL_ERROR "Please provide the correct SGXSDK path") ++message("Current Platform: Intel SGX, SGX SDK PATH:${SDK_PATH}") ++if(NOT IS_DIRECTORY ${SDK_PATH}) ++message(FATAL_ERROR "Please provide the correct SDK_PATH path") + endif() + set(CC_SGX ON) + endif() +diff --git a/examples/secure_channel/Readme.md b/examples/secure_channel/Readme.md +index c5f5c69..514408e 100644 +--- a/examples/secure_channel/Readme.md ++++ b/examples/secure_channel/Readme.md +@@ -38,7 +38,7 @@ git clone https://gitee.com/openeuler/secGear.git + // build example secure channel + cd secGear/examples/secure_channel + source /opt/intel/sgxsdk/environment +-mkdir debug && cd debug && cmake -DSSL_PATH=/opt/intel/sgxssl .. && make && sudo make install ++mkdir debug && cd debug && cmake .. && make && sudo make install + + // start server + ./bin/sc_server +diff --git a/examples/secure_channel/client/CMakeLists.txt b/examples/secure_channel/client/CMakeLists.txt +index 87838b4..4c05022 100644 +--- a/examples/secure_channel/client/CMakeLists.txt ++++ b/examples/secure_channel/client/CMakeLists.txt +@@ -6,14 +6,14 @@ set(SOURCE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/client.c) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-maybe-uninitialized -fPIE") + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") +- link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) ++ link_directories(/usr/lib64 /usr/local/lib) + endif() + add_executable(${OUTPUT} ${SOURCE_FILE}) + target_include_directories(${OUTPUT} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${SECGEAR_INSTALL_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") +- target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) ++ target_link_directories(${OUTPUT} PRIVATE /usr/lib64 /usr/local/lib) + endif() + target_link_libraries(${OUTPUT} pthread csecure_channel) + +diff --git a/examples/secure_channel/client/client.c b/examples/secure_channel/client/client.c +index 7582ae1..08d2574 100644 +--- a/examples/secure_channel/client/client.c ++++ b/examples/secure_channel/client/client.c +@@ -10,7 +10,7 @@ + #include "secure_channel_client.h" + + +-#define MAXBUF 1024 ++#define MAXBUF 12800 + cc_sec_chl_ctx_t g_ctx = {0}; + + int socket_write_and_read(void *conn, void *buf, size_t count) +@@ -69,6 +69,7 @@ int main(int argc, char **argv) + // step1: 初始化安全通道客户端,注册消息发送函数 + g_ctx.conn_kit.send = (void *)socket_write_and_read; + g_ctx.conn_kit.conn = &sockfd; ++ g_ctx.basevalue = "/vendor/bin/basevalue.txt"; // content format:taid image_hash mem_hash + ret = cc_sec_chl_client_init(CC_SEC_CHL_ALGO_RSA_ECDH_AES_GCM, &g_ctx); + if (ret != CC_SUCCESS) { + printf("secure channel init failed:%u\n", ret); +diff --git a/examples/secure_channel/enclave/CMakeLists.txt b/examples/secure_channel/enclave/CMakeLists.txt +index 9690bed..9485dea 100644 +--- a/examples/secure_channel/enclave/CMakeLists.txt ++++ b/examples/secure_channel/enclave/CMakeLists.txt +@@ -26,7 +26,7 @@ endif() + + if(CC_SGX) + #sgxsdk path +- set(SGX_SDK_PATH ${SGXSDK}) ++ set(SGX_SDK_PATH ${SDK_PATH}) + set(OUTPUT ${PREFIX}.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} +@@ -50,8 +50,8 @@ if(CC_GP) + 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/) ++ set(ITRUSTEE_TEEDIR ${SDK_PATH}/) ++ set(ITRUSTEE_LIBC ${SDK_PATH}/thirdparty/open_source/musl/libc/) + + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + link_directories(${CMAKE_BINARY_DIR}/lib/) +@@ -64,7 +64,7 @@ if(CC_GP) + ${SECGEAR_INSTALL_DIR} + ${ITRUSTEE_TEEDIR}/include/TA + ${ITRUSTEE_TEEDIR}/include/TA/huawei_ext +- ${ITRUSTEE_TEEDIR}/include/TA/openssl ++ ${SDK_PATH}/thirdparty/open_source/openssl + ${ITRUSTEE_LIBC}/arch/aarch64 + ${ITRUSTEE_LIBC}/ + ${ITRUSTEE_LIBC}/arch/arm/bits +@@ -82,9 +82,9 @@ if(CC_GP) + add_definitions(-DWHITE_LIST_OWNER="${WHITE_LIST_OWNER}") + + target_link_libraries(${PREFIX} -ltsecure_channel -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 -m ${CMAKE_CURRENT_SOURCE_DIR}/config_cloud.ini -o ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${OUTPUT}) ++ 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 +diff --git a/examples/secure_channel/enclave/config_cloud.ini b/examples/secure_channel/enclave/config_cloud.ini +index 950c818..8c70225 100644 +--- a/examples/secure_channel/enclave/config_cloud.ini ++++ b/examples/secure_channel/enclave/config_cloud.ini +@@ -1,50 +1,60 @@ +-[config] +-;0 means debug +-;1 means release ++[signSecPrivateCfg] ++;;; ++;private key length for signing TA: + ;[fixed value] +-releaseType = 1 ++;256 ECDSA Alg ++;2048/4096 RSA Alg ++secSignKeyLen = 4096 + ;;; +-;0 means TA not installed by OTRP +-;1 means TA installed by OTRP +-otrpFlag = 0 ++;[fixed value] ++;0 means SHA256 hash type ++;1 means SHA512 hash type ++secHashType = 0 + ;;; +-;server address for signing TA +-serverIp= ++; [fixed value] ++;0 means padding type is pkcs1v15 ++;1 means padding type is PSS ++;[fixed value] ++secPaddingType = 1 + ;;; +-;public key for encrypt TA + ;[fixed value] +-encryptKey = cloud/rsa_public_key_cloud.pem ++;RSA alg ++;ECDSA alg ++;SM2 alg ++secSignAlg = RSA ++;;; ++;public key for encrypt TA ++secEncryptKey = rsa_public_key_cloud.pem + ;;; + ;public key length ++secEncryptKeyLen = 3072 ++ ++[signSecPublicCfg] ++;;; + ;[fixed value] +-encryptKeyLen = 3072 ++; sec sign key type ++;0 means debug ++;1 means release ++secReleaseType = 1 ++;;; ++;0 means TA not installed by OTRP ++;1 means TA installed by OTRP ++secOtrpFlag = 0 + ;;; + ;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 ++secSignType = 1 ++;;; ++;server address for signing TA ++secSignServerIp = + ;;; + ;private key for signing TA +-;this private key is only for the debug mdoe so plaintext private key does exist in the production environment + ;[private key owned by yourself] +-signKey = ../../examples/secure_channel/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 ++secSignKey = /home/TA_cert/private_key.pem + ;;; + ;config file + ;[signed config file by Huawei] +-configPath= ../../examples/secure_channel/enclave/signed_config/config ++configPath = /home/TA_cert/secgear-app1/config +diff --git a/examples/secure_channel/host/CMakeLists.txt b/examples/secure_channel/host/CMakeLists.txt +index 33424f4..bd67eed 100644 +--- a/examples/secure_channel/host/CMakeLists.txt ++++ b/examples/secure_channel/host/CMakeLists.txt +@@ -15,13 +15,13 @@ endif() + + if(CC_SGX) + #sgxsdk path +- set(SGX_SDK_PATH ${SGXSDK}) ++ set(SGX_SDK_PATH ${SDK_PATH}) + 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 ${SECGEAR_INSTALL_DIR} +- --search-path ${SGXSDK}/include ++ --search-path ${SDK_PATH}/include + --search-path ${SSL_PATH}/include) + endif() + +@@ -39,12 +39,12 @@ if(CC_GP) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +- target_link_libraries(${OUTPUT} secgear usecure_channel pthread) ++ target_link_libraries(${OUTPUT} secgear usecure_channel pthread qca) + endif() + + if(CC_SGX) + if(${CMAKE_VERSION} VERSION_LESS "3.13.0") +- link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${SGXSDK}/lib64 ${SSL_PATH}/lib64) ++ link_directories(${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${SDK_PATH}/lib64 ${SSL_PATH}/lib64) + endif() + set(SGX_MODE HW) + set(COMMON_CFLAGS "-m64") +@@ -54,7 +54,7 @@ if(CC_SGX) + ${CMAKE_CURRENT_BINARY_DIR} + ${SECGEAR_INSTALL_DIR}) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") +- target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${SGXSDK}/lib64 ${SSL_PATH}/lib64) ++ target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${SDK_PATH}/lib64 ${SSL_PATH}/lib64) + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${host_C_Flags}") + target_link_libraries(${OUTPUT} secgear usecure_channel pthread sgx_usgxssl) +diff --git a/examples/secure_channel/host/server.c b/examples/secure_channel/host/server.c +index b6d3d62..1f7e54e 100644 +--- a/examples/secure_channel/host/server.c ++++ b/examples/secure_channel/host/server.c +@@ -11,7 +11,7 @@ + #include "sc_demo_u.h" + #include "usr_msg.h" + +-#define MAXBUF 1024 ++#define MAXBUF 10240 + #define MAX_LISTEN_NUM 100 + typedef struct { + cc_sec_chl_svr_ctx_t *svr_ctx; +-- +2.33.0 + diff --git a/0063-some-code-optimize.patch b/0063-some-code-optimize.patch new file mode 100644 index 0000000000000000000000000000000000000000..f6dd1b3dae1e9af3714be1770d89e2c9e800e7fe --- /dev/null +++ b/0063-some-code-optimize.patch @@ -0,0 +1,406 @@ +From 907b34fa937eb6e41f25ebff23db88956842c635 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Sat, 27 May 2023 15:29:01 +0800 +Subject: [PATCH] some code optimize + +--- + .../remote_attest/ra_report/CMakeLists.txt | 2 -- + .../remote_attest/ra_report/gp_ra_report.c | 11 +++---- + .../remote_attest/ra_report/gp_ra_report.h | 24 --------------- + .../remote_attest/ra_report/sgx_ra_report.c | 10 +++---- + .../remote_attest/ra_report/sgx_ra_report.h | 24 --------------- + .../remote_attest/ra_verify/CMakeLists.txt | 3 -- + .../ra_verify/gp_ra_report_verify.c | 11 +++---- + .../ra_verify/gp_ra_report_verify.h | 30 ------------------- + .../ra_verify/sgx_ra_report_verify.c | 9 ++---- + .../ra_verify/sgx_ra_report_verify.h | 30 ------------------- + examples/secure_channel/client/CMakeLists.txt | 6 +++- + .../client_with_recv_thread/CMakeLists.txt | 5 +++- + .../client_with_recv_thread/client.c | 3 +- + 13 files changed, 26 insertions(+), 142 deletions(-) + delete mode 100644 component/remote_attest/ra_report/gp_ra_report.h + delete mode 100644 component/remote_attest/ra_report/sgx_ra_report.h + delete mode 100644 component/remote_attest/ra_verify/gp_ra_report_verify.h + delete mode 100644 component/remote_attest/ra_verify/sgx_ra_report_verify.h + +diff --git a/component/remote_attest/ra_report/CMakeLists.txt b/component/remote_attest/ra_report/CMakeLists.txt +index 548e786..2f00dc7 100644 +--- a/component/remote_attest/ra_report/CMakeLists.txt ++++ b/component/remote_attest/ra_report/CMakeLists.txt +@@ -45,5 +45,3 @@ install(TARGETS ${TARGET} + LIBRARY + DESTINATION ${LIBRARY_INSTALL} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +- +- +diff --git a/component/remote_attest/ra_report/gp_ra_report.c b/component/remote_attest/ra_report/gp_ra_report.c +index 978127a..4625cd3 100644 +--- a/component/remote_attest/ra_report/gp_ra_report.c ++++ b/component/remote_attest/ra_report/gp_ra_report.c +@@ -9,9 +9,6 @@ + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ +- +-#include "gp_ra_report.h" +- + #include + #include + #include "ra_client_api.h" +@@ -171,7 +168,7 @@ static cc_enclave_result_t gp_ra_provision_no_as() + return CC_SUCCESS; + } + +-cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario) ++static cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario) + { + cc_enclave_result_t ret = CC_SUCCESS; + switch (scenario) { +@@ -184,7 +181,7 @@ cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario) + return ret; + } + +-cc_enclave_result_t gp_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report) ++static cc_enclave_result_t gp_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report) + { + cc_ra_buf_t *ra_buf_in = NULL; + cc_enclave_result_t ret = gen_ra_report_in_buff(in, &ra_buf_in); +@@ -203,12 +200,12 @@ cc_enclave_result_t gp_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t * + return CC_SUCCESS; + } + +-uni_ree_agent_t g_gp_agent = { ++static uni_ree_agent_t g_gp_agent = { + .tee_type = CC_TEE_TYPE_GP, + .prepare_ra_env = gp_prepare_ra_env, + .get_ra_report = gp_get_ra_report, + }; +-static __attribute__((constructor)) void gp_register_ree_agent() ++static __attribute__((constructor)) void gp_register_ree_agent(void) + { + cc_register_ree_agent(&g_gp_agent); + } +\ No newline at end of file +diff --git a/component/remote_attest/ra_report/gp_ra_report.h b/component/remote_attest/ra_report/gp_ra_report.h +deleted file mode 100644 +index ed58bb0..0000000 +--- a/component/remote_attest/ra_report/gp_ra_report.h ++++ /dev/null +@@ -1,24 +0,0 @@ +-/* +- * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +- * secGear is licensed under the Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +- * PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-#ifndef SECGEAR_GP_RA_REPORT_H +-#define SECGEAR_GP_RA_REPORT_H +- +-#include "status.h" +-#include "sg_report_st.h" +- +-cc_enclave_result_t gp_prepare_ra_env(cc_ra_scenario_t scenario); +- +-cc_enclave_result_t gp_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report); +- +-#endif +- +diff --git a/component/remote_attest/ra_report/sgx_ra_report.c b/component/remote_attest/ra_report/sgx_ra_report.c +index 8d02fc3..6bd0bdc 100644 +--- a/component/remote_attest/ra_report/sgx_ra_report.c ++++ b/component/remote_attest/ra_report/sgx_ra_report.c +@@ -9,17 +9,15 @@ + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ +- +-#include "sgx_ra_report.h" + #include "uni_ree_agent.h" + +-cc_enclave_result_t sgx_prepare_ra_env(cc_ra_scenario_t scenario) ++static cc_enclave_result_t sgx_prepare_ra_env(cc_ra_scenario_t scenario) + { + (void)scenario; + return CC_SUCCESS; + } + +-cc_enclave_result_t sgx_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report) ++static cc_enclave_result_t sgx_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report) + { + (void)in; + (void)report; +@@ -27,12 +25,12 @@ cc_enclave_result_t sgx_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t + return CC_SUCCESS; + } + +-uni_ree_agent_t g_sgx_agent = { ++static uni_ree_agent_t g_sgx_agent = { + .tee_type = CC_TEE_TYPE_SGX, + .prepare_ra_env = sgx_prepare_ra_env, + .get_ra_report = sgx_get_ra_report, + }; +-static __attribute__((constructor)) void sgx_register_ree_agent() ++static __attribute__((constructor)) void sgx_register_ree_agent(void) + { + cc_register_ree_agent(&g_sgx_agent); + } +\ No newline at end of file +diff --git a/component/remote_attest/ra_report/sgx_ra_report.h b/component/remote_attest/ra_report/sgx_ra_report.h +deleted file mode 100644 +index d9a33cc..0000000 +--- a/component/remote_attest/ra_report/sgx_ra_report.h ++++ /dev/null +@@ -1,24 +0,0 @@ +-/* +- * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +- * secGear is licensed under the Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +- * PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-#ifndef SECGEAR_SGX_RA_REPORT_H +-#define SECGEAR_SGX_RA_REPORT_H +- +-#include "status.h" +-#include "sg_report_st.h" +- +-cc_enclave_result_t sgx_prepare_ra_env(cc_ra_scenario_t scenario); +- +-cc_enclave_result_t sgx_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report); +- +-#endif +- +diff --git a/component/remote_attest/ra_verify/CMakeLists.txt b/component/remote_attest/ra_verify/CMakeLists.txt +index 53707b1..54b2eca 100644 +--- a/component/remote_attest/ra_verify/CMakeLists.txt ++++ b/component/remote_attest/ra_verify/CMakeLists.txt +@@ -31,7 +31,6 @@ if(${CMAKE_VERSION} VERSION_LESS "3.13.0") + endif() + + include_directories( +- ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${LOCAL_ROOT_PATH}/inc/host_inc +@@ -49,5 +48,3 @@ install(TARGETS ${TARGET} + LIBRARY + DESTINATION ${LIBRARY_INSTALL} + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +- +- +diff --git a/component/remote_attest/ra_verify/gp_ra_report_verify.c b/component/remote_attest/ra_verify/gp_ra_report_verify.c +index 76debb4..f74c2ea 100644 +--- a/component/remote_attest/ra_verify/gp_ra_report_verify.c ++++ b/component/remote_attest/ra_verify/gp_ra_report_verify.c +@@ -9,15 +9,12 @@ + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ +- +-#include "gp_ra_report_verify.h" +- + #include "teeverifier.h" + #include "enclave_log.h" + + #include "uni_ra_verify_agent.h" + +-int convert_cctype_to_gptype(cc_ra_verify_type_t type) ++static int convert_cctype_to_gptype(cc_ra_verify_type_t type) + { + // gp type, 1: compare image hash; 2: compare mem hash; 3: compare image and mem hash + if (type == CC_RA_VERIFY_TYPE_LOOSE) { +@@ -29,7 +26,7 @@ int convert_cctype_to_gptype(cc_ra_verify_type_t type) + } + } + +-cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, ++static cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, + cc_ra_verify_type_t type, char *basevalue) + { + int gp_type = convert_cctype_to_gptype(type); +@@ -52,10 +49,10 @@ cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, + return ret; + } + +-uni_ra_verify_agent_t g_gp_ra_verify_agent = { ++static uni_ra_verify_agent_t g_gp_ra_verify_agent = { + .verify_ra_report = gp_verify_report, + }; +-static __attribute__((constructor)) void gp_register_ra_agent() ++static __attribute__((constructor)) void gp_register_ra_agent(void) + { + cc_register_ra_verify_agent(&g_gp_ra_verify_agent); + } +\ No newline at end of file +diff --git a/component/remote_attest/ra_verify/gp_ra_report_verify.h b/component/remote_attest/ra_verify/gp_ra_report_verify.h +deleted file mode 100644 +index 68a7c38..0000000 +--- a/component/remote_attest/ra_verify/gp_ra_report_verify.h ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* +- * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +- * secGear is licensed under the Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +- * PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-#ifndef SECGEAR_GP_RA_REPORT_VERIFY_H +-#define SECGEAR_GP_RA_REPORT_VERIFY_H +- +-#include "status.h" +-#include "sg_report_st.h" +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-cc_enclave_result_t gp_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, +- cc_ra_verify_type_t type, char *basevalue); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif +diff --git a/component/remote_attest/ra_verify/sgx_ra_report_verify.c b/component/remote_attest/ra_verify/sgx_ra_report_verify.c +index 0e2e81f..e2472a3 100644 +--- a/component/remote_attest/ra_verify/sgx_ra_report_verify.c ++++ b/component/remote_attest/ra_verify/sgx_ra_report_verify.c +@@ -9,12 +9,9 @@ + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ +- +-#include "sgx_ra_report_verify.h" +- + #include "uni_ra_verify_agent.h" + +-cc_enclave_result_t sgx_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, ++static cc_enclave_result_t sgx_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, + cc_ra_verify_type_t type, char *basevalue) + { + (void)report; +@@ -24,10 +21,10 @@ cc_enclave_result_t sgx_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, + return CC_SUCCESS; + } + +-uni_ra_verify_agent_t g_sgx_ra_verify_agent = { ++static uni_ra_verify_agent_t g_sgx_ra_verify_agent = { + .verify_ra_report = sgx_verify_report, + }; +-static __attribute__((constructor)) void gp_register_ra_agent() ++static __attribute__((constructor)) void gp_register_ra_agent(void) + { + cc_register_ra_verify_agent(&g_sgx_ra_verify_agent); + } +\ No newline at end of file +diff --git a/component/remote_attest/ra_verify/sgx_ra_report_verify.h b/component/remote_attest/ra_verify/sgx_ra_report_verify.h +deleted file mode 100644 +index 773f484..0000000 +--- a/component/remote_attest/ra_verify/sgx_ra_report_verify.h ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* +- * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. +- * secGear is licensed under the Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +- * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +- * PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-#ifndef SECGEAR_SGX_RA_REPORT_VERIFY_H +-#define SECGEAR_SGX_RA_REPORT_VERIFY_H +- +-#include "status.h" +-#include "sg_report_st.h" +- +-#ifdef __cplusplus +-extern "C" { +-#endif +- +-cc_enclave_result_t sgx_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, +- cc_ra_verify_type_t type, char *basevalue); +- +-#ifdef __cplusplus +-} +-#endif +- +-#endif +diff --git a/examples/secure_channel/client/CMakeLists.txt b/examples/secure_channel/client/CMakeLists.txt +index 4c05022..ea8f079 100644 +--- a/examples/secure_channel/client/CMakeLists.txt ++++ b/examples/secure_channel/client/CMakeLists.txt +@@ -15,7 +15,11 @@ target_include_directories(${OUTPUT} PRIVATE + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE /usr/lib64 /usr/local/lib) + endif() +-target_link_libraries(${OUTPUT} pthread csecure_channel) ++if (CC_GP) ++ set(THIRDPARTY_VERIFY teeverifier) ++endif() ++ ++target_link_libraries(${OUTPUT} pthread csecure_channel ${THIRDPARTY_VERIFY}) + + set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +diff --git a/examples/secure_channel/client_with_recv_thread/CMakeLists.txt b/examples/secure_channel/client_with_recv_thread/CMakeLists.txt +index 63f2c78..1e27d72 100644 +--- a/examples/secure_channel/client_with_recv_thread/CMakeLists.txt ++++ b/examples/secure_channel/client_with_recv_thread/CMakeLists.txt +@@ -15,7 +15,10 @@ target_include_directories(${OUTPUT} PRIVATE + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0") + target_link_directories(${OUTPUT} PRIVATE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + endif() +-target_link_libraries(${OUTPUT} pthread csecure_channel) ++if (CC_GP) ++ set(THIRDPARTY_VERIFY teeverifier) ++endif() ++target_link_libraries(${OUTPUT} pthread csecure_channel ${THIRDPARTY_VERIFY}) + + set_target_properties(${OUTPUT} PROPERTIES SKIP_BUILD_RPATH TRUE) + +diff --git a/examples/secure_channel/client_with_recv_thread/client.c b/examples/secure_channel/client_with_recv_thread/client.c +index 52ebc10..db142bb 100644 +--- a/examples/secure_channel/client_with_recv_thread/client.c ++++ b/examples/secure_channel/client_with_recv_thread/client.c +@@ -10,7 +10,7 @@ + #include "secure_channel_client.h" + + +-#define MAXBUF 1024 ++#define MAXBUF 12800 + cc_sec_chl_ctx_t g_ctx = {0}; + + void *recv_msg_thread(void *arg) +@@ -87,6 +87,7 @@ int main(int argc, char **argv) + // step1: 初始化安全通道客户端,注册消息发送函数 + g_ctx.conn_kit.send = (void *)socket_write_adpt; + g_ctx.conn_kit.conn = &sockfd; ++ g_ctx.basevalue = "/vendor/bin/basevalue.txt"; // content format:taid image_hash mem_hash + + // step2: 创建消息接收线程 + pthread_t thread; +-- +2.33.0 + diff --git a/0064-support-local-attest.patch b/0064-support-local-attest.patch new file mode 100644 index 0000000000000000000000000000000000000000..fc6dc2336c86ebabd30bca5e6306bd4d443bed92 --- /dev/null +++ b/0064-support-local-attest.patch @@ -0,0 +1,852 @@ +From d866feaeb8476541025efa4325459fae3f7f3493 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Mon, 29 May 2023 21:29:46 +0800 +Subject: [PATCH] support local attest + +--- + CMakeLists.txt | 9 +- + component/CMakeLists.txt | 1 + + component/local_attest/CMakeLists.txt | 60 +++++++ + component/local_attest/gp_local_attest.c | 153 ++++++++++++++++++ + component/local_attest/local_attest_agent.h | 28 ++++ + component/local_attest/sg_local_attest.c | 22 +++ + component/local_attest/sg_local_attest.h | 29 ++++ + component/local_attest/sgx_local_attest.c | 20 +++ + .../remote_attest/ra_report/CMakeLists.txt | 2 +- + .../remote_attest/ra_report/gp_ra_report.c | 131 +-------------- + .../ra_report/gp_report_helper.c | 121 ++++++++++++++ + .../ra_report/gp_report_helper.h | 24 +++ + .../client/secure_channel_client.c | 7 +- + .../secure_channel/enclave/CMakeLists.txt | 3 - + examples/secure_channel/basevalue.txt | 1 + + examples/secure_channel/client/client.c | 9 +- + .../client_with_recv_thread/client.c | 9 +- + inc/host_inc/status.h | 2 + + 18 files changed, 489 insertions(+), 142 deletions(-) + create mode 100644 component/local_attest/CMakeLists.txt + create mode 100644 component/local_attest/gp_local_attest.c + create mode 100644 component/local_attest/local_attest_agent.h + create mode 100644 component/local_attest/sg_local_attest.c + create mode 100644 component/local_attest/sg_local_attest.h + create mode 100644 component/local_attest/sgx_local_attest.c + create mode 100644 component/remote_attest/ra_report/gp_report_helper.c + create mode 100644 component/remote_attest/ra_report/gp_report_helper.h + create mode 100644 examples/secure_channel/basevalue.txt + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 079be3b..25e6381 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -17,9 +17,6 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + + set(LOCAL_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +- +-set(SECGEAR_DEBUG_LEVEL SECGEAR_LOG_LEVEL_DEBUG) +-add_definitions(-DSECGEAR_DEBUG_LEVEL=${SECGEAR_DEBUG_LEVEL}) + message("=============cmake help info=======================") + message("Example default cmd: cmake ..") + message("same with default: cmake -DENCLAVE=SGX -DSDK_PATH=/opt/intel/sgxsdk -DSSL_PATH=/opt/intel/sgxssl ..") +@@ -40,6 +37,12 @@ set(PL_SDK_DEFAULT_PATH /root/dev/sdk) + + if(CMAKE_BUILD_TYPE MATCHES "Debug") + add_definitions(-DDEBUG_FILE_LINE) ++ #set enclave log level ++ set(PRINT_LEVEL 3) ++ add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) ++ #set host log level ++ set(SECGEAR_DEBUG_LEVEL SECGEAR_LOG_LEVEL_DEBUG) ++ add_definitions(-DSECGEAR_DEBUG_LEVEL=${SECGEAR_DEBUG_LEVEL}) + endif() + set(CMAKE_C_FLAGS "-fstack-protector-all -W -Wall -Werror -Wextra -Werror=array-bounds -D_FORTIFY_SOURCE=2 -O2 -ftrapv") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -s") +diff --git a/component/CMakeLists.txt b/component/CMakeLists.txt +index 7442334..83aa4cd 100644 +--- a/component/CMakeLists.txt ++++ b/component/CMakeLists.txt +@@ -13,6 +13,7 @@ set(LIBRARY_INSTALL ${LOCAL_ROOT_PATH_INSTALL}/usr/lib64) + ADD_SUBDIRECTORY(secure_channel) + + ADD_SUBDIRECTORY(remote_attest) ++ADD_SUBDIRECTORY(local_attest) + + + +diff --git a/component/local_attest/CMakeLists.txt b/component/local_attest/CMakeLists.txt +new file mode 100644 +index 0000000..45ebf82 +--- /dev/null ++++ b/component/local_attest/CMakeLists.txt +@@ -0,0 +1,60 @@ ++# Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++# secGear is licensed under the Mulan PSL v2. ++# You can use this software according to the terms and conditions of the Mulan PSL v2. ++# You may obtain a copy of Mulan PSL v2 at: ++# http://license.coscl.org.cn/MulanPSL2 ++# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++# PURPOSE. ++# See the Mulan PSL v2 for more details. ++set(target_lib secgear_la) ++ ++set(CMAKE_C_FLAGS "-W -Wall -fno-short-enums -fno-omit-frame-pointer -fstack-protector-strong -Wstack-protector \ ++ --param ssp-buffer-size=4 -frecord-gcc-switches -Wextra -nostdinc -nodefaultlibs -fno-peephole \ ++ -fno-peephole2 -Wno-main -Wno-error=unused-parameter -Wno-error=unused-but-set-variable \ ++ -Wno-error=format-truncation= -D_FORTIFY_SOURCE=2 -O2") ++set(COMMON_C_LINK_FLAGS "-Wl,-z,now -Wl,-z,relro -Wl,-z,noexecstack -Wl,-nostdlib -nodefaultlibs -nostartfiles") ++ ++set(SOURCE_FILES sg_local_attest.c) ++ ++if(CC_SGX) ++ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS}") ++ add_definitions(-DSGX_ENCLAVE) ++ set(SOURCE_FILES ${SOURCE_FILES} sgx_local_attest.c) ++endif() ++ ++if(CC_GP) ++ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a -fPIC") ++ set(CMAKE_SHARED_LINKER_FLAGS "${COMMON_C_LINK_FLAGS} -Wl,-s") ++ add_definitions(-DGP_ENCLAVE) ++ aux_source_directory(${LOCAL_ROOT_PATH}/thirdparty/cjson/ CJSON_SRC) ++ FILE (GLOB_RECURSE BASE64_SRC "${LOCAL_ROOT_PATH}/thirdparty/base64url/*.c") ++ set(REPORT_HELPER ${LOCAL_ROOT_PATH}/component/remote_attest/ra_report/gp_report_helper.c) ++ set(SOURCE_FILES ${SOURCE_FILES} gp_local_attest.c ${CJSON_SRC} ${BASE64_SRC} ${REPORT_HELPER}) ++ set(INCLUDE_DIR ${SDK_PATH}/include/TA ++ ${SDK_PATH}/include/TA/huawei_ext ++ ${SDK_PATH}/thirdparty/open_source/musl/libc ++ ${SDK_PATH}/thirdparty/open_source/musl/libc/arch/aarch64 ++ ${SDK_PATH}/thirdparty/open_source/musl/libc/arch/generic ++ ${LOCAL_ROOT_PATH}/thirdparty/cjson ++ ${LOCAL_ROOT_PATH}/thirdparty/base64url ++ ${LOCAL_ROOT_PATH}/inc/enclave_inc/gp/itrustee) ++endif() ++ ++add_library(${target_lib} STATIC ${SOURCE_FILES}) ++ ++target_include_directories(${target_lib} PRIVATE ++ ${LOCAL_ROOT_PATH}/inc/host_inc ++ ${LOCAL_ROOT_PATH}/component/remote_attest ++ ${LOCAL_ROOT_PATH}/component/remote_attest/ra_report ++ ${INCLUDE_DIR}) ++ ++install(TARGETS ${target_lib} ++ ARCHIVE ++ DESTINATION ${LIBRARY_INSTALL} ++ PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) ++ ++file(GLOB LA_HEADERS sg_local_attest.h) ++install(FILES ${LA_HEADERS} ++ DESTINATION /usr/include/secGear ++ PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) +diff --git a/component/local_attest/gp_local_attest.c b/component/local_attest/gp_local_attest.c +new file mode 100644 +index 0000000..7f75147 +--- /dev/null ++++ b/component/local_attest/gp_local_attest.c +@@ -0,0 +1,153 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++#include ++#include ++#include ++#include "tee_ra_api.h" ++#include "tee_crypto_api.h" ++#include "base64url.h" ++#include "cJSON.h" ++#include "secgear_log.h" ++#include "status.h" ++#include "sg_report_st.h" ++#include "local_attest_agent.h" ++#include "gp_report_helper.h" ++ ++#define CC_HASH_LEN 64 ++typedef struct { ++ char *taid; ++ char *img_hash; ++ char *mem_hash; ++} gp_basevalue_t; ++ ++#define HEX_ONE_CHAR_BITS 4 ++#define HEX_BYTE_MAX 0xf ++ ++static void hex2str(const uint8_t *source, int source_len, char *dest) ++{ ++ char *hexEncode = "0123456789abcdef"; ++ int i = 0, j = 0; ++ for (i = 0; i < source_len; i++) { ++ dest[j++] = hexEncode[(source[i] >> HEX_ONE_CHAR_BITS) & HEX_BYTE_MAX]; ++ dest[j++] = hexEncode[(source[i]) & HEX_BYTE_MAX]; ++ } ++} ++ ++static cc_enclave_result_t gp_compare_hash(gp_basevalue_t *basevalue, char *ta_img, char *ta_mem) ++{ ++ size_t imglen = 0; ++ size_t memlen = 0; ++ uint8_t *decodedimg = kpsecl_base64urldecode(ta_img, strlen(ta_img), &imglen); ++ uint8_t *decodedmem = kpsecl_base64urldecode(ta_mem, strlen(ta_mem), &memlen); ++ ++ char heximg[CC_HASH_LEN + 1] = {0}; ++ char hexmem[CC_HASH_LEN + 1] = {0}; ++ hex2str(decodedimg, imglen, heximg); ++ hex2str(decodedmem, memlen, hexmem); ++ free(decodedimg); ++ free(decodedmem); ++ ++ PrintInfo(PRINT_STRACE, "heximg:%s, hexmem:%s", heximg, hexmem); ++ PrintInfo(PRINT_STRACE, "img_hash:%s, mem_hash:%s", basevalue->img_hash, basevalue->mem_hash); ++ ++ if (memcmp(heximg, basevalue->img_hash, strlen(basevalue->img_hash)) != 0 || ++ memcmp(hexmem, basevalue->mem_hash, strlen(basevalue->mem_hash)) != 0) { ++ PrintInfo(PRINT_ERROR, "verify local report hash failed!\n"); ++ return CC_ERROR_LOCAL_REPORT_HASH_MISMATCH; ++ } ++ return CC_SUCCESS; ++} ++ ++static cc_enclave_result_t gp_verify_local_report(gp_basevalue_t *basevalue, uint8_t *nonce, size_t nonce_len, ++ cc_ra_buf_t *report) ++{ ++ char *b64_nonce = NULL; ++ size_t b64_nonce_len = 0; ++ cc_enclave_result_t ret = CC_ERROR_LOCAL_REPORT_INVALID; ++ ++ cJSON *cj_report = cJSON_ParseWithLength((char *)report->buf, report->len); ++ if (cj_report == NULL) { ++ PrintInfo(PRINT_ERROR, "report to json failed\n"); ++ return ret; ++ } ++ cJSON *cj_payload = cJSON_GetObjectItemCaseSensitive(cj_report, "payload"); ++ if (cj_payload == NULL) { ++ PrintInfo(PRINT_ERROR, "report payload failed!\n"); ++ goto end; ++ } ++ b64_nonce = kpsecl_base64urlencode(nonce, nonce_len, &b64_nonce_len); ++ cJSON *cj_b64_nonce = cJSON_GetObjectItemCaseSensitive(cj_payload, "nonce"); ++ if (cj_b64_nonce == NULL || strcmp(cj_b64_nonce->valuestring, b64_nonce)) { ++ PrintInfo(PRINT_ERROR, "check nonce value failed!\n"); ++ free(b64_nonce); ++ goto end; ++ } ++ free(b64_nonce); ++ ++ cJSON *cj_uuid = cJSON_GetObjectItemCaseSensitive(cj_payload, "uuid"); ++ if (cj_uuid == NULL || strcmp(cj_uuid->valuestring, basevalue->taid)) { ++ PrintInfo(PRINT_ERROR, "check uuid failed!\n"); ++ goto end; ++ } ++ cJSON *cj_ta_img = cJSON_GetObjectItemCaseSensitive(cj_payload, "ta_img"); ++ if (cj_ta_img == NULL) { ++ PrintInfo(PRINT_ERROR, "check ta_img failed!\n"); ++ goto end; ++ } ++ cJSON *cj_ta_mem = cJSON_GetObjectItemCaseSensitive(cj_payload, "ta_mem"); ++ if (cj_ta_mem == NULL) { ++ PrintInfo(PRINT_ERROR, "check ta_mem failed!\n"); ++ goto end; ++ } ++ ++ ret = gp_compare_hash(basevalue, cj_ta_img->valuestring, cj_ta_mem->valuestring); ++end: ++ cJSON_Delete(cj_report); ++ ++ return ret; ++} ++ ++#define LOCAL_REPORT_OUT_LEN 0x3000 ++#define LOCAL_REPORT_NONCE_LEN 32 ++cc_enclave_result_t agent_local_attest(char *taid, char *img_hash, char *mem_hash) ++{ ++ cc_get_ra_report_input_t ra_input = {0}; ++ ra_input.taid = (uint8_t *)taid; ++ ra_input.with_tcb = false; ++ ++ TEE_GenerateRandom(ra_input.nonce, LOCAL_REPORT_NONCE_LEN); ++ ra_input.nonce_len = LOCAL_REPORT_NONCE_LEN + 1; ++ ++ cc_ra_buf_t *in = NULL; ++ cc_enclave_result_t ret = gen_ra_report_in_buff(&ra_input, &in); ++ if (ret != CC_SUCCESS) { ++ PrintInfo(PRINT_ERROR, "gen ra report in buff error! ret:%x\n", ret); ++ return -1; ++ } ++ ++ uint8_t data[LOCAL_REPORT_OUT_LEN] = {0}; ++ cc_ra_buf_t report = {LOCAL_REPORT_OUT_LEN, data}; ++ ++ TEE_Result gp_ret = ra_local_report((struct ra_buffer_data *)in, (struct ra_buffer_data *)&report); ++ free_cc_ra_buf(in); ++ if (gp_ret != CC_SUCCESS) { ++ PrintInfo(PRINT_ERROR, "get ra report failed, ret:%x\n", gp_ret); ++ return CC_ERROR_RA_GET_REPORT; ++ } ++ ++ gp_basevalue_t basevalue = { ++ .taid = taid, ++ .img_hash = img_hash, ++ .mem_hash = mem_hash, ++ }; ++ return gp_verify_local_report(&basevalue, ra_input.nonce, ra_input.nonce_len, &report); ++} +diff --git a/component/local_attest/local_attest_agent.h b/component/local_attest/local_attest_agent.h +new file mode 100644 +index 0000000..c79bc03 +--- /dev/null ++++ b/component/local_attest/local_attest_agent.h +@@ -0,0 +1,28 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_LOCAL_ATTEST_AGENT_H ++#define SECGEAR_LOCAL_ATTEST_AGENT_H ++ ++#include "status.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++cc_enclave_result_t agent_local_attest(char *taid, char *img_hash, char *mem_hash); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/component/local_attest/sg_local_attest.c b/component/local_attest/sg_local_attest.c +new file mode 100644 +index 0000000..f94473e +--- /dev/null ++++ b/component/local_attest/sg_local_attest.c +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++#include "sg_local_attest.h" ++#include "local_attest_agent.h" ++ ++cc_enclave_result_t cc_local_attest(char *taid, char *img_hash, char *mem_hash) ++{ ++ if (taid == NULL || (img_hash == NULL && mem_hash == NULL)) { ++ return CC_ERROR_BAD_PARAMETERS; ++ } ++ ++ return agent_local_attest(taid, img_hash, mem_hash); ++} +diff --git a/component/local_attest/sg_local_attest.h b/component/local_attest/sg_local_attest.h +new file mode 100644 +index 0000000..97f31ef +--- /dev/null ++++ b/component/local_attest/sg_local_attest.h +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_LOCAL_ATTESTATION_H ++#define SECGEAR_LOCAL_ATTESTATION_H ++ ++#include "status.h" ++#include "secgear_defs.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++CC_API_SPEC cc_enclave_result_t cc_local_attest(char *taid, char *img_hash, char *mem_hash); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/component/local_attest/sgx_local_attest.c b/component/local_attest/sgx_local_attest.c +new file mode 100644 +index 0000000..aa772b0 +--- /dev/null ++++ b/component/local_attest/sgx_local_attest.c +@@ -0,0 +1,20 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++#include "local_attest_agent.h" ++ ++cc_enclave_result_t agent_local_attest(char *taid, char *img_hash, char *mem_hash) ++{ ++ (void)taid; ++ (void)img_hash; ++ (void)mem_hash; ++ return CC_SUCCESS; ++} +diff --git a/component/remote_attest/ra_report/CMakeLists.txt b/component/remote_attest/ra_report/CMakeLists.txt +index 2f00dc7..4314f02 100644 +--- a/component/remote_attest/ra_report/CMakeLists.txt ++++ b/component/remote_attest/ra_report/CMakeLists.txt +@@ -20,7 +20,7 @@ endif() + if(CC_GP) + aux_source_directory(${LOCAL_ROOT_PATH}/thirdparty/cjson/ CJSON_SRC) + FILE (GLOB_RECURSE BASE64_SRC "${LOCAL_ROOT_PATH}/thirdparty/base64url/*.c") +- set(SRC_FILES ${SRC_FILES} ${CJSON_SRC} ${BASE64_SRC} gp_ra_report.c) ++ set(SRC_FILES ${SRC_FILES} ${CJSON_SRC} ${BASE64_SRC} gp_ra_report.c gp_report_helper.c) + set(INCLUDE_DIR ${SDK_PATH}/include/CA + ${LOCAL_ROOT_PATH}/thirdparty/cjson + ${LOCAL_ROOT_PATH}/thirdparty/libqca +diff --git a/component/remote_attest/ra_report/gp_ra_report.c b/component/remote_attest/ra_report/gp_ra_report.c +index 4625cd3..ca1fa03 100644 +--- a/component/remote_attest/ra_report/gp_ra_report.c ++++ b/component/remote_attest/ra_report/gp_ra_report.c +@@ -13,136 +13,8 @@ + #include + #include "ra_client_api.h" + #include "enclave_log.h" +-#include "cJSON.h" +-#include "base64url.h" +- + #include "uni_ree_agent.h" +- +-static void free_cc_ra_buf(cc_ra_buf_t *ra_buf) +-{ +- if (ra_buf == NULL) { +- return; +- } +- if (ra_buf->buf != NULL) { +- free(ra_buf->buf); +- } +- +- free(ra_buf); +- return; +-} +- +-/* caller need to free (cc_ra_buf_t **in) */ +-static cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in) +-{ +- if (in == NULL) { +- return CC_ERROR_BAD_PARAMETERS; +- } +- cc_enclave_result_t ret = CC_SUCCESS; +- cJSON *in_json = cJSON_CreateObject(); +- cJSON_AddStringToObject(in_json, "handler", "provisioning-input"); +- +- cJSON *in_payload = cJSON_CreateObject(); +- cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); +- cJSON_AddStringToObject(in_payload, "scenario", "sce_no_as"); +- cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); +- +- cJSON_AddItemToObject(in_json, "payload", in_payload); +- +- char *in_buf = cJSON_PrintUnformatted(in_json); +- uint32_t in_buf_len = strlen(in_buf) + 1; +- +- cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); +- if (tmp_ra_buf == NULL) { +- ret = CC_ERROR_RA_MEMORY; +- goto end; +- } +- tmp_ra_buf->buf = calloc(1, in_buf_len); +- if (tmp_ra_buf->buf == NULL) { +- ret = CC_ERROR_RA_MEMORY; +- free(tmp_ra_buf); +- goto end; +- } +- (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); +- tmp_ra_buf->len = in_buf_len; +- +- *in = tmp_ra_buf; +-end: +- cJSON_free(in_buf); +- cJSON_Delete(in_json); +- return ret; +-} +- +-/* caller need to free (cc_ra_buf_t **in) */ +-static cc_enclave_result_t gen_ra_report_in_buff(cc_get_ra_report_input_t *param, cc_ra_buf_t **json_buf) +-{ +- if (param == NULL || param->taid == NULL || json_buf == NULL) { +- return CC_ERROR_BAD_PARAMETERS; +- } +- cc_enclave_result_t ret = CC_SUCCESS; +- cJSON *in_json = cJSON_CreateObject(); +- cJSON_AddStringToObject(in_json, "handler", "report-input"); +- +- size_t b64_nonce_len = 0; +- char *b64_nonce = kpsecl_base64urlencode(param->nonce, param->nonce_len, &b64_nonce_len); +- +- cJSON *in_payload = cJSON_CreateObject(); +- cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); +- cJSON_AddStringToObject(in_payload, "nonce", b64_nonce); +- free(b64_nonce); +- cJSON_AddStringToObject(in_payload, "uuid", (char *)param->taid); +- cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); +- cJSON_AddBoolToObject(in_payload, "with_tcb", param->with_tcb); +- if (param->req_key) { +- cJSON_AddBoolToObject(in_payload, "request_key", param->req_key); +- } +- +- cJSON_AddItemToObject(in_json, "payload", in_payload); +- +- char *in_buf = cJSON_PrintUnformatted(in_json); +- uint32_t in_buf_len = strlen(in_buf) + 1; +- +- print_debug("get ra report input json buf:%s\n", in_buf); +- +- cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); +- if (tmp_ra_buf == NULL) { +- ret = CC_ERROR_RA_MEMORY; +- goto end; +- } +- tmp_ra_buf->buf = calloc(1, in_buf_len); +- if (tmp_ra_buf->buf == NULL) { +- ret = CC_ERROR_RA_MEMORY; +- free(tmp_ra_buf); +- goto end; +- } +- (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); +- tmp_ra_buf->len = in_buf_len; +- +- *json_buf = (cc_ra_buf_t *)tmp_ra_buf; +-end: +- cJSON_free(in_buf); +- cJSON_Delete(in_json); +- return ret; +-} +- +-static void print_ra_report(cc_ra_buf_t *report) +-{ +- if (report == NULL || report->buf == NULL) { +- return; +- } +- cJSON *cj_report = cJSON_ParseWithLength((char *)report->buf, report->len); +- if (cj_report == NULL) { +- // print_debug("cjson parse report error!\n"); +- return; +- } +- char *str_report = cJSON_Print(cj_report); +- +- print_debug("report:%s\n", str_report); +- print_debug("report len:%u, str_len:%lu\n", report->len, strlen(str_report)); +- +- cJSON_free(str_report); +- cJSON_Delete(cj_report); +- return; +-} ++#include "gp_report_helper.h" + + #define PROVISION_OUT_LEN 0x3000 + static cc_enclave_result_t gp_ra_provision_no_as() +@@ -195,7 +67,6 @@ static cc_enclave_result_t gp_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_ + print_error_term("get ra report failed, ret:%x\n", gp_ret); + return CC_ERROR_RA_GET_REPORT; + } +- print_ra_report(report); + + return CC_SUCCESS; + } +diff --git a/component/remote_attest/ra_report/gp_report_helper.c b/component/remote_attest/ra_report/gp_report_helper.c +new file mode 100644 +index 0000000..0a73745 +--- /dev/null ++++ b/component/remote_attest/ra_report/gp_report_helper.c +@@ -0,0 +1,121 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++#include ++#include ++#include "cJSON.h" ++#include "base64url.h" ++#include "gp_report_helper.h" ++ ++void free_cc_ra_buf(cc_ra_buf_t *ra_buf) ++{ ++ if (ra_buf == NULL) { ++ return; ++ } ++ if (ra_buf->buf != NULL) { ++ free(ra_buf->buf); ++ } ++ ++ free(ra_buf); ++ return; ++} ++ ++/* caller need to free (cc_ra_buf_t **in) */ ++cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in) ++{ ++ if (in == NULL) { ++ return CC_ERROR_BAD_PARAMETERS; ++ } ++ cc_enclave_result_t ret = CC_SUCCESS; ++ cJSON *in_json = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_json, "handler", "provisioning-input"); ++ ++ cJSON *in_payload = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); ++ cJSON_AddStringToObject(in_payload, "scenario", "sce_no_as"); ++ cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); ++ ++ cJSON_AddItemToObject(in_json, "payload", in_payload); ++ ++ char *in_buf = cJSON_PrintUnformatted(in_json); ++ uint32_t in_buf_len = strlen(in_buf) + 1; ++ ++ cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); ++ if (tmp_ra_buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ goto end; ++ } ++ tmp_ra_buf->buf = calloc(1, in_buf_len); ++ if (tmp_ra_buf->buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ free(tmp_ra_buf); ++ goto end; ++ } ++ (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); ++ tmp_ra_buf->len = in_buf_len; ++ ++ *in = tmp_ra_buf; ++end: ++ cJSON_free(in_buf); ++ cJSON_Delete(in_json); ++ return ret; ++} ++ ++/* caller need to free (cc_ra_buf_t **in) */ ++cc_enclave_result_t gen_ra_report_in_buff(cc_get_ra_report_input_t *param, cc_ra_buf_t **json_buf) ++{ ++ if (param == NULL || param->taid == NULL || json_buf == NULL) { ++ return CC_ERROR_BAD_PARAMETERS; ++ } ++ cc_enclave_result_t ret = CC_SUCCESS; ++ cJSON *in_json = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_json, "handler", "report-input"); ++ ++ size_t b64_nonce_len = 0; ++ char *b64_nonce = kpsecl_base64urlencode(param->nonce, param->nonce_len, &b64_nonce_len); ++ ++ cJSON *in_payload = cJSON_CreateObject(); ++ cJSON_AddStringToObject(in_payload, "version", "TEE.RA.1.0"); ++ cJSON_AddStringToObject(in_payload, "nonce", b64_nonce); ++ free(b64_nonce); ++ cJSON_AddStringToObject(in_payload, "uuid", (char *)param->taid); ++ cJSON_AddStringToObject(in_payload, "hash_alg", "HS256"); ++ cJSON_AddBoolToObject(in_payload, "with_tcb", param->with_tcb); ++ if (param->req_key) { ++ cJSON_AddBoolToObject(in_payload, "request_key", param->req_key); ++ } ++ ++ cJSON_AddItemToObject(in_json, "payload", in_payload); ++ ++ char *in_buf = cJSON_PrintUnformatted(in_json); ++ uint32_t in_buf_len = strlen(in_buf) + 1; ++ ++ cc_ra_buf_t *tmp_ra_buf = calloc(1, sizeof(cc_ra_buf_t)); ++ if (tmp_ra_buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ goto end; ++ } ++ tmp_ra_buf->buf = calloc(1, in_buf_len); ++ if (tmp_ra_buf->buf == NULL) { ++ ret = CC_ERROR_RA_MEMORY; ++ free(tmp_ra_buf); ++ goto end; ++ } ++ (void)memcpy(tmp_ra_buf->buf, in_buf, in_buf_len); ++ tmp_ra_buf->len = in_buf_len; ++ ++ *json_buf = (cc_ra_buf_t *)tmp_ra_buf; ++end: ++ cJSON_free(in_buf); ++ cJSON_Delete(in_json); ++ return ret; ++} ++ +diff --git a/component/remote_attest/ra_report/gp_report_helper.h b/component/remote_attest/ra_report/gp_report_helper.h +new file mode 100644 +index 0000000..58786d9 +--- /dev/null ++++ b/component/remote_attest/ra_report/gp_report_helper.h +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * secGear is licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++#ifndef SECGEAR_GP_REPORT_HELPER_H ++#define SECGEAR_GP_REPORT_HELPER_H ++ ++#include "status.h" ++#include "sg_report_st.h" ++ ++cc_enclave_result_t gen_provision_no_as_in_buff(cc_ra_buf_t **in); ++cc_enclave_result_t gen_ra_report_in_buff(cc_get_ra_report_input_t *param, cc_ra_buf_t **json_buf); ++void free_cc_ra_buf(cc_ra_buf_t *ra_buf); ++ ++#endif ++ +diff --git a/component/secure_channel/client/secure_channel_client.c b/component/secure_channel/client/secure_channel_client.c +index 27b0812..21067b1 100644 +--- a/component/secure_channel/client/secure_channel_client.c ++++ b/component/secure_channel/client/secure_channel_client.c +@@ -191,10 +191,11 @@ static cc_enclave_result_t get_taid_from_file(char *file, char *taid) + } + + int ret = fscanf(fp, "%s", taid); // only read taid from line +- +- printf("read ret:%d, taid:%s\n", ret, taid); +- + fclose(fp); ++ if (ret < 0) { ++ printf("secure channel init read taid and hash from file failed\n"); ++ return CC_ERROR_SEC_CHL_INIT_GET_TAID; ++ } + + return CC_SUCCESS; + } +diff --git a/component/secure_channel/enclave/CMakeLists.txt b/component/secure_channel/enclave/CMakeLists.txt +index a84de8a..b2050fb 100644 +--- a/component/secure_channel/enclave/CMakeLists.txt ++++ b/component/secure_channel/enclave/CMakeLists.txt +@@ -14,9 +14,6 @@ set(PREFIX secure_channel) + set(SOURCE_FILES secure_channel_enclave.c ${CMAKE_CURRENT_SOURCE_DIR}/../secure_channel_common.c) + FILE (GLOB_RECURSE BASE64_SRC "${LOCAL_ROOT_PATH}/thirdparty/base64url/*.c") + +-set(PRINT_LEVEL 3) +-add_definitions(-DPRINT_LEVEL=${PRINT_LEVEL}) +- + if(CC_GP) + add_definitions(-DGP_ENCLAVE) + set(AUTO_FILES ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_t.h ${CMAKE_CURRENT_BINARY_DIR}/${PREFIX}_args.h) +diff --git a/examples/secure_channel/basevalue.txt b/examples/secure_channel/basevalue.txt +new file mode 100644 +index 0000000..694c455 +--- /dev/null ++++ b/examples/secure_channel/basevalue.txt +@@ -0,0 +1 @@ ++7763a15a-0a9e-4e86-90cd-e4262583948a 8b7373be89840534eafc2836110b31c7fee5b96ebbab09a1db87c34be393afee 52bc57fb201ebd00fcc66059084dfb38e98c0e4d11d7131d29448bc6f7cb5939 +diff --git a/examples/secure_channel/client/client.c b/examples/secure_channel/client/client.c +index 08d2574..28b3695 100644 +--- a/examples/secure_channel/client/client.c ++++ b/examples/secure_channel/client/client.c +@@ -49,6 +49,13 @@ int main(int argc, char **argv) + cc_enclave_result_t ret; + struct sockaddr_in svr_addr; + ++ char *ta_basevalue_file = "../basevalue.txt"; ++ char basevalue_real_path[PATH_MAX] = {0}; ++ if (realpath(ta_basevalue_file, basevalue_real_path) == NULL) { ++ printf("ta basevalue file path error\n"); ++ return -1; ++ } ++ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) { + printf("create socket failed\n"); +@@ -69,7 +76,7 @@ int main(int argc, char **argv) + // step1: 初始化安全通道客户端,注册消息发送函数 + g_ctx.conn_kit.send = (void *)socket_write_and_read; + g_ctx.conn_kit.conn = &sockfd; +- g_ctx.basevalue = "/vendor/bin/basevalue.txt"; // content format:taid image_hash mem_hash ++ g_ctx.basevalue = basevalue_real_path; // content format:taid image_hash mem_hash + ret = cc_sec_chl_client_init(CC_SEC_CHL_ALGO_RSA_ECDH_AES_GCM, &g_ctx); + if (ret != CC_SUCCESS) { + printf("secure channel init failed:%u\n", ret); +diff --git a/examples/secure_channel/client_with_recv_thread/client.c b/examples/secure_channel/client_with_recv_thread/client.c +index db142bb..d492624 100644 +--- a/examples/secure_channel/client_with_recv_thread/client.c ++++ b/examples/secure_channel/client_with_recv_thread/client.c +@@ -67,6 +67,13 @@ int main(int argc, char **argv) + cc_enclave_result_t ret; + struct sockaddr_in svr_addr; + ++ char *ta_basevalue_file = "../basevalue.txt"; ++ char basevalue_real_path[PATH_MAX] = {0}; ++ if (realpath(ta_basevalue_file, basevalue_real_path) == NULL) { ++ printf("ta basevalue file path error\n"); ++ return -1; ++ } ++ + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) { + printf("create socket failed\n"); +@@ -87,7 +94,7 @@ int main(int argc, char **argv) + // step1: 初始化安全通道客户端,注册消息发送函数 + g_ctx.conn_kit.send = (void *)socket_write_adpt; + g_ctx.conn_kit.conn = &sockfd; +- g_ctx.basevalue = "/vendor/bin/basevalue.txt"; // content format:taid image_hash mem_hash ++ g_ctx.basevalue = basevalue_real_path; // content format:taid image_hash mem_hash + + // step2: 创建消息接收线程 + pthread_t thread; +diff --git a/inc/host_inc/status.h b/inc/host_inc/status.h +index 56f4da4..0ecb243 100644 +--- a/inc/host_inc/status.h ++++ b/inc/host_inc/status.h +@@ -89,6 +89,8 @@ typedef enum _enclave_result_t + + CC_ERROR_REE_AGENT_NOT_INIT, + CC_ERROR_RA_VERIFY_AGENT_NOT_INIT, ++ CC_ERROR_LOCAL_REPORT_INVALID, ++ CC_ERROR_LOCAL_REPORT_HASH_MISMATCH, + /* secure channel */ + CC_ERROR_SEC_CHL_INVALID_CONN, /* invalid connection */ + CC_ERROR_SEC_CHL_LEN_NOT_ENOUGH, /* the buf length to store secure channle encrypt/decrypt is not enough */ +-- +2.33.0 + diff --git a/0065-optimize-name-ree-agent-to-ra-agent.patch b/0065-optimize-name-ree-agent-to-ra-agent.patch new file mode 100644 index 0000000000000000000000000000000000000000..c8113d876ace96883f72850846310c3377c5bd8f --- /dev/null +++ b/0065-optimize-name-ree-agent-to-ra-agent.patch @@ -0,0 +1,268 @@ +From 9ae8329b203d7d64b18958b79c8ce21ef46f8baf Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Thu, 1 Jun 2023 19:28:26 +0800 +Subject: [PATCH] optimize name ree agent to ra agent + +--- + component/local_attest/sg_local_attest.h | 14 +++++++++++++ + .../remote_attest/ra_report/gp_ra_report.c | 8 ++++---- + .../remote_attest/ra_report/sg_ra_report.c | 20 +++++++++---------- + .../remote_attest/ra_report/sg_ra_report.h | 13 +++++++++--- + .../remote_attest/ra_report/sgx_ra_report.c | 8 ++++---- + .../{uni_ree_agent.h => uni_ra_agent.h} | 8 ++++---- + .../ra_verify/sg_ra_report_verify.h | 15 +++++++++++++- + .../client/secure_channel_client.h | 3 +++ + inc/host_inc/status.h | 2 +- + 9 files changed, 64 insertions(+), 27 deletions(-) + rename component/remote_attest/ra_report/{uni_ree_agent.h => uni_ra_agent.h} (89%) + +diff --git a/component/local_attest/sg_local_attest.h b/component/local_attest/sg_local_attest.h +index 97f31ef..e615073 100644 +--- a/component/local_attest/sg_local_attest.h ++++ b/component/local_attest/sg_local_attest.h +@@ -20,6 +20,20 @@ + extern "C" { + #endif + ++/** ++* [host TEE API] get and verify local attestation report by TA ++* [NOTICE] before calling cc_local_attest, the attestation service ++* need to be initialized by cc_prepare_ra_env, otherwise get report error ++* ++* @param[in] taid, the unique ID stirng of target TA ++* ++* @param[in] img_hash, the static image measure of target TA ++* ++* @param[in] mem_hash, the static memory measure of target TA ++* ++* @retval, On success, return 0. ++* On error, cc_enclave_result_t errorno is returned. ++*/ + CC_API_SPEC cc_enclave_result_t cc_local_attest(char *taid, char *img_hash, char *mem_hash); + + #ifdef __cplusplus +diff --git a/component/remote_attest/ra_report/gp_ra_report.c b/component/remote_attest/ra_report/gp_ra_report.c +index ca1fa03..29c6a6a 100644 +--- a/component/remote_attest/ra_report/gp_ra_report.c ++++ b/component/remote_attest/ra_report/gp_ra_report.c +@@ -13,7 +13,7 @@ + #include + #include "ra_client_api.h" + #include "enclave_log.h" +-#include "uni_ree_agent.h" ++#include "uni_ra_agent.h" + #include "gp_report_helper.h" + + #define PROVISION_OUT_LEN 0x3000 +@@ -71,12 +71,12 @@ static cc_enclave_result_t gp_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_ + return CC_SUCCESS; + } + +-static uni_ree_agent_t g_gp_agent = { ++static uni_ra_agent_t g_gp_agent = { + .tee_type = CC_TEE_TYPE_GP, + .prepare_ra_env = gp_prepare_ra_env, + .get_ra_report = gp_get_ra_report, + }; +-static __attribute__((constructor)) void gp_register_ree_agent(void) ++static __attribute__((constructor)) void gp_register_ra_agent(void) + { +- cc_register_ree_agent(&g_gp_agent); ++ cc_register_ra_agent(&g_gp_agent); + } +\ No newline at end of file +diff --git a/component/remote_attest/ra_report/sg_ra_report.c b/component/remote_attest/ra_report/sg_ra_report.c +index 21ad417..20eba26 100644 +--- a/component/remote_attest/ra_report/sg_ra_report.c ++++ b/component/remote_attest/ra_report/sg_ra_report.c +@@ -10,15 +10,15 @@ + * See the Mulan PSL v2 for more details. + */ + #include "sg_ra_report.h" +-#include "uni_ree_agent.h" ++#include "uni_ra_agent.h" + +-static uni_ree_agent_t *g_ree_agent = NULL; ++static uni_ra_agent_t *g_ra_agent = NULL; + cc_enclave_result_t cc_prepare_ra_env(cc_ra_scenario_t scenario) + { +- if (g_ree_agent == NULL) { +- return CC_ERROR_REE_AGENT_NOT_INIT; ++ if (g_ra_agent == NULL) { ++ return CC_ERROR_RA_AGENT_NOT_INIT; + } +- return g_ree_agent->prepare_ra_env(scenario); ++ return g_ra_agent->prepare_ra_env(scenario); + } + + cc_enclave_result_t cc_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t *report) +@@ -26,13 +26,13 @@ cc_enclave_result_t cc_get_ra_report(cc_get_ra_report_input_t *in, cc_ra_buf_t * + if (in == NULL || in->taid == NULL || report == NULL || report->buf == NULL) { + return CC_ERROR_BAD_PARAMETERS; + } +- if (g_ree_agent == NULL) { +- return CC_ERROR_REE_AGENT_NOT_INIT; ++ if (g_ra_agent == NULL) { ++ return CC_ERROR_RA_AGENT_NOT_INIT; + } +- return g_ree_agent->get_ra_report(in, report); ++ return g_ra_agent->get_ra_report(in, report); + } + +-void cc_register_ree_agent(uni_ree_agent_t *agent) ++void cc_register_ra_agent(uni_ra_agent_t *agent) + { +- g_ree_agent = agent; ++ g_ra_agent = agent; + } +diff --git a/component/remote_attest/ra_report/sg_ra_report.h b/component/remote_attest/ra_report/sg_ra_report.h +index f3294c5..0d0d44f 100644 +--- a/component/remote_attest/ra_report/sg_ra_report.h ++++ b/component/remote_attest/ra_report/sg_ra_report.h +@@ -21,15 +21,22 @@ + #ifdef __cplusplus + extern "C" { + #endif +- ++/** ++* [host REE API] prepare attest environment before get report by attestation service ++* ++* @param[in] scenario, the scenario of attestation service ++* ++* @retval, On success, return 0. ++* On error, cc_enclave_result_t errorno is returned. ++*/ + CC_API_SPEC cc_enclave_result_t cc_prepare_ra_env(cc_ra_scenario_t scenario); + + /** +-* get remote attestation report ++* [host REE API] get remote attestation report by attestation service + * + * @param[in] in, bytes of input + * +-* @param[out] report, remote attestion report, 0x3000 =< len < 0x100000 ++* @param[in/out] report, remote attestion report, 0x3000 =< report->len < 0x100000 + * + * @retval, On success, return 0. + * On error, cc_enclave_result_t errorno is returned. +diff --git a/component/remote_attest/ra_report/sgx_ra_report.c b/component/remote_attest/ra_report/sgx_ra_report.c +index 6bd0bdc..d63474e 100644 +--- a/component/remote_attest/ra_report/sgx_ra_report.c ++++ b/component/remote_attest/ra_report/sgx_ra_report.c +@@ -9,7 +9,7 @@ + * PURPOSE. + * See the Mulan PSL v2 for more details. + */ +-#include "uni_ree_agent.h" ++#include "uni_ra_agent.h" + + static cc_enclave_result_t sgx_prepare_ra_env(cc_ra_scenario_t scenario) + { +@@ -25,12 +25,12 @@ static cc_enclave_result_t sgx_get_ra_report(cc_get_ra_report_input_t *in, cc_ra + return CC_SUCCESS; + } + +-static uni_ree_agent_t g_sgx_agent = { ++static uni_ra_agent_t g_sgx_agent = { + .tee_type = CC_TEE_TYPE_SGX, + .prepare_ra_env = sgx_prepare_ra_env, + .get_ra_report = sgx_get_ra_report, + }; +-static __attribute__((constructor)) void sgx_register_ree_agent(void) ++static __attribute__((constructor)) void sgx_register_ra_agent(void) + { +- cc_register_ree_agent(&g_sgx_agent); ++ cc_register_ra_agent(&g_sgx_agent); + } +\ No newline at end of file +diff --git a/component/remote_attest/ra_report/uni_ree_agent.h b/component/remote_attest/ra_report/uni_ra_agent.h +similarity index 89% +rename from component/remote_attest/ra_report/uni_ree_agent.h +rename to component/remote_attest/ra_report/uni_ra_agent.h +index 65a46d1..0801ab9 100644 +--- a/component/remote_attest/ra_report/uni_ree_agent.h ++++ b/component/remote_attest/ra_report/uni_ra_agent.h +@@ -10,8 +10,8 @@ + * See the Mulan PSL v2 for more details. + */ + +-#ifndef SECGEAR_UNI_REE_AGENT_H +-#define SECGEAR_UNI_REE_AGENT_H ++#ifndef SECGEAR_UNI_RA_AGENT_H ++#define SECGEAR_UNI_RA_AGENT_H + + #include + #include "status.h" +@@ -33,9 +33,9 @@ typedef struct { + cc_tee_type_t tee_type; + uni_prepare_ra_env_proc_t prepare_ra_env; + uni_get_ra_report_proc_t get_ra_report; +-} uni_ree_agent_t; ++} uni_ra_agent_t; + +-void cc_register_ree_agent(uni_ree_agent_t *agent); ++void cc_register_ra_agent(uni_ra_agent_t *agent); + + #ifdef __cplusplus + } +diff --git a/component/remote_attest/ra_verify/sg_ra_report_verify.h b/component/remote_attest/ra_verify/sg_ra_report_verify.h +index b566cef..e5da876 100644 +--- a/component/remote_attest/ra_verify/sg_ra_report_verify.h ++++ b/component/remote_attest/ra_verify/sg_ra_report_verify.h +@@ -20,7 +20,20 @@ + #ifdef __cplusplus + extern "C" { + #endif +- ++/** ++* [verifier API] verify remote attestation report by verifier ++* ++* @param[in] report, the report of target TA ++* ++* @param[in] nonce, the nonce generated when get report ++* ++* @param[in] type, the mode of verify report ++* ++* @param[in] basevalue, the basevalue file path of target TA, ++* ++* @retval, On success, return 0. ++* On error, cc_enclave_result_t errorno is returned. ++*/ + CC_API_SPEC cc_enclave_result_t cc_verify_report(cc_ra_buf_t *report, cc_ra_buf_t *nonce, + cc_ra_verify_type_t type, char *basevalue); + +diff --git a/component/secure_channel/client/secure_channel_client.h b/component/secure_channel/client/secure_channel_client.h +index e2d0b7e..2f5c13d 100644 +--- a/component/secure_channel/client/secure_channel_client.h ++++ b/component/secure_channel/client/secure_channel_client.h +@@ -55,11 +55,14 @@ typedef enum { + + /** + * secure channel init function ++* [Warning] because TA report is big, the conn_kit must have bigger read buffer ++* to carry secure channel msg(>=12320bytes). + * + * @param[in] algo, The algorithm suite of secure channel + * + * @param[in/out] ctx, The pointer of secure channel context + * input need init conn_kit; ++* input need init basevalue; the secure channel server's TA basevalue, generated by sign TA + * output session_id and cc_sec_chl_handle_t + * + * @retval, On success, return 0. generate session_key between client and enclave. +diff --git a/inc/host_inc/status.h b/inc/host_inc/status.h +index 0ecb243..7a7920b 100644 +--- a/inc/host_inc/status.h ++++ b/inc/host_inc/status.h +@@ -87,7 +87,7 @@ typedef enum _enclave_result_t + CC_ERROR_RA_REPORT_VERIFY_HASH, + CC_ERROR_RA_REPORT_VERIFY_INVALID_TYPE, + +- CC_ERROR_REE_AGENT_NOT_INIT, ++ CC_ERROR_RA_AGENT_NOT_INIT, + CC_ERROR_RA_VERIFY_AGENT_NOT_INIT, + CC_ERROR_LOCAL_REPORT_INVALID, + CC_ERROR_LOCAL_REPORT_HASH_MISMATCH, +-- +2.33.0 + diff --git a/0066-fix-error-file-name.patch b/0066-fix-error-file-name.patch new file mode 100644 index 0000000000000000000000000000000000000000..5272a72b59902ad9699faa3c68d5c3d91d8ec60d --- /dev/null +++ b/0066-fix-error-file-name.patch @@ -0,0 +1,45 @@ +From a2c0a27d8011ebb0c66c22daca17e0342d8bc5cf Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Fri, 2 Jun 2023 10:31:11 +0800 +Subject: [PATCH] fix error file name + +--- + thirdparty/cjson/{cJSON.bak => cJSON.c} | 0 + .../kunpengsecl/verifier/custom_base64url.h | 20 ------------------- + 2 files changed, 20 deletions(-) + rename thirdparty/cjson/{cJSON.bak => cJSON.c} (100%) + delete mode 100644 thirdparty/kunpengsecl/verifier/custom_base64url.h + +diff --git a/thirdparty/cjson/cJSON.bak b/thirdparty/cjson/cJSON.c +similarity index 100% +rename from thirdparty/cjson/cJSON.bak +rename to thirdparty/cjson/cJSON.c +diff --git a/thirdparty/kunpengsecl/verifier/custom_base64url.h b/thirdparty/kunpengsecl/verifier/custom_base64url.h +deleted file mode 100644 +index 1e003da..0000000 +--- a/thirdparty/kunpengsecl/verifier/custom_base64url.h ++++ /dev/null +@@ -1,20 +0,0 @@ +-/* +-kunpengsecl licensed under the Mulan PSL v2. +-You can use this software according to the terms and conditions of +-the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: +- http://license.coscl.org.cn/MulanPSL2 +-THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +-EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +-MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +-See the Mulan PSL v2 for more details. +-*/ +- +-#ifndef CUSTOM_BASE64URL_H +-#define CUSTOM_BASE64URL_H +- +-#include +- +-void base64urlencode(const uint8_t *src, int src_len, uint8_t *cipher, int *dest_len); +-uint8_t *base64urldecode(const uint8_t *src, int src_len, int *dest_len); +- +-#endif +-- +2.33.0 + diff --git a/0067-local-attest-verify-input-hash-pointer.patch b/0067-local-attest-verify-input-hash-pointer.patch new file mode 100644 index 0000000000000000000000000000000000000000..6c0ab5694f2b3ec71848baea2a6f5b7897372f14 --- /dev/null +++ b/0067-local-attest-verify-input-hash-pointer.patch @@ -0,0 +1,25 @@ +From 91394f19abb7d7f5863bbf3c44a7ef83f0616ee6 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Fri, 2 Jun 2023 15:47:33 +0800 +Subject: [PATCH] local attest verify input hash pointer + +--- + component/local_attest/sg_local_attest.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/component/local_attest/sg_local_attest.c b/component/local_attest/sg_local_attest.c +index f94473e..3e612cf 100644 +--- a/component/local_attest/sg_local_attest.c ++++ b/component/local_attest/sg_local_attest.c +@@ -14,7 +14,7 @@ + + cc_enclave_result_t cc_local_attest(char *taid, char *img_hash, char *mem_hash) + { +- if (taid == NULL || (img_hash == NULL && mem_hash == NULL)) { ++ if (taid == NULL || img_hash == NULL || mem_hash == NULL) { + return CC_ERROR_BAD_PARAMETERS; + } + +-- +2.33.0 + diff --git a/0068-bugfix-when-input-empty-hash.patch b/0068-bugfix-when-input-empty-hash.patch new file mode 100644 index 0000000000000000000000000000000000000000..8840b9ff4f1cc6ebcf71851efacdc5a7bc9830fb --- /dev/null +++ b/0068-bugfix-when-input-empty-hash.patch @@ -0,0 +1,27 @@ +From 5df0040e56c697ffc4797c798dcbafde796ff5e5 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Sat, 3 Jun 2023 16:05:25 +0800 +Subject: [PATCH] bugfix when input empty hash + +--- + component/local_attest/gp_local_attest.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/component/local_attest/gp_local_attest.c b/component/local_attest/gp_local_attest.c +index 7f75147..53dc5d9 100644 +--- a/component/local_attest/gp_local_attest.c ++++ b/component/local_attest/gp_local_attest.c +@@ -59,8 +59,8 @@ static cc_enclave_result_t gp_compare_hash(gp_basevalue_t *basevalue, char *ta_i + PrintInfo(PRINT_STRACE, "heximg:%s, hexmem:%s", heximg, hexmem); + PrintInfo(PRINT_STRACE, "img_hash:%s, mem_hash:%s", basevalue->img_hash, basevalue->mem_hash); + +- if (memcmp(heximg, basevalue->img_hash, strlen(basevalue->img_hash)) != 0 || +- memcmp(hexmem, basevalue->mem_hash, strlen(basevalue->mem_hash)) != 0) { ++ if (memcmp(heximg, basevalue->img_hash, strlen(heximg)) != 0 || ++ memcmp(hexmem, basevalue->mem_hash, strlen(hexmem)) != 0) { + PrintInfo(PRINT_ERROR, "verify local report hash failed!\n"); + return CC_ERROR_LOCAL_REPORT_HASH_MISMATCH; + } +-- +2.33.0 + diff --git a/0069-adapt-sign-tool-to-pass-API_LEVEL.patch b/0069-adapt-sign-tool-to-pass-API_LEVEL.patch new file mode 100644 index 0000000000000000000000000000000000000000..04c237e6e787f9d5b3666789ddceabfaf197f179 --- /dev/null +++ b/0069-adapt-sign-tool-to-pass-API_LEVEL.patch @@ -0,0 +1,28 @@ +From 0962d86c5a359171191c127479491217074039b7 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Tue, 6 Jun 2023 21:15:39 +0800 +Subject: [PATCH] adapt sign tool to pass API_LEVEL + +--- + tools/sign_tool/sign_tool.sh | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/sign_tool/sign_tool.sh b/tools/sign_tool/sign_tool.sh +index c567423..74e2514 100755 +--- a/tools/sign_tool/sign_tool.sh ++++ b/tools/sign_tool/sign_tool.sh +@@ -122,8 +122,10 @@ itrustee_start_sign() { + cp ${IN_ENCLAVE} ${IN_PATH}/libcombine.so + OUT_PATH=$(dirname ${OUT_FILE}) + echo ${IN_PATH} ${OUT_PATH} ++ echo "CFLAGS += -DAPI_LEVEL=${API_LEVEL}" > ${IN_PATH}/config.mk + python3 -B ${signtoolpath}/signtool_v3.py ${IN_PATH} ${OUT_PATH} --privateCfg ${A_CONFIG_FILE} +- rm -rf ${IN_PATH}/libcombine.so ++ rm -f ${IN_PATH}/config.mk ++ rm -f ${IN_PATH}/libcombine.so + else + echo "Error: illegal command" + fi +-- +2.33.0 + diff --git a/0070-sign-tool-add-invalid-param-verify.patch b/0070-sign-tool-add-invalid-param-verify.patch new file mode 100644 index 0000000000000000000000000000000000000000..00e5863fb64e58a41b68b7fc99ca849682d255ff --- /dev/null +++ b/0070-sign-tool-add-invalid-param-verify.patch @@ -0,0 +1,54 @@ +From f0cd1f169bec254162c7e7d1781aabc68879fb9c Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Thu, 8 Jun 2023 20:51:22 +0800 +Subject: [PATCH] sign tool add invalid param verify + +--- + tools/sign_tool/sign_tool.sh | 24 +++++++++++++++++++++--- + 1 file changed, 21 insertions(+), 3 deletions(-) + +diff --git a/tools/sign_tool/sign_tool.sh b/tools/sign_tool/sign_tool.sh +index 74e2514..5bf7fbb 100755 +--- a/tools/sign_tool/sign_tool.sh ++++ b/tools/sign_tool/sign_tool.sh +@@ -17,9 +17,11 @@ print_help() { + echo "-k private key required for single-step method. Note: single-step method is only for the debug mode," + echo "-k plaintext private key does exist in the production environment." + echo "-m additional config_cloud.ini for trustzone." +- echo "-o output parameter, the sign command outputs signed enclave, the digest command outputs signing" +- echo " material, the dump command outputs data containing the SIGStruct metadata for the SGX signed" +- echo " enclave, which is submitted to Intel for whitelisting." ++ echo "-o output parameter. " ++ echo " sgx: the sign command outputs signed enclave, the digest command outputs signing" ++ echo " material, the dump command outputs data containing the SIGStruct metadata for the SGX signed" ++ echo " enclave, which is submitted to Intel for whitelisting." ++ echo " trustzone: /output_path/uuid.sec, uuid must be the same as the value of gpd.ta.appID in manifest.txt" + echo "-p signing server public key certificate, required for sgx two-step method." + echo "-s the signature value required for two-step method, this parameter is empty to indicate" + echo " single-step method." +@@ -116,6 +118,22 @@ itrustee_start_sign() { + echo "Error: missing additional config_cloud.ini file for signing iTrustee enclave" + exit 1 + fi ++ if [ -z $CONFIG_FILE ]; then ++ echo "Error: missing basic config file for signing iTrustee enclave" ++ exit 1 ++ fi ++ if [ ! -e $CONFIG_FILE ]; then ++ echo "No such file or directory" ++ exit 1 ++ fi ++ if [ -z $IN_ENCLAVE ]; then ++ echo "Error: missing enclave file" ++ exit 1 ++ fi ++ if [ ! -e $IN_ENCLAVE ]; then ++ echo "Error: No such file or directory" ++ exit 1 ++ fi + + if [ "${CMD}"x == "sign"x ]; then + IN_PATH=$(dirname ${CONFIG_FILE}) +-- +2.33.0 + diff --git a/0071-adapt-report-with-request-key.patch b/0071-adapt-report-with-request-key.patch new file mode 100644 index 0000000000000000000000000000000000000000..21868974e91c809c2c0f475802446853ddac3b52 --- /dev/null +++ b/0071-adapt-report-with-request-key.patch @@ -0,0 +1,155 @@ +From a6064d550da8a0b204249d16692708cc3ed14832 Mon Sep 17 00:00:00 2001 +From: houmingyong +Date: Tue, 20 Jun 2023 19:19:39 +0800 +Subject: [PATCH] adapt report with request key + +--- + .../client/secure_channel_client.c | 70 ++++--------------- + .../secure_channel/host/secure_channel_host.c | 12 ---- + 2 files changed, 15 insertions(+), 67 deletions(-) + +diff --git a/component/secure_channel/client/secure_channel_client.c b/component/secure_channel/client/secure_channel_client.c +index 21067b1..6a45a1d 100644 +--- a/component/secure_channel/client/secure_channel_client.c ++++ b/component/secure_channel/client/secure_channel_client.c +@@ -243,53 +243,6 @@ static cc_enclave_result_t request_report(cc_sec_chl_ctx_t *ctx, sec_chl_msg_typ + return CC_SUCCESS; + } + +-static cc_enclave_result_t get_ra_report(cc_sec_chl_ctx_t *ctx) +-{ +- return request_report(ctx, SEC_CHL_MSG_GET_RA_REPORT, false); +-} +- +-static cc_enclave_result_t verify_report(cc_sec_chl_ctx_t *ctx, sec_chl_msg_t *msg) +-{ +- cc_enclave_result_t ret = CC_SUCCESS; +- if (msg->sub_type == GET_SVRPUBKEY_SUBTYPE_REPORT) { +- cc_ra_buf_t report = {0}; +- report.buf = msg->data; +- report.len = msg->data_len; +- cc_ra_buf_t nonce = {0}; +- nonce.len = SEC_CHL_REQ_NONCE_LEN; +- nonce.buf = ctx->handle->ra_req.nonce; +- ret = cc_verify_report(&report, &nonce, CC_RA_VERIFY_TYPE_STRICT, ctx->basevalue); +- if (ret != CC_SUCCESS) { +- printf("verify report failed ret:%u\n", ret); +- return CC_ERROR_SEC_CHL_INIT_VERIFY_REPORT; +- } +- } +- return ret; +-} +- +-static cc_enclave_result_t recv_ra_report(cc_sec_chl_ctx_t *ctx) +-{ +- sec_chl_msg_t *msg = NULL; +- +- pthread_mutex_lock(&ctx->handle->lock); +- if (ctx->handle->recv_buf_len == 0) { +- pthread_mutex_unlock(&ctx->handle->lock); +- return CC_ERROR_SEC_CHL_WAITING_RECV_MSG; +- } +- msg = (sec_chl_msg_t *)ctx->handle->recv_buf; +- cc_enclave_result_t ret = verify_report(ctx, msg); +- if (ret != CC_SUCCESS) { +- pthread_mutex_unlock(&ctx->handle->lock); +- return ret; +- } +- +- ctx->session_id = msg->session_id; +- ctx->handle->recv_buf_len = 0; +- pthread_mutex_unlock(&ctx->handle->lock); +- +- return CC_SUCCESS; +-} +- + static cc_enclave_result_t get_svr_pubkey(cc_sec_chl_ctx_t *ctx) + { + return request_report(ctx, SEC_CHL_MSG_GET_SVR_PUBKEY, true); +@@ -311,14 +264,14 @@ static cc_enclave_result_t get_svr_key_from_report(cc_sec_chl_ctx_t *ctx, cc_ra_ + printf("report payload failed!\n"); + goto end; + } +- cJSON *cj_nonce = cJSON_GetObjectItemCaseSensitive(cj_payload, "nonce"); +- if(cj_nonce == NULL) { +- printf("report nonce failed!\n"); ++ cJSON *cj_key = cJSON_GetObjectItemCaseSensitive(cj_payload, "key"); ++ if (cj_key == NULL) { ++ printf("report key failed!\n"); + goto end; + } + // comput pubkey +- cJSON *cj_pub_key = cJSON_GetObjectItemCaseSensitive(cj_nonce, "pub_key"); +- if(cj_pub_key == NULL) { ++ cJSON *cj_pub_key = cJSON_GetObjectItemCaseSensitive(cj_key, "pub_key"); ++ if (cj_pub_key == NULL) { + printf("report pub_key failed!\n"); + goto end; + } +@@ -347,7 +300,7 @@ static cc_enclave_result_t get_svr_key_from_report(cc_sec_chl_ctx_t *ctx, cc_ra_ + ctx->handle->rsa_svr_pubkey = svr_pub_key; + + // save enc key to ctx +- cJSON *cj_enc_key = cJSON_GetObjectItemCaseSensitive(cj_nonce, "enc_key"); ++ cJSON *cj_enc_key = cJSON_GetObjectItemCaseSensitive(cj_key, "enc_key"); + if(cj_enc_key == NULL) { + printf("report enc_key failed!\n"); + goto fail; +@@ -410,6 +363,15 @@ static cc_enclave_result_t parse_svrpubkey_from_recv_msg(cc_sec_chl_ctx_t *ctx, + cc_ra_buf_t report = {0}; + report.buf = msg->data; + report.len = msg->data_len; ++ cc_ra_buf_t nonce = {0}; ++ nonce.len = SEC_CHL_REQ_NONCE_LEN; ++ nonce.buf = ctx->handle->ra_req.nonce; ++ ++ ret = cc_verify_report(&report, &nonce, CC_RA_VERIFY_TYPE_STRICT, ctx->basevalue); ++ if (ret != CC_SUCCESS) { ++ printf("verify report failed ret:%u\n", ret); ++ return CC_ERROR_SEC_CHL_INIT_VERIFY_REPORT; ++ } + + ret = get_svr_key_from_report(ctx, &report); + if (ret != CC_SUCCESS) { +@@ -635,8 +597,6 @@ static cc_enclave_result_t sec_chl_compute_session_key(cc_sec_chl_ctx_t *ctx) + } + + static sec_chl_fsm_state_transform_t g_state_transform_table[] = { +- {get_ra_report}, +- {recv_ra_report}, + {get_svr_pubkey}, + {recv_svr_pubkey}, + {set_encrypt_key_to_server_ta}, +diff --git a/component/secure_channel/host/secure_channel_host.c b/component/secure_channel/host/secure_channel_host.c +index e7adf3c..9ef160c 100644 +--- a/component/secure_channel/host/secure_channel_host.c ++++ b/component/secure_channel/host/secure_channel_host.c +@@ -96,15 +96,6 @@ static int sec_chl_get_ra_report(cc_enclave_t *context, sec_chl_msg_t *msg, + return CC_SUCCESS; + } + +-static int sec_chl_get_ra_report_ex(cc_enclave_t *context, sec_chl_msg_t *msg, +- sec_chl_msg_t **rsp_msg, size_t *rsp_msg_len) +-{ +- if (is_support_remote_attest(context)) { +- return sec_chl_get_ra_report(context, msg, rsp_msg, rsp_msg_len); +- } +- return CC_SUCCESS; +-} +- + static int sec_chl_get_pubkey(cc_enclave_t *context, sec_chl_msg_t *msg, sec_chl_msg_t **rsp_msg, size_t *rsp_msg_len) + { + if (is_support_remote_attest(context)) { +@@ -423,9 +414,6 @@ static cc_enclave_result_t handle_recv_msg(cc_enclave_t *context, sec_chl_msg_t + { + cc_enclave_result_t ret = CC_FAIL; + switch (msg->msg_type) { +- case SEC_CHL_MSG_GET_RA_REPORT: +- ret = sec_chl_get_ra_report_ex(context, msg, rsp_msg, rsp_msg_len); +- break; + case SEC_CHL_MSG_GET_SVR_PUBKEY: + ret = sec_chl_get_pubkey(context, msg, rsp_msg, rsp_msg_len); + break; +-- +2.33.0 + diff --git a/secGear.spec b/secGear.spec index 2f3e3c418d0da7d2c5b874a3154e9b342edbb398..5734aefdaa3e3c6960df193d95d116cf8939a514 100644 --- a/secGear.spec +++ b/secGear.spec @@ -1,6 +1,6 @@ Name: secGear Version: 0.1.0 -Release: 34 +Release: 35 Summary: secGear is an SDK to develop confidential computing apps based on hardware enclave features @@ -54,20 +54,32 @@ Patch41: 0042-destroy-rwlock-when-create-enclave-failed.patch Patch42: 0043-fix-partial-resource-leak.patch Patch43: 0044-fix-pointer-without-init-or-check-NULL.patch Patch44: 0045-optimize-the-private-key-usage-of-the-single-step-si.patch -Patch45: 0046-fix-return-value.patch -Patch46: 0047-del-print-uncontrol-form-string.patch +Patch45: 0046-fix-return-value.patch +Patch46: 0047-del-print-uncontrol-form-string.patch Patch47: 0048-Delete-the-null-determination-of-out_buf-in-codegene.patch -Patch48: 0049-support-switchless-feature.patch -Patch49: 0050-switchless-schedule-policy.patch -Patch50: 0051-asynchronous-switchless.patch -Patch51: 0052-rollback-to-common-invoking-when-async-invoking-fail.patch -Patch52: 0053-asynchronous-switchless-example.patch -Patch53: 0054-fix-gen-ecall-header-error.patch -Patch54: 0055-switchless-readme-add-async-interface.patch -Patch55: 0056-destroy-enclave-release-remain-shared-memory.patch -Patch56: 0057-new-feature-secure-channel-support.patch -Patch57: 0058-refactor-cmake-SDK_PATH.patch -Patch58: 0059-adapt-itrustee_sdk-openssl-path-modification.patch +Patch48: 0049-support-switchless-feature.patch +Patch49: 0050-switchless-schedule-policy.patch +Patch50: 0051-asynchronous-switchless.patch +Patch51: 0052-rollback-to-common-invoking-when-async-invoking-fail.patch +Patch52: 0053-asynchronous-switchless-example.patch +Patch53: 0054-fix-gen-ecall-header-error.patch +Patch54: 0055-switchless-readme-add-async-interface.patch +Patch55: 0056-destroy-enclave-release-remain-shared-memory.patch +Patch56: 0057-new-feature-secure-channel-support.patch +Patch57: 0058-refactor-cmake-SDK_PATH.patch +Patch58: 0059-adapt-itrustee_sdk-openssl-path-modification.patch +Patch59: 0060-supprot-kunpeng-remote-attestation.patch +Patch60: 0061-refactor-remote-attestation.patch +Patch61: 0062-secure-channel-support-authentication-by-remote-atte.patch +Patch62: 0063-some-code-optimize.patch +Patch63: 0064-support-local-attest.patch +Patch64: 0065-optimize-name-ree-agent-to-ra-agent.patch +Patch65: 0066-fix-error-file-name.patch +Patch66: 0067-local-attest-verify-input-hash-pointer.patch +Patch67: 0068-bugfix-when-input-empty-hash.patch +Patch68: 0069-adapt-sign-tool-to-pass-API_LEVEL.patch +Patch69: 0070-sign-tool-add-invalid-param-verify.patch +Patch70: 0071-adapt-report-with-request-key.patch BuildRequires: gcc python automake autoconf libtool BUildRequires: glibc glibc-devel cmake ocaml-dune rpm gcc-c++ openssl-libs openssl-devel @@ -129,8 +141,6 @@ install -d %{buildroot}/%{_includedir}/secGear install -d %{buildroot}/%{_bindir} install -pm 751 bin/codegen %{buildroot}/%{_bindir} install -pm 751 tools/sign_tool/sign_tool.sh %{buildroot}/%{_bindir} -install -d %{buildroot}/lib/secGear/ -install -pm 751 tools/sign_tool/*.py %{buildroot}/lib/secGear install -pm 644 component/secure_channel/*.h %{buildroot}/%{_includedir}/secGear install -pm 644 component/secure_channel/*.edl %{buildroot}/%{_includedir}/secGear install -pm 644 component/secure_channel/client/*.h %{buildroot}/%{_includedir}/secGear @@ -151,6 +161,11 @@ install -pm 644 inc/enclave_inc/*.h %{buildroot}/%{_includedir}/secGear install -pm 644 inc/enclave_inc/gp/*.h %{buildroot}/%{_includedir}/secGear install -pm 644 inc/enclave_inc/gp/itrustee/*.h %{buildroot}/%{_includedir}/secGear %endif +install -pm 644 component/remote_attest/ra_report/sg_ra_report.h %{buildroot}/%{_includedir}/secGear +install -pm 644 component/remote_attest/ra_verify/sg_ra_report_verify.h %{buildroot}/%{_includedir}/secGear +install -pm 644 component/remote_attest/sg_report_st.h %{buildroot}/%{_includedir}/secGear +install -pm 644 component/local_attest/sg_local_attest.h %{buildroot}/%{_includedir}/secGear + pushd %{buildroot} rm `find . -name secgear_helloworld` -rf rm `find . -name secgear_seal_data` -rf @@ -169,6 +184,9 @@ popd %{_libdir}/libusecure_channel.so %{_libdir}/libcsecure_channel.so %{_libdir}/libtsecure_channel.a +%{_libdir}/libsecgear_verify.so +%{_libdir}/libsecgear_ra.so +%{_libdir}/libsecgear_la.a %ifarch x86_64 %{_libdir}/libsgx_0.so %else @@ -180,7 +198,6 @@ popd %files devel %{_bindir}/* %{_includedir}/secGear/* -/lib/secGear/* %ifarch x86_64 %files sim @@ -194,6 +211,9 @@ popd systemctl restart rsyslog %changelog +* Wed Sep 13 2023 wangqingsan - 0.1.0-35 +- synchronous features + * Thu Apr 27 2023 houmingyong - 0.1.0-34 - DESC:backport some patchs