From 4d68cb7b76de62b88aa88f59eb2e086dbc46788b Mon Sep 17 00:00:00 2001 From: Bruno Vavala Date: Fri, 18 Oct 2024 23:38:11 +0000 Subject: [PATCH 1/2] add attestation api to pdo build Signed-off-by: Bruno Vavala --- .gitmodules | 6 + build/__tools__/build.sh | 2 +- common/crypto/CMakeLists.txt | 3 + common/crypto/attestation-api/.gitignore | 2 + common/crypto/attestation-api/CMakeLists.txt | 220 +++++++++++++ .../crypto/attestation-api/CMakeVariables.txt | 7 + common/crypto/attestation-api/LICENSE | 201 +++++++++++ common/crypto/attestation-api/Makefile | 23 ++ common/crypto/attestation-api/README.md | 91 +++++ .../attestation/attestation.cpp | 171 ++++++++++ .../attestation-api/attestation/dcap.cpp | 136 ++++++++ .../crypto/attestation-api/attestation/dcap.h | 12 + .../attestation-api/attestation/epid.cpp | 167 ++++++++++ .../crypto/attestation-api/attestation/epid.h | 22 ++ .../crypto/attestation-api/common/.gitignore | 2 + .../attestation-api/common/CMakeLists.txt | 22 ++ common/crypto/attestation-api/common/Makefile | 15 + .../common/_nologging/CMakeLists.txt | 9 + .../common/_nologging/README.md | 4 + .../common/_nologging/ocalls/logging.edl | 7 + .../common/_nologging/trusted/logging.h | 17 + .../common/_nologging/untrusted/logging.h | 18 + .../common/_yeslogging/CMakeLists.txt | 47 +++ .../common/_yeslogging/CMakeVariables.txt | 29 ++ .../common/_yeslogging/Makefile | 22 ++ .../common/_yeslogging/include/log-defines.h | 85 +++++ .../common/_yeslogging/ocalls/logging.c | 17 + .../common/_yeslogging/ocalls/logging.edl | 12 + .../common/_yeslogging/test/CMakeLists.txt | 29 ++ .../_yeslogging/test/untrusted/test.cpp | 38 +++ .../common/_yeslogging/trusted/logging.c | 40 +++ .../common/_yeslogging/trusted/logging.h | 25 ++ .../common/_yeslogging/untrusted/logging.c | 51 +++ .../common/_yeslogging/untrusted/logging.h | 49 +++ .../attestation-api/common/base64/base64.cpp | 122 +++++++ .../attestation-api/common/base64/base64.h | 14 + .../attestation-api/common/crypto/sha256.cpp | 22 ++ .../attestation-api/common/crypto/sha256.h | 8 + .../crypto/verify_dcap_direct/CMakeLists.txt | 41 +++ .../get_dcap_certificate.cpp | 14 + .../verify_dcap_direct/get_dcap_certificate.h | 7 + .../crypto/verify_ias_report/.gitignore | 1 + .../crypto/verify_ias_report/CMakeLists.txt | 39 +++ .../verify_ias_report/verify-report.cpp | 311 ++++++++++++++++++ .../crypto/verify_ias_report/verify-report.h | 70 ++++ .../crypto/verify_ita_token/CMakeLists.txt | 46 +++ .../crypto/verify_ita_token/verify-token.cpp | 112 +++++++ .../crypto/verify_ita_token/verify-token.h | 16 + common/crypto/attestation-api/common/error.h | 46 +++ common/crypto/attestation-api/common/jwt-cpp | 1 + .../attestation-api/common/jwt-cpp.patch | 224 +++++++++++++ common/crypto/attestation-api/common/logging | 1 + .../attestation-api/common/nlohmann/json | 1 + .../common/scripts/common_utils.sh | 85 +++++ .../common/sgx-support/clocale | 59 ++++ .../common/types/hex_string.cpp | 156 +++++++++ .../attestation-api/common/types/hex_string.h | 50 +++ .../attestation-api/common/types/types.cpp | 85 +++++ .../attestation-api/common/types/types.h | 76 +++++ .../conversion/attestation_to_evidence.sh | 98 ++++++ .../conversion/dcap-direct/a2e.sh | 25 ++ .../b64attestation2b64collateral.cpp | 86 +++++ .../attestation-api/conversion/dcap/a2e.sh | 53 +++ .../conversion/define_to_variable.sh | 18 + .../conversion/enclave_to_mrenclave.sh | 29 ++ .../attestation-api/conversion/epid/a2e.sh | 59 ++++ .../conversion/simulated/a2e.sh | 16 + .../conversion/tag_to_variable.sh | 27 ++ .../crypto/attestation-api/docker/Dockerfile | 146 ++++++++ common/crypto/attestation-api/docker/Makefile | 9 + .../evidence/verify-dcap-direct-evidence.cpp | 268 +++++++++++++++ .../evidence/verify-dcap-direct-evidence.h | 7 + .../evidence/verify-dcap-evidence.cpp | 104 ++++++ .../evidence/verify-dcap-evidence.h | 7 + .../evidence/verify-evidence.cpp | 88 +++++ .../evidence/verify-ias-evidence.cpp | 240 ++++++++++++++ .../evidence/verify-ias-evidence.h | 7 + .../attestation-api/include/attestation.h | 17 + .../include/attestation_tags.h | 34 ++ .../attestation-api/include/verify-evidence.h | 24 ++ .../ocalls/attestation-ocalls.c | 99 ++++++ .../ocalls/attestation-ocalls.edl | 25 ++ .../attestation-api/test/CMakeLists.txt | 150 +++++++++ .../test/attested_evidence_test.sh | 293 +++++++++++++++++ .../test/common/test-defines.h | 17 + .../test/common/test-utils.cpp | 55 ++++ .../attestation-api/test/common/test-utils.h | 12 + .../test/conversion_app_go/main.go | 74 +++++ .../test/get_attestation_app/app/main.cpp | 64 ++++ .../enclave/CMakeLists.txt | 74 +++++ .../enclave/CMakeVariables.txt | 100 ++++++ .../test/get_attestation_app/enclave/test.cpp | 27 ++ .../test/get_attestation_app/enclave/test.h | 15 + .../enclave/test_enclave.config.xml | 18 + .../enclave/test_enclave.edl | 21 ++ .../enclave/test_enclave.lds | 15 + .../enclave/CMakeLists.txt | 78 +++++ .../enclave/CMakeVariables.txt | 99 ++++++ .../test/verify_evidence_app/enclave/test.cpp | 27 ++ .../enclave/test_verify_enclave.config.xml | 18 + .../enclave/test_verify_enclave.edl | 20 ++ .../enclave/test_verify_enclave.lds | 15 + .../test/verify_evidence_app/main.cpp | 19 ++ .../test/verify_evidence_app/test-enclave.cpp | 112 +++++++ .../test/verify_evidence_app/test.cpp | 80 +++++ .../test/verify_evidence_app/test.h | 9 + .../test/verify_evidence_app_go/main.go | 70 ++++ docker/pdo_services_base.dockerfile | 57 +++- 108 files changed, 6229 insertions(+), 4 deletions(-) create mode 100644 common/crypto/attestation-api/.gitignore create mode 100644 common/crypto/attestation-api/CMakeLists.txt create mode 100644 common/crypto/attestation-api/CMakeVariables.txt create mode 100644 common/crypto/attestation-api/LICENSE create mode 100644 common/crypto/attestation-api/Makefile create mode 100644 common/crypto/attestation-api/README.md create mode 100644 common/crypto/attestation-api/attestation/attestation.cpp create mode 100644 common/crypto/attestation-api/attestation/dcap.cpp create mode 100644 common/crypto/attestation-api/attestation/dcap.h create mode 100644 common/crypto/attestation-api/attestation/epid.cpp create mode 100644 common/crypto/attestation-api/attestation/epid.h create mode 100644 common/crypto/attestation-api/common/.gitignore create mode 100644 common/crypto/attestation-api/common/CMakeLists.txt create mode 100644 common/crypto/attestation-api/common/Makefile create mode 100644 common/crypto/attestation-api/common/_nologging/CMakeLists.txt create mode 100644 common/crypto/attestation-api/common/_nologging/README.md create mode 100644 common/crypto/attestation-api/common/_nologging/ocalls/logging.edl create mode 100644 common/crypto/attestation-api/common/_nologging/trusted/logging.h create mode 100644 common/crypto/attestation-api/common/_nologging/untrusted/logging.h create mode 100644 common/crypto/attestation-api/common/_yeslogging/CMakeLists.txt create mode 100644 common/crypto/attestation-api/common/_yeslogging/CMakeVariables.txt create mode 100644 common/crypto/attestation-api/common/_yeslogging/Makefile create mode 100644 common/crypto/attestation-api/common/_yeslogging/include/log-defines.h create mode 100644 common/crypto/attestation-api/common/_yeslogging/ocalls/logging.c create mode 100644 common/crypto/attestation-api/common/_yeslogging/ocalls/logging.edl create mode 100644 common/crypto/attestation-api/common/_yeslogging/test/CMakeLists.txt create mode 100644 common/crypto/attestation-api/common/_yeslogging/test/untrusted/test.cpp create mode 100644 common/crypto/attestation-api/common/_yeslogging/trusted/logging.c create mode 100644 common/crypto/attestation-api/common/_yeslogging/trusted/logging.h create mode 100644 common/crypto/attestation-api/common/_yeslogging/untrusted/logging.c create mode 100644 common/crypto/attestation-api/common/_yeslogging/untrusted/logging.h create mode 100644 common/crypto/attestation-api/common/base64/base64.cpp create mode 100644 common/crypto/attestation-api/common/base64/base64.h create mode 100644 common/crypto/attestation-api/common/crypto/sha256.cpp create mode 100644 common/crypto/attestation-api/common/crypto/sha256.h create mode 100644 common/crypto/attestation-api/common/crypto/verify_dcap_direct/CMakeLists.txt create mode 100644 common/crypto/attestation-api/common/crypto/verify_dcap_direct/get_dcap_certificate.cpp create mode 100644 common/crypto/attestation-api/common/crypto/verify_dcap_direct/get_dcap_certificate.h create mode 100644 common/crypto/attestation-api/common/crypto/verify_ias_report/.gitignore create mode 100644 common/crypto/attestation-api/common/crypto/verify_ias_report/CMakeLists.txt create mode 100644 common/crypto/attestation-api/common/crypto/verify_ias_report/verify-report.cpp create mode 100644 common/crypto/attestation-api/common/crypto/verify_ias_report/verify-report.h create mode 100644 common/crypto/attestation-api/common/crypto/verify_ita_token/CMakeLists.txt create mode 100644 common/crypto/attestation-api/common/crypto/verify_ita_token/verify-token.cpp create mode 100644 common/crypto/attestation-api/common/crypto/verify_ita_token/verify-token.h create mode 100644 common/crypto/attestation-api/common/error.h create mode 160000 common/crypto/attestation-api/common/jwt-cpp create mode 100644 common/crypto/attestation-api/common/jwt-cpp.patch create mode 120000 common/crypto/attestation-api/common/logging create mode 160000 common/crypto/attestation-api/common/nlohmann/json create mode 100644 common/crypto/attestation-api/common/scripts/common_utils.sh create mode 100644 common/crypto/attestation-api/common/sgx-support/clocale create mode 100644 common/crypto/attestation-api/common/types/hex_string.cpp create mode 100644 common/crypto/attestation-api/common/types/hex_string.h create mode 100644 common/crypto/attestation-api/common/types/types.cpp create mode 100644 common/crypto/attestation-api/common/types/types.h create mode 100755 common/crypto/attestation-api/conversion/attestation_to_evidence.sh create mode 100644 common/crypto/attestation-api/conversion/dcap-direct/a2e.sh create mode 100644 common/crypto/attestation-api/conversion/dcap-direct/b64attestation2b64collateral.cpp create mode 100755 common/crypto/attestation-api/conversion/dcap/a2e.sh create mode 100755 common/crypto/attestation-api/conversion/define_to_variable.sh create mode 100755 common/crypto/attestation-api/conversion/enclave_to_mrenclave.sh create mode 100755 common/crypto/attestation-api/conversion/epid/a2e.sh create mode 100755 common/crypto/attestation-api/conversion/simulated/a2e.sh create mode 100644 common/crypto/attestation-api/conversion/tag_to_variable.sh create mode 100644 common/crypto/attestation-api/docker/Dockerfile create mode 100644 common/crypto/attestation-api/docker/Makefile create mode 100644 common/crypto/attestation-api/evidence/verify-dcap-direct-evidence.cpp create mode 100644 common/crypto/attestation-api/evidence/verify-dcap-direct-evidence.h create mode 100644 common/crypto/attestation-api/evidence/verify-dcap-evidence.cpp create mode 100644 common/crypto/attestation-api/evidence/verify-dcap-evidence.h create mode 100644 common/crypto/attestation-api/evidence/verify-evidence.cpp create mode 100644 common/crypto/attestation-api/evidence/verify-ias-evidence.cpp create mode 100644 common/crypto/attestation-api/evidence/verify-ias-evidence.h create mode 100644 common/crypto/attestation-api/include/attestation.h create mode 100644 common/crypto/attestation-api/include/attestation_tags.h create mode 100644 common/crypto/attestation-api/include/verify-evidence.h create mode 100644 common/crypto/attestation-api/ocalls/attestation-ocalls.c create mode 100644 common/crypto/attestation-api/ocalls/attestation-ocalls.edl create mode 100644 common/crypto/attestation-api/test/CMakeLists.txt create mode 100755 common/crypto/attestation-api/test/attested_evidence_test.sh create mode 100644 common/crypto/attestation-api/test/common/test-defines.h create mode 100644 common/crypto/attestation-api/test/common/test-utils.cpp create mode 100644 common/crypto/attestation-api/test/common/test-utils.h create mode 100644 common/crypto/attestation-api/test/conversion_app_go/main.go create mode 100644 common/crypto/attestation-api/test/get_attestation_app/app/main.cpp create mode 100644 common/crypto/attestation-api/test/get_attestation_app/enclave/CMakeLists.txt create mode 100644 common/crypto/attestation-api/test/get_attestation_app/enclave/CMakeVariables.txt create mode 100644 common/crypto/attestation-api/test/get_attestation_app/enclave/test.cpp create mode 100644 common/crypto/attestation-api/test/get_attestation_app/enclave/test.h create mode 100644 common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.config.xml create mode 100644 common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.edl create mode 100644 common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.lds create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/enclave/CMakeLists.txt create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/enclave/CMakeVariables.txt create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/enclave/test.cpp create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.config.xml create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.edl create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.lds create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/main.cpp create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/test-enclave.cpp create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/test.cpp create mode 100644 common/crypto/attestation-api/test/verify_evidence_app/test.h create mode 100644 common/crypto/attestation-api/test/verify_evidence_app_go/main.go diff --git a/.gitmodules b/.gitmodules index 74568ac7..922e8b3d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "interpreters/wasm-micro-runtime"] path = interpreters/wasm-micro-runtime url = https://github.com/bytecodealliance/wasm-micro-runtime.git +[submodule "common/crypto/attestation-api/common/jwt-cpp"] + path = common/crypto/attestation-api/common/jwt-cpp + url = https://github.com/Thalhammer/jwt-cpp +[submodule "common/crypto/attestation-api/common/nlohmann/json"] + path = common/crypto/attestation-api/common/nlohmann/json + url = https://github.com/nlohmann/json.git diff --git a/build/__tools__/build.sh b/build/__tools__/build.sh index 72dea721..4dc69490 100755 --- a/build/__tools__/build.sh +++ b/build/__tools__/build.sh @@ -91,7 +91,7 @@ fi cd build #try cmake ${CMAKE_ARGS} .. #try make ${MAKE_ARGS} -try cmake --build . -- ${MAKE_ARGS} +try cmake --build . -- ${MAKE_ARGS} -j1 yell --------------- BIN --------------- cd $SRCDIR/bin diff --git a/common/crypto/CMakeLists.txt b/common/crypto/CMakeLists.txt index 8960fb84..c26201f4 100644 --- a/common/crypto/CMakeLists.txt +++ b/common/crypto/CMakeLists.txt @@ -39,6 +39,9 @@ ENDIF() # by the client (ias verification requires sgx). ################################################################################ IF (BUILD_TRUSTED OR BUILD_UNTRUSTED) + # Build attestation library + ADD_SUBDIRECTORY (attestation-api) + SET(PROJECT_GENERATED_IAS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/verify_ias_report/ias-certificates.txt) SET_SOURCE_FILES_PROPERTIES(${PROJECT_GENERATED_IAS_SOURCES} PROPERTIES GENERATED TRUE) SET(FETCH_IAS_CERTS ${CMAKE_CURRENT_SOURCE_DIR}/verify_ias_report/fetch_ias_certificates.sh) diff --git a/common/crypto/attestation-api/.gitignore b/common/crypto/attestation-api/.gitignore new file mode 100644 index 00000000..9ef96044 --- /dev/null +++ b/common/crypto/attestation-api/.gitignore @@ -0,0 +1,2 @@ +build + diff --git a/common/crypto/attestation-api/CMakeLists.txt b/common/crypto/attestation-api/CMakeLists.txt new file mode 100644 index 00000000..5044cfe6 --- /dev/null +++ b/common/crypto/attestation-api/CMakeLists.txt @@ -0,0 +1,220 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13) + +PROJECT(ATTESTATION-API) + +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +INCLUDE(CMakeVariables.txt) + +# get the tag of the dcap primitives (necessary to manage library links) +EXECUTE_PROCESS(COMMAND bash -c "cd $ENV{DCAP_PRIMITIVES} && git describe --tags" OUTPUT_VARIABLE DCAP_PRIMITIVES_TAG) +STRING(STRIP ${DCAP_PRIMITIVES_TAG} DCAP_PRIMITIVES_TAG) + +################################################################################################### +# First run cmake in common +################################################################################################### +# This patches the jwt repo for sgx use +ADD_SUBDIRECTORY(common) + +################################################################################################### +# Set up trusted certificates in headers +################################################################################################### + +# This creates the necessary headers which include the trusted certificates +# and returns sets CERTIFICATE_INCLUDE_PATH to find them +ADD_SUBDIRECTORY(common/crypto/verify_ias_report) +LIST(APPEND CERTIFICATE_INCLUDE_PATHS "${CERTIFICATE_INCLUDE_PATH}") + +ADD_SUBDIRECTORY(common/crypto/verify_ita_token) +LIST(APPEND CERTIFICATE_INCLUDE_PATHS "${CERTIFICATE_INCLUDE_PATH}") + +ADD_SUBDIRECTORY(common/crypto/verify_dcap_direct) +LIST(APPEND CERTIFICATE_INCLUDE_PATHS "${CERTIFICATE_INCLUDE_PATH}") + +################################################################################################### +# Logging +################################################################################################### + +# Prepare the logging libs. +# Note: by default, no trusted logging and untrusted logging is printf. +# This returns the variables: LOGGING_UNTRUSTED_INCLUDE_PATH, LOGGING_TRUSTED_INCLUDE_PATH +ADD_SUBDIRECTORY(common/logging) + +################################################################################################### +# Project files and headers +################################################################################################### + +FILE(GLOB PROJECT_HEADERS + "include/*.h" + "${CERTIFICATE_INCLUDE_PATH}/*.h" + ) + +FILE(GLOB PROJECT_SOURCES + "evidence/*.cpp" + "common/base64/base64.cpp" + "common/types/*.cpp" + "common/crypto/*.cpp" + "common/crypto/verify_ias_report/*.cpp" + "common/crypto/verify_ita_token/*.cpp" + "common/crypto/verify_dcap_direct/*.cpp" + ) + +FILE(GLOB PROJECT_OCALLS + "ocalls/*.c" + ) + +FILE(GLOB PROJECT_TRUSTED_SOURCES + "attestation/*.cpp" + $ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src/*.cpp + $ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src/OpensslHelpers/*.cpp + $ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src/PckParser/*.cpp + $ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src/CertVerification/*.cpp + $ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src/QuoteVerification/*.cpp + $ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src/Verifiers/*.cpp + $ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src/Verifiers/Checks/*.cpp + $ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src/Utils/*.cpp + $ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/include/SgxEcdsaAttestation/*.h + ) + +SET(DCAP_QG_PATH "$ENV{DCAP_PRIMITIVES}/QuoteGeneration") +SET(DCAP_QV_PATH "$ENV{DCAP_PRIMITIVES}/QuoteVerification") + +################################################################################################### +# Tools +################################################################################################### +SET(B64ATTESTATION_TO_B64COLLATERAL "b64attestation_to_b64collateral") +ADD_EXECUTABLE(${B64ATTESTATION_TO_B64COLLATERAL} + conversion/dcap-direct/b64attestation2b64collateral.cpp + common/base64/base64.cpp) +ADD_CUSTOM_COMMAND(TARGET ${B64ATTESTATION_TO_B64COLLATERAL} + POST_BUILD + COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/conversion/dcap-direct/ && + mv $ ${CMAKE_CURRENT_BINARY_DIR}/conversion/dcap-direct/) + +TARGET_INCLUDE_DIRECTORIES(${B64ATTESTATION_TO_B64COLLATERAL} PRIVATE common) + +IF("${DCAP_PRIMITIVES_TAG}" STREQUAL "DCAP_1.22") + SET(DCAP_LINK_LIBS ${DCAP_QV_PATH}/appraisal/qal/libdcap_qal.a) +ENDIF() + +TARGET_LINK_LIBRARIES(${B64ATTESTATION_TO_B64COLLATERAL} + #${DCAP_QV_PATH}/dcap_quoteverify/linux/libsgx_dcap_quoteverify.a + #${DCAP_QG_PATH}/build/linux/libdcap_quoteprov.a + #${DCAP_QG_PATH}/build/linux/libsgx_default_qcnl_wrapper.a + #sgx_dcap_quoteverify dcap_quoteprov sgx_default_qcnl_wrapper + sgx_dcap_quoteverify + # sgx_dcap_ql dcap_quoteprov necessary for the callbacks + sgx_dcap_ql + dcap_quoteprov + ) + +################################################################################################### +# Untrusted one-attestation library +################################################################################################### + +SET(U_OA_LIB_STATIC ${U_ONE_ATTESTATION_LIB_NAME}_Static) + +ADD_LIBRARY(${U_OA_LIB_STATIC} STATIC ${PROJECT_HEADERS} ${PROJECT_SOURCES} ${PROJECT_OCALLS}) + +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE "$ENV{SGX_SDK}/include") +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE "include") +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} BEFORE PRIVATE "common") +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE "common/nlohmann/json/include") +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE "common/jwt-cpp/include") +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE ${CERTIFICATE_INCLUDE_PATHS}) +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE ${LOGGING_UNTRUSTED_INCLUDE_PATH}) + +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE "$ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/Build/Release/dist/include/") +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE "$ENV{DCAP_PRIMITIVES}") +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE "$ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src") +TARGET_INCLUDE_DIRECTORIES(${U_OA_LIB_STATIC} PRIVATE "$ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationCommons/include") + +TARGET_COMPILE_OPTIONS(${U_OA_LIB_STATIC} PRIVATE -fvisibility=hidden) +TARGET_COMPILE_OPTIONS(${U_OA_LIB_STATIC} PRIVATE -fpie) +TARGET_COMPILE_OPTIONS(${U_OA_LIB_STATIC} PRIVATE -fstack-protector) + +SET(QVL_LIB_PATH "$ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/Build/Release/dist/lib") + +add_custom_target(combined_u_static_target ALL + COMMAND mkdir -p oals_objs lqvs_objs lacs_objs laps_objs + COMMAND ar -x --output oals_objs $ + COMMAND ar -x --output lqvs_objs ${QVL_LIB_PATH}/libQuoteVerificationStatic.a + COMMAND ar -x --output lacs_objs ${QVL_LIB_PATH}/libAttestationCommonsStatic.a + COMMAND ar -x --output laps_objs ${QVL_LIB_PATH}/libAttestationParsersStatic.a + COMMAND ar -qcs lib${U_ONE_ATTESTATION_LIB_NAME}.a oals_objs/*.o lqvs_objs/*.o lacs_objs/*.o laps_objs/*.o + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${U_OA_LIB_STATIC} + ) +ADD_LIBRARY(${U_ONE_ATTESTATION_LIB_NAME} STATIC IMPORTED) +ADD_DEPENDENCIES(${U_ONE_ATTESTATION_LIB_NAME} combined_u_static_target) +SET_TARGET_PROPERTIES(${U_ONE_ATTESTATION_LIB_NAME} + PROPERTIES + IMPORTED_LOCATION lib${U_ONE_ATTESTATION_LIB_NAME}.a + ) + +################################################################################################### +# Trusted one-attestation library +################################################################################################### + +SET(T_OA_LIB_STATIC ${T_ONE_ATTESTATION_LIB_NAME}_Static) +ADD_LIBRARY(${T_OA_LIB_STATIC} STATIC + ${PROJECT_HEADERS} ${PROJECT_TRUSTED_HEADERS} ${PROJECT_SOURCES} ${PROJECT_TRUSTED_SOURCES}) + +#dependency in common to ensure the jwt lib is patched for building the trusted lib in SGX +ADD_DEPENDENCIES(${T_OA_LIB_STATIC} patch_jwt) + +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "common/sgx-support") # for clocale, before sgxsdk includes +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "$ENV{SGX_SDK}/include") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "$ENV{SGX_SDK}/include/libcxx") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "$ENV{SGX_SDK}/include/tlibc") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "$ENV{SGX_SSL}/include") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "include") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} BEFORE PRIVATE "common") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "common/nlohmann/json/include") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "common/jwt-cpp/include") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE ${CERTIFICATE_INCLUDE_PATHS}) +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE ${LOGGING_TRUSTED_INCLUDE_PATH}) + +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "$ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/Build/Release/dist/include/") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "$ENV{DCAP_PRIMITIVES}") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "$ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationLibrary/src") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "$ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/AttestationCommons/include") +TARGET_INCLUDE_DIRECTORIES(${T_OA_LIB_STATIC} PRIVATE "$ENV{DCAP_PRIMITIVES}/QuoteVerification/QVL/Src/ThirdParty/rapidjson/include") + +TARGET_COMPILE_OPTIONS(${T_OA_LIB_STATIC} PRIVATE -nostdinc++) +TARGET_COMPILE_OPTIONS(${T_OA_LIB_STATIC} PRIVATE -fvisibility=hidden) +TARGET_COMPILE_OPTIONS(${T_OA_LIB_STATIC} PRIVATE -fpie) +TARGET_COMPILE_OPTIONS(${T_OA_LIB_STATIC} PRIVATE -fstack-protector) + +#remove time-related code from jwt tool (as dcap primitives do) +TARGET_COMPILE_OPTIONS(${T_OA_LIB_STATIC} PRIVATE -DSGX_JWT) + +add_custom_target(combined_t_static_target ALL + COMMAND mkdir -p toals_objs lacse_objs lapse_objs + COMMAND ar -x --output toals_objs $ + COMMAND ar -x --output lacse_objs ${QVL_LIB_PATH}/libAttestationCommonsStaticEnclave.a + COMMAND ar -x --output lapse_objs ${QVL_LIB_PATH}/libAttestationParsersStaticEnclave.a + COMMAND ar -qcs lib${T_ONE_ATTESTATION_LIB_NAME}.a toals_objs/*.o lacse_objs/*.o lapse_objs/*.o + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS ${U_OA_LIB_STATIC} + ) +ADD_LIBRARY(${T_ONE_ATTESTATION_LIB_NAME} STATIC IMPORTED) +ADD_DEPENDENCIES(${T_ONE_ATTESTATION_LIB_NAME} combined_t_static_target) +SET_TARGET_PROPERTIES(${T_ONE_ATTESTATION_LIB_NAME} + PROPERTIES + IMPORTED_LOCATION lib${T_ONE_ATTESTATION_LIB_NAME}.a + ) + + +################################################################################################### +# Local Tests +################################################################################################### +ENABLE_TESTING() +ADD_SUBDIRECTORY (test) + diff --git a/common/crypto/attestation-api/CMakeVariables.txt b/common/crypto/attestation-api/CMakeVariables.txt new file mode 100644 index 00000000..093af70d --- /dev/null +++ b/common/crypto/attestation-api/CMakeVariables.txt @@ -0,0 +1,7 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +SET(U_ONE_ATTESTATION_LIB_NAME u-one-attestation) +SET(T_ONE_ATTESTATION_LIB_NAME t-one-attestation) + diff --git a/common/crypto/attestation-api/LICENSE b/common/crypto/attestation-api/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/common/crypto/attestation-api/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/common/crypto/attestation-api/Makefile b/common/crypto/attestation-api/Makefile new file mode 100644 index 00000000..40439a97 --- /dev/null +++ b/common/crypto/attestation-api/Makefile @@ -0,0 +1,23 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +export SGX_MODE ?= SIM +export SGX_SSL ?= /opt/intel/sgxssl +export SGX_SDK ?= /opt/intel/sgxsdk +export DCAP_PRIMITIVES ?= /tmp/SGXDataCenterAttestationPrimitives + +all: build test + +build: + mkdir -p build + cd build && cmake .. + . ${SGX_SDK}/environment && make -C build + +.PHONY: test +test: + . ${SGX_SDK}/environment && env CTEST_OUTPUT_ON_FAILURE=1 make -C build test + +clean: + rm -rf build + diff --git a/common/crypto/attestation-api/README.md b/common/crypto/attestation-api/README.md new file mode 100644 index 00000000..daaade43 --- /dev/null +++ b/common/crypto/attestation-api/README.md @@ -0,0 +1,91 @@ +# Attestation API + +This library implements a single API for generating and verifying hardware-based attestation (e.g., Intel SGX EPID/DCAP attestations). +The library implementation originally started as part of the Fabric Private Chaincode project, and later spun off and extended. + +The library works with Intel SGX EPID attestations, verified through Intel Attestation Service (IAS), and DCAP attestations, verified through Intel Trust Authority (ITA). + +## Build + +Build the docker image to create an environment with all necessaty dependencies. +```bash +cd docker +make +``` + +### Simulation mode +Start the dev container: +```bash +docker run -v :/project -e SGX_MODE=SIM -it oaa-dev +``` + +Simulation mode is the default mode. It does not use actual Intel SGX operations, and tests are conducted on simulated-type attestations. + +```bash +make +``` + +### Hardware mode +Start the dev container, here is an example: +```bash +docker run --network host -v :/project -e SGX_MODE=HW -it oaa-dev +``` +The container is attached to the host network to download the root certificates. +Also, enabling the HW mode makes the generated artifacts use actual Intel SGX operations -- and tests are conducted on real attestations. + +DCAP support with ITA is built by default, but requires the URL to the ITA CA root certificates (in JWK format). If the URL is not specified, the build will succeed but it won't be able to verify DCAP attestations. +```bash +export ITA_ROOT_CACERT_URL= +``` + +EPID support and DCAP support for direct verificaiton (without ITA) are built by default, and require an internet connection to download the Intel CA root certificates. + +```bash +make build +``` + +#### Collateral (for usage and testing) +Using (or testing) SGX attestation requires some collateral. The folder to such collateral must be provided as: +```bash +export COLLATERAL_FOLDER= +``` + +EPID collateral files: +* `spid_type.txt`, a text file containing the SPID type ("epid-linkable" or "epid-unlinkable") +* `spid.txt`, a text file containing the SPID (a 32-byte long hex string) +* `api_key.txt`, a text file containing the API key to use IAS (a 32-byte long hex string) + +DCAP collateral files: +* `ita_api_key.txt`, a text file containing the API key to use ITA +* `attestation_type.txt`, a text file containing the attestation type ("dcap-sgx") + + +#### Testing + +To run the tests in HW mode, the collateral (see above) and the SGX devices are necessary. +Assuming a default system configuration, you may want to start the dev docker image as follows: +```bash +docker run --network host --device /dev/sgx_enclave:/dev/sgx_enclave --device /dev/sgx_provision:/dev/sgx_provision -v /var/run/aesmd:/var/run/aesmd -v :/project -v :/collateral -e SGX_MODE=HW -e COLLATERAL_FOLDER=/collateral -it oaa-dev +``` + +To test everything (simulated attestations in SIM mode, and all supported attestations in HW mode for platforms that support both EPID and DCAP): +```bash +make test +``` + +To test everything except DCAP with ITA: +```bash +SKIP_TEST_DCAP= make test +``` + +To test everything except DCAP with direct verification: +```bash +SKIP_TEST_DCAP_DIRECT= make test +``` +For SGX platform that do not support DCAP or FLC, both DCAP tests must be disabled. + + +To test everything except EPID (for SGX platforms that do not support EPID): +```bash +SKIP_TEST_EPID= make test +``` diff --git a/common/crypto/attestation-api/attestation/attestation.cpp b/common/crypto/attestation-api/attestation/attestation.cpp new file mode 100644 index 00000000..8e38eddb --- /dev/null +++ b/common/crypto/attestation-api/attestation/attestation.cpp @@ -0,0 +1,171 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "attestation.h" +#include "attestation_tags.h" +#include "base64/base64.h" +#include "error.h" +#include "logging.h" +#include "types/types.h" +#include "epid.h" +#include "dcap.h" + +// < JSON include +#define JSON_HAS_CPP_11 +#define JSON_NO_IO 1 +#include +#include "nlohmann/json.hpp" +using json = nlohmann::json; +// JSON include > + +/********************************************************************************************************************** + * Attestation APIs + * *******************************************************************************************************************/ + +typedef struct +{ + epid_state_t epid; + //dcap_state_t dcap_state +} state_u; + +typedef struct +{ + bool initialized; + std::string attestation_type; + state_u state; +} attestation_state_t; + +attestation_state_t g_attestation_state = {0}; + +bool init_attestation(uint8_t* params, uint32_t params_length) +{ + if(params == NULL) + { + LOG_ERROR("bad attestation init params"); + return false; + } + + // open json + bool ret = false; + json root; + std::string params_string((char*)params, params_length); + CATCH(ret, root = json::parse(params_string)); + COND2LOGERR(!ret, "invalid attestation params"); + + { + CATCH(ret, g_attestation_state.attestation_type = root[ATTESTATION_TYPE_TAG].template get()); + COND2LOGERR(!ret, "invalid attestation type field"); + + // check for simulated type + if (g_attestation_state.attestation_type.compare(SIMULATED_TYPE_TAG) == 0) + { + // terminate init successfully + goto init_success; + } + + //check for epid type + if (g_attestation_state.attestation_type.compare(0, strlen(EPID_PREFIX_TAG), EPID_PREFIX_TAG) == 0) + { + COND2ERR(!init_epid(params, params_length, &g_attestation_state.state.epid)); + goto init_success; + } + + //check for dcap type + if (g_attestation_state.attestation_type.compare(0, strlen(DCAP_PREFIX_TAG), DCAP_PREFIX_TAG) == 0) + { + COND2ERR(!init_dcap(params, params_length)); + goto init_success; + } + } + +init_success: + g_attestation_state.initialized = true; + return true; + +err: + return false; +} + +bool get_attestation(uint8_t* statement, + uint32_t statement_length, + uint8_t* attestation, + uint32_t attestation_max_length, + uint32_t* attestation_length) +{ + std::string b64attestation; + + COND2LOGERR(!g_attestation_state.initialized, "attestation not initialized"); + COND2LOGERR(statement == NULL, "bad input statement"); + COND2LOGERR(attestation == NULL, "bad input attestation buffer"); + COND2LOGERR(attestation_length == NULL || attestation_max_length == 0, + "bad input attestation buffer size"); + + // attestation type: simulated + if (g_attestation_state.attestation_type.compare(SIMULATED_TYPE_TAG) == 0) + { + std::string zero("0"); + b64attestation = base64_encode((const unsigned char*)zero.c_str(), zero.length()); + } + + // attestation type: epid + if (g_attestation_state.attestation_type.compare(0, strlen(EPID_PREFIX_TAG), EPID_PREFIX_TAG) == 0) + { + COND2ERR( + !get_epid_attestation( + statement, + statement_length, + &g_attestation_state.state.epid, + b64attestation)); + } + + // attestation type: dcap + if (g_attestation_state.attestation_type.compare(0, strlen(DCAP_PREFIX_TAG), DCAP_PREFIX_TAG) == 0) + { + COND2ERR( + !get_dcap_attestation( + statement, + statement_length, + b64attestation)); + } + + // Got the base64 attestation + + // package the output in json format + { + bool ret; + size_t serialization_size = 0; + std::string serialized_json; + json root; + + root[ATTESTATION_TYPE_TAG] = g_attestation_state.attestation_type; + root[ATTESTATION_TAG] = b64attestation; + + CATCH(ret, serialized_json = root.dump()); + COND2LOGERR(!ret, "error serializing attestation json"); + + //serialization_size = json_serialization_size(root_value); + serialization_size = serialized_json.length(); + COND2LOGERR( + serialization_size > attestation_max_length, + "not enough space for b64 conversion: serialization len %d buf len %d", + serialization_size, + attestation_max_length); + + std::strncpy((char*)attestation, serialized_json.c_str(), serialization_size); + + *attestation_length = serialization_size; + + LOG_DEBUG("attestation json: %s", serialized_json.c_str()); + LOG_DEBUG("attestation json length: %d", serialization_size); + } + + return true; + +err: + return false; +} diff --git a/common/crypto/attestation-api/attestation/dcap.cpp b/common/crypto/attestation-api/attestation/dcap.cpp new file mode 100644 index 00000000..46daa2f4 --- /dev/null +++ b/common/crypto/attestation-api/attestation/dcap.cpp @@ -0,0 +1,136 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "sgx_quote.h" +#include "sgx_utils.h" +#include "types/types.h" +#include "crypto/sha256.h" +#include "base64/base64.h" +#include "attestation_tags.h" +#include "logging.h" +#include "error.h" + +// < JSON include +#define JSON_HAS_CPP_11 +#define JSON_NO_IO 1 +#include +#include "nlohmann/json.hpp" +using json = nlohmann::json; +// JSON include > + +/********************************************************************************************************************** + * C prototype declarations for the ocalls + * *******************************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +sgx_status_t ocall_init_quote( + uint8_t* target, uint32_t target_len, uint8_t* egid, uint32_t egid_len, uint32_t* sgxret); +sgx_status_t ocall_get_quote(uint8_t* spid, + uint32_t spid_len, + uint8_t* sig_rl, + uint32_t sig_rl_len, + uint32_t sign_type, + uint8_t* report, + uint32_t report_len, + uint8_t* quote, + uint32_t max_quote_len, + uint32_t* actual_quote_len, + uint32_t* sgxret); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +/********************************************************************************************************************** + * DCAP Attestation APIs + * *******************************************************************************************************************/ + +bool init_dcap(uint8_t* params, uint32_t params_length) +{ + if(params == NULL) + { + LOG_ERROR("bad params"); + return false; + } + + // open json + bool ret = false; + json root; + std::string params_string((char*)params, params_length); + CATCH(ret, root = json::parse(params_string)); + COND2LOGERR(!ret, "invalid attestation params"); + + { // set attestation type + std::string attestation_type; + CATCH(ret, attestation_type = root[ATTESTATION_TYPE_TAG].template get()); + COND2LOGERR(!ret, "invalid attestation type field"); + + COND2LOGERR( + 0 != attestation_type.compare(DCAP_SGX_TYPE_TAG) && + 0 != attestation_type.compare(DCAP_DIRECT_SGX_TYPE_TAG), + "invalid attestation type: %s", attestation_type.c_str()); + } + + return true; + +err: + return false; +} + +bool get_dcap_attestation(uint8_t* statement, + uint32_t statement_length, + std::string& b64attestation) +{ + uint32_t ret; + sgx_report_t report; + sgx_target_info_t qe_target_info = {0}; + sgx_report_data_t report_data = {0}; + uint32_t attestation_length_max = (1<<13); // 8K + uint32_t attestation_length; + uint8_t attestation[attestation_length_max]; + + ByteArray ba_statement(statement, statement + statement_length); + ByteArray rd; + COND2ERR(false == SHA256(ba_statement, rd)); + + ocall_init_quote((uint8_t*)&qe_target_info, sizeof(qe_target_info), NULL, 0, &ret); + COND2LOGERR(ret != SGX_SUCCESS, "error ocall_init_quote: %d", ret); + + COND2LOGERR(rd.size() > sizeof(sgx_report_data_t), + "report data too long: %d, needed %d", rd.size(), sizeof(sgx_report_data_t)); + memcpy(&report_data, rd.data(), rd.size()); + + ret = sgx_create_report(&qe_target_info, &report_data, &report); + COND2LOGERR(SGX_SUCCESS != ret, "error sgx_create_report: %d", ret); + + ocall_get_quote( + NULL, + 0, + NULL, + 0, + 0, + (uint8_t*)&report, + sizeof(report), + attestation, + attestation_length_max, + &attestation_length, + &ret); + COND2LOGERR(ret != SGX_SUCCESS, "error ocall_get_quote: %d", ret); + COND2LOGERR(attestation_length == 0, "error get quote"); + + // convert to base64 (accepted by ITA) + b64attestation = base64_encode((const unsigned char*)attestation, attestation_length); + + return true; + +err: + return false; +} diff --git a/common/crypto/attestation-api/attestation/dcap.h b/common/crypto/attestation-api/attestation/dcap.h new file mode 100644 index 00000000..2841b007 --- /dev/null +++ b/common/crypto/attestation-api/attestation/dcap.h @@ -0,0 +1,12 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +bool init_dcap(uint8_t* params, uint32_t params_length); + +bool get_dcap_attestation(uint8_t* statement, + uint32_t statement_length, + std::string& b64attestation); + diff --git a/common/crypto/attestation-api/attestation/epid.cpp b/common/crypto/attestation-api/attestation/epid.cpp new file mode 100644 index 00000000..e71ad022 --- /dev/null +++ b/common/crypto/attestation-api/attestation/epid.cpp @@ -0,0 +1,167 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sgx_quote.h" +#include "sgx_utils.h" +#include "error.h" +#include "logging.h" +#include "attestation_tags.h" +#include "types/types.h" +#include "crypto/sha256.h" +#include "base64/base64.h" +#include "epid.h" + +// < JSON include +#define JSON_HAS_CPP_11 +#define JSON_NO_IO 1 +#include +#include "nlohmann/json.hpp" +using json = nlohmann::json; +// JSON include > + +/********************************************************************************************************************** + * C prototype declarations for the ocalls + * *******************************************************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +sgx_status_t ocall_init_quote( + uint8_t* target, uint32_t target_len, uint8_t* egid, uint32_t egid_len, uint32_t* sgxret); +sgx_status_t ocall_get_quote(uint8_t* spid, + uint32_t spid_len, + uint8_t* sig_rl, + uint32_t sig_rl_len, + uint32_t sign_type, + uint8_t* report, + uint32_t report_len, + uint8_t* quote, + uint32_t max_quote_len, + uint32_t* actual_quote_len, + uint32_t* sgxret); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +/********************************************************************************************************************** + * EPID Attestation APIs + * *******************************************************************************************************************/ + +bool init_epid(uint8_t* params, uint32_t params_length, epid_state_t* state) +{ + if(params == NULL || state == NULL) + { + LOG_ERROR("bad params"); + return false; + } + + // open json + bool ret = false; + json root; + std::string params_string((char*)params, params_length); + CATCH(ret, root = json::parse(params_string)); + COND2LOGERR(!ret, "invalid attestation params"); + + { // set attestation type + std::string attestation_type; + CATCH(ret, attestation_type = root[ATTESTATION_TYPE_TAG].template get()); + COND2LOGERR(!ret, "invalid attestation type field"); + + state->sign_type = -1; + if (attestation_type.compare(EPID_LINKABLE_TYPE_TAG) == 0) + { + state->sign_type = SGX_LINKABLE_SIGNATURE; + } + + if (attestation_type.compare(EPID_UNLINKABLE_TYPE_TAG) == 0) + { + state->sign_type = SGX_UNLINKABLE_SIGNATURE; + } + + COND2LOGERR(state->sign_type == -1, "wrong attestation type"); + } + + { // set SPID + HexEncodedString hex_spid; + CATCH(ret, hex_spid = root[SPID_TAG].template get()); + COND2LOGERR(!ret, "invalid spid"); + COND2LOGERR(hex_spid.length() != sizeof(sgx_spid_t) * 2, "wrong spid length"); + + // translate hex spid to binary + ByteArray ba = HexEncodedStringToByteArray(hex_spid); + memcpy(state->spid.id, ba.data(), ba.size()); + } + + { // set sig_rl + std::string sig_rl_str; + CATCH(ret, sig_rl_str = root[SIG_RL_TAG].template get()); + COND2LOGERR(!ret, "invalid sig_rl"); + state->sig_rl = ByteArray(sig_rl_str.begin(), sig_rl_str.end()); + } + + return true; + +err: + return false; +} + +bool get_epid_attestation(uint8_t* statement, + uint32_t statement_length, + epid_state_t* state, + std::string& b64attestation) +{ + sgx_report_t report; + sgx_report_data_t report_data = {0}; + sgx_target_info_t qe_target_info = {0}; + sgx_epid_group_id_t egid = {0}; + uint32_t ret; + uint32_t attestation_length_max = (1<<12); // 4K + uint32_t attestation_length; + uint8_t attestation[attestation_length_max]; + + ByteArray ba_statement(statement, statement + statement_length); + ByteArray rd; + COND2ERR(false == SHA256(ba_statement, rd)); + + ocall_init_quote((uint8_t*)&qe_target_info, sizeof(qe_target_info), (uint8_t*)&egid, sizeof(egid), &ret); + COND2LOGERR(ret != SGX_SUCCESS, "error ocall_init_quote: %d", ret); + + + COND2LOGERR(rd.size() > sizeof(sgx_report_data_t), + "report data too long: %d, needed %d", rd.size(), sizeof(sgx_report_data_t)); + memcpy(&report_data, rd.data(), rd.size()); + + ret = sgx_create_report(&qe_target_info, &report_data, &report); + COND2LOGERR(SGX_SUCCESS != ret, "error sgx_create_report: %d", ret); + + ocall_get_quote( + (uint8_t*)&state->spid, + (uint32_t)sizeof(sgx_spid_t), + state->sig_rl.data(), + state->sig_rl.size(), + state->sign_type, + (uint8_t*)&report, + sizeof(report), + attestation, + attestation_length_max, + &attestation_length, + &ret); + COND2LOGERR(ret != SGX_SUCCESS, "error ocall_get_quote: %d", ret); + COND2LOGERR(attestation_length == 0, "error get quote"); + + // convert to base64 (accepted by IAS) + b64attestation = base64_encode((const unsigned char*)attestation, attestation_length); + + return true; + +err: + return false; +} diff --git a/common/crypto/attestation-api/attestation/epid.h b/common/crypto/attestation-api/attestation/epid.h new file mode 100644 index 00000000..5cc9ce87 --- /dev/null +++ b/common/crypto/attestation-api/attestation/epid.h @@ -0,0 +1,22 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "sgx_quote.h" +#include "sgx_utils.h" + +typedef struct +{ + sgx_spid_t spid; + ByteArray sig_rl; + uint32_t sign_type; +} epid_state_t; + +bool init_epid(uint8_t* params, uint32_t params_length, epid_state_t* state); + +bool get_epid_attestation(uint8_t* statement, + uint32_t statement_length, + epid_state_t* state, + std::string& b64attestation); diff --git a/common/crypto/attestation-api/common/.gitignore b/common/crypto/attestation-api/common/.gitignore new file mode 100644 index 00000000..7209299c --- /dev/null +++ b/common/crypto/attestation-api/common/.gitignore @@ -0,0 +1,2 @@ +.jwt-cpp-patched + diff --git a/common/crypto/attestation-api/common/CMakeLists.txt b/common/crypto/attestation-api/common/CMakeLists.txt new file mode 100644 index 00000000..9b92ef9b --- /dev/null +++ b/common/crypto/attestation-api/common/CMakeLists.txt @@ -0,0 +1,22 @@ +# Copyright 2024 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + + +SET(JWT_PATCHED_FILENAME .jwt-cpp-patched) +SET(JWT_PATCHED_FILEPATH ${CMAKE_CURRENT_SOURCE_DIR}/${JWT_PATCHED_FILENAME} PARENT_SCOPE) + +ADD_CUSTOM_COMMAND( + OUTPUT ${JWT_PATCHED_FILENAME} + COMMAND [ ! -f ${JWT_PATCHED_FILENAME} ] && cd jwt-cpp && git apply ../jwt-cpp.patch && touch ../${JWT_PATCHED_FILENAME} || true + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + +ADD_CUSTOM_TARGET(patch_jwt DEPENDS ${JWT_PATCHED_FILENAME}) + +# TODO: devise better strategy for clean up; usually the build folder is removed so the clean is not called +ADD_CUSTOM_TARGET(clean_patch_jwt + COMMAND [ -f ${JWT_PATCHED_FILENAME} ] && cd jwt-cpp && git apply --reverse ../jwt-cpp.patch && rm ../${JWT_PATCHED_FILENAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + diff --git a/common/crypto/attestation-api/common/Makefile b/common/crypto/attestation-api/common/Makefile new file mode 100644 index 00000000..f43bcfce --- /dev/null +++ b/common/crypto/attestation-api/common/Makefile @@ -0,0 +1,15 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +.jwt-cpp-patched: + cd jwt-cpp && git apply ../jwt-cpp.patch && touch ../.jwt-cpp-patched + +all build test: .jwt-cpp-patched + +clean: + if [ -f .jwt-cpp-patched ]; then \ + cd jwt-cpp && git apply --reverse ../jwt-cpp.patch && rm ../.jwt-cpp-patched ;\ + fi + + diff --git a/common/crypto/attestation-api/common/_nologging/CMakeLists.txt b/common/crypto/attestation-api/common/_nologging/CMakeLists.txt new file mode 100644 index 00000000..7ea91835 --- /dev/null +++ b/common/crypto/attestation-api/common/_nologging/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +SET(LOGGING_TRUSTED_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/trusted PARENT_SCOPE) +SET(LOGGING_UNTRUSTED_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/untrusted PARENT_SCOPE) +SET(LOGGING_UNTRUSTED_LIB "" PARENT_SCOPE) +SET(LOGGING_TRUSTED_LIB "" PARENT_SCOPE) + diff --git a/common/crypto/attestation-api/common/_nologging/README.md b/common/crypto/attestation-api/common/_nologging/README.md new file mode 100644 index 00000000..dca2d76a --- /dev/null +++ b/common/crypto/attestation-api/common/_nologging/README.md @@ -0,0 +1,4 @@ +This package provides the `LOG_*` defines inside and outside of the enclave for logging purposes. +Inside the enclave, the package disables logging, i.e., no enclave-edge APIs are produced +and all function calls are empty. +Outside of the enclave, the package uses the standard I/O library. diff --git a/common/crypto/attestation-api/common/_nologging/ocalls/logging.edl b/common/crypto/attestation-api/common/_nologging/ocalls/logging.edl new file mode 100644 index 00000000..e99af1fb --- /dev/null +++ b/common/crypto/attestation-api/common/_nologging/ocalls/logging.edl @@ -0,0 +1,7 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +enclave {}; diff --git a/common/crypto/attestation-api/common/_nologging/trusted/logging.h b/common/crypto/attestation-api/common/_nologging/trusted/logging.h new file mode 100644 index 00000000..dbe654e4 --- /dev/null +++ b/common/crypto/attestation-api/common/_nologging/trusted/logging.h @@ -0,0 +1,17 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef logging_h +#define logging_h + +#define LOG_DEBUG(fmt, ...) +#define LOG_INFO(fmt, ...) +#define LOG_WARNING(fmt, ...) +#define LOG_ERROR(fmt, ...) +#define LOG(fmt, ...) + +#endif + diff --git a/common/crypto/attestation-api/common/_nologging/untrusted/logging.h b/common/crypto/attestation-api/common/_nologging/untrusted/logging.h new file mode 100644 index 00000000..39b05f69 --- /dev/null +++ b/common/crypto/attestation-api/common/_nologging/untrusted/logging.h @@ -0,0 +1,18 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef logging_h +#define logging_h + +#include + +#define LOG_DEBUG(fmt, ...) printf("DEBUG: %s-%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define LOG_INFO(fmt, ...) printf("INFO: %s-%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define LOG_WARNING(fmt, ...) printf("WARNING: %s-%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define LOG_ERROR(fmt, ...) printf("ERROR: %s-%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__) + +#endif // logging_h diff --git a/common/crypto/attestation-api/common/_yeslogging/CMakeLists.txt b/common/crypto/attestation-api/common/_yeslogging/CMakeLists.txt new file mode 100644 index 00000000..f85f85e4 --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +CMAKE_MINIMUM_REQUIRED(VERSION 3.2 FATAL_ERROR) + +PROJECT(Logging) + +INCLUDE(CMakeVariables.txt) + +FILE(GLOB PROJECT_OCALLS + "ocalls/*.c" + ) + +FILE(GLOB PROJECT_TRUSTED_SOURCES + "trusted/*.c" + ) + +FILE(GLOB PROJECT_UNTRUSTED_SOURCES + "untrusted/*.c" + ) + +################################################################################################### +# Untrusted logging library +################################################################################################### +ADD_LIBRARY(${U_LOGGING_LIB_NAME} STATIC ${PROJECT_UNTRUSTED_SOURCES} ${PROJECT_OCALLS}) + +TARGET_INCLUDE_DIRECTORIES(${U_LOGGING_LIB_NAME} PRIVATE "untrusted/") +TARGET_INCLUDE_DIRECTORIES(${U_LOGGING_LIB_NAME} PRIVATE "../../common") # path for error.h + +# fPIC necessary for `g_log_callback` +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") + +################################################################################################### +# Trusted logging library +################################################################################################### +ADD_LIBRARY(${T_LOGGING_LIB_NAME} STATIC ${PROJECT_TRUSTED_SOURCES}) + +TARGET_INCLUDE_DIRECTORIES(${T_LOGGING_LIB_NAME} PRIVATE "trusted/") +TARGET_INCLUDE_DIRECTORIES(${T_LOGGING_LIB_NAME} PRIVATE "../../common") # for error.h +TARGET_INCLUDE_DIRECTORIES(${T_LOGGING_LIB_NAME} PUBLIC "${SGX_SDK}/include/tlibc") + +################################################################################################### +# Test +################################################################################################### +enable_testing() +ADD_SUBDIRECTORY(test) diff --git a/common/crypto/attestation-api/common/_yeslogging/CMakeVariables.txt b/common/crypto/attestation-api/common/_yeslogging/CMakeVariables.txt new file mode 100644 index 00000000..5a2c13ff --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/CMakeVariables.txt @@ -0,0 +1,29 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +include_guard() + +SET(U_LOGGING_LIB_NAME ulogging) +SET(T_LOGGING_LIB_NAME tlogging) + +# variables useful for a parent cmake using this module +SET(LOGGING_TRUSTED_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/trusted PARENT_SCOPE) +SET(LOGGING_UNTRUSTED_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/untrusted PARENT_SCOPE) +SET(LOGGING_UNTRUSTED_LIB ${U_LOGGING_LIB_NAME} PARENT_SCOPE) +SET(LOGGING_TRUSTED_LIB ${T_LOGGING_LIB_NAME} PARENT_SCOPE) + +# set LOGGING_FLAGS based on SGX_BUILD +if ("$ENV{SGX_BUILD}" STREQUAL "DEBUG") + set(LOGGING_FLAGS "-DDO_DEBUG=true") +elseif("$ENV{SGX_BUILD}" STREQUAL "PRERELEASE") + set(LOGGING_FLAGS "-DDO_DEBUG=false") +elseif("$ENV{SGX_BUILD}" STREQUAL "RELEASE") + set(LOGGING_FLAGS "-DDO_DEBUG=false") +else() + set(LOGGING_FLAGS "-DDO_DEBUG=false") +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${LOGGING_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LOGGING_FLAGS}") + diff --git a/common/crypto/attestation-api/common/_yeslogging/Makefile b/common/crypto/attestation-api/common/_yeslogging/Makefile new file mode 100644 index 00000000..7e07d612 --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/Makefile @@ -0,0 +1,22 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +TOP = ../.. +#include $(TOP)/build.mk + +BUILD_DIR := build + +build: + @if [ ! -d $(BUILD_DIR) ]; then \ + mkdir -p $(BUILD_DIR) && \ + cd $(BUILD_DIR) && \ + cmake ./.. ; \ + fi + $(MAKE) --directory=$(BUILD_DIR) + +test: build + $(MAKE) -C $(BUILD_DIR) test + +clean: + rm -rf $(BUILD_DIR) diff --git a/common/crypto/attestation-api/common/_yeslogging/include/log-defines.h b/common/crypto/attestation-api/common/_yeslogging/include/log-defines.h new file mode 100644 index 00000000..5a2a7f17 --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/include/log-defines.h @@ -0,0 +1,85 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef LOG_DEFINES +#define LOG_DEFINES + +#ifndef TAG +#define TAG "" +#endif + +#define LOC_FMT " (%s:%d) " + +#define NRM "\x1B[0m" +#define CYN "\x1B[36m" +#define YEL "\x1B[33m" +#define RED "\x1B[31m" + +/* + * Note: `DO_DEBUG` is set to `false` by default, so no `LOG_DEBUG` is displayed. + * At compile time, this behaviour can be changed by defining `-DDO_DEBUG=true` before the header is + * included. In SGX deployments, such define should be set "only" when the `SGX_BUILD` environment + * variable is set to `DEBUG`. Finally, notice that `DO_INFO`, `DO_WARNING` and `DO_ERROR` are set + * to `true` by default. So, unless they are explictly disabled at compile time, the respective logs + * will be displayed. + */ + +#ifndef DO_DEBUG +#define DO_DEBUG true +#endif + +#ifndef DO_INFO +#define DO_INFO true +#endif + +#ifndef DO_WARNING +#define DO_WARNING true +#endif + +#ifndef DO_ERROR +#define DO_ERROR true +#endif + +#ifdef __cplusplus +extern "C" { +#endif +int loggingf(const char* fmt, ...); +#ifdef __cplusplus +} +#endif + +#if DO_DEBUG == true +#define LOG_DEBUG(fmt, ...) \ + loggingf(CYN "DEBUG " LOC_FMT TAG YEL fmt NRM "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#else // DO_DEBUG +#define LOG_DEBUG(fmt, ...) +#endif // DO_DEBUG + +#if DO_INFO == true +#define LOG_INFO(fmt, ...) \ + loggingf(CYN "INFO " LOC_FMT TAG NRM fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#else // DO_INFO +#define LOG_INFO(fmt, ...) +#endif // DO_INFO + +#if DO_WARNING == true +#define LOG_WARNING(fmt, ...) \ + loggingf(CYN "WARNING " LOC_FMT TAG RED fmt NRM "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#else // DO_WARNING +#define LOG_WARNING(fmt, ...) +#endif // DO_WARNING + +#if DO_ERROR == true +#define LOG_ERROR(fmt, ...) \ + loggingf(CYN "ERROR " LOC_FMT TAG RED fmt NRM "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#else // DO_ERROR +#define LOG_ERROR(fmt, ...) +#endif // DO_ERROR + +#define ERROR_LOG_STRING "error log - omitted" + +#endif // LOG_DEFINES diff --git a/common/crypto/attestation-api/common/_yeslogging/ocalls/logging.c b/common/crypto/attestation-api/common/_yeslogging/ocalls/logging.c new file mode 100644 index 00000000..714c3090 --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/ocalls/logging.c @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "logging.h" +#include "error.h" + +int ocall_log(const char* str) +{ + COND2ERR(str == NULL); + return loggingf(str); + +err: + return 0; +} diff --git a/common/crypto/attestation-api/common/_yeslogging/ocalls/logging.edl b/common/crypto/attestation-api/common/_yeslogging/ocalls/logging.edl new file mode 100644 index 00000000..fd347f5c --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/ocalls/logging.edl @@ -0,0 +1,12 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +enclave { + untrusted { + int ocall_log([in, string] const char *str); + }; +}; diff --git a/common/crypto/attestation-api/common/_yeslogging/test/CMakeLists.txt b/common/crypto/attestation-api/common/_yeslogging/test/CMakeLists.txt new file mode 100644 index 00000000..1185d00f --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/test/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + + +################################################################################################## +## LOG test app: +## this app tests the untrusted log library +################################################################################################## +SET(TEST_LOG_APP test_log_app) +PROJECT(${TEST_LOG_APP} CXX) +ADD_EXECUTABLE(${TEST_LOG_APP} + untrusted/test.cpp + ) + +TARGET_INCLUDE_DIRECTORIES(${TEST_LOG_APP} PRIVATE "../untrusted") # for logging.h +TARGET_INCLUDE_DIRECTORIES(${TEST_LOG_APP} PRIVATE "../../../common") # for error.h +TARGET_LINK_LIBRARIES(${TEST_LOG_APP} ${U_LOGGING_LIB_NAME}) + +# Register this application as a test +add_test( + NAME ${TEST_LOG_APP} + COMMAND ./${TEST_LOG_APP} + ) + +IF(DEFINED TEST_TARGET) + ADD_DEPENDENCIES(${TEST_TARGET} ${TEST_LOG_APP}) +endif() + diff --git a/common/crypto/attestation-api/common/_yeslogging/test/untrusted/test.cpp b/common/crypto/attestation-api/common/_yeslogging/test/untrusted/test.cpp new file mode 100644 index 00000000..d5c8bc15 --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/test/untrusted/test.cpp @@ -0,0 +1,38 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "error.h" +#include "logging.h" + +int main() +{ + int r; + + LOG_INFO("IF YOU READ THIS, IT'S GOOD - 1"); // this should be displayed + + r = loggingf("IF YOU READ THIS, IT'S GOOD - 2"); // this should be displayed + COND2ERR(r == 0); + + r = logging_set_callback(&puts); + COND2ERR(r == 0); + + r = loggingf("HOPEFULLY YOU READ THIS! -3"); // this succeeds, should be displayed + COND2ERR(r == 0); + + LOG_DEBUG("If you read this, log DEBUG is enabled"); + LOG_INFO("If you read this, log INFO is enabled"); + LOG_WARNING("If you read this, log WARNING is enabled"); + LOG_ERROR("If you read this, log ERROR is enabled"); + + puts("Test successful"); + return 0; + +err: + + puts("test log failed"); + return -1; +} diff --git a/common/crypto/attestation-api/common/_yeslogging/trusted/logging.c b/common/crypto/attestation-api/common/_yeslogging/trusted/logging.c new file mode 100644 index 00000000..9ed3f6ae --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/trusted/logging.c @@ -0,0 +1,40 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "logging.h" +#include //for BUFSIZ +#include //for va_list +#include +#include "error.h" + +int ocall_log(int* retval, const char* str); + +int loggingf(const char* fmt, ...) +{ + char buf[BUFSIZ] = {'\0'}; + va_list ap; + va_start(ap, fmt); + int n = vsnprintf(buf, BUFSIZ, fmt, ap); + va_end(ap); + + char* pbuf; + if (n >= 0 || n < BUFSIZ) + pbuf = buf; + else + pbuf = ERROR_LOG_STRING; + + int sgxstatus, ret; + sgxstatus = ocall_log(&ret, buf); + COND2ERR(sgxstatus != 0); + + COND2ERR(pbuf != buf); // if outputted error log, fail + + return ret; + +err: + return 0; +} diff --git a/common/crypto/attestation-api/common/_yeslogging/trusted/logging.h b/common/crypto/attestation-api/common/_yeslogging/trusted/logging.h new file mode 100644 index 00000000..73faa365 --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/trusted/logging.h @@ -0,0 +1,25 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef logging_h +#define logging_h + +#undef TAG +#define TAG "[Enclave] " + +#include "../include/log-defines.h" + +/* + * `loggingf` forwards the input string to the ocall function. + * Returns a boolean as integer: + * 0 false/error + * >0 true/success + * + * The function prototype is in "../include/log-defines.h" + */ + +#endif diff --git a/common/crypto/attestation-api/common/_yeslogging/untrusted/logging.c b/common/crypto/attestation-api/common/_yeslogging/untrusted/logging.c new file mode 100644 index 00000000..68b7ad68 --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/untrusted/logging.c @@ -0,0 +1,51 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "logging.h" +#include +#include "error.h" + +static log_callback_f g_log_callback = puts; + +bool logging_set_callback(log_callback_f log_callback) +{ + COND2ERR(log_callback == NULL); + + g_log_callback = log_callback; + return true; + +err: + return false; +} + +int loggingf(const char* fmt, ...) +{ + COND2ERR(g_log_callback == NULL); + + char buf[BUFSIZ] = {'\0'}; + va_list ap; + int n; + + va_start(ap, fmt); + n = vsnprintf(buf, BUFSIZ, fmt, ap); + va_end(ap); + + char* pbuf; + if (n >= 0 || n < BUFSIZ) + pbuf = buf; + else + pbuf = ERROR_LOG_STRING; + + n = g_log_callback(pbuf); + COND2ERR(n < 0); + + COND2ERR(pbuf != buf); // if outputted error log, fail + + return 1; + +err: + return 0; +} diff --git a/common/crypto/attestation-api/common/_yeslogging/untrusted/logging.h b/common/crypto/attestation-api/common/_yeslogging/untrusted/logging.h new file mode 100644 index 00000000..ba75f6ed --- /dev/null +++ b/common/crypto/attestation-api/common/_yeslogging/untrusted/logging.h @@ -0,0 +1,49 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef logging_h +#define logging_h + +#include +#include // for printf +#include "../include/log-defines.h" + +/* + * log_callback_f is the function type that the user must pass as a callback, + * through `logging_set_callback`. + * The expected return value roughly follows the standard definitions of `printf` and `puts`: + * - negative int for error + * - non-negative for success + */ +typedef int (*log_callback_f)(const char* str); + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * `logging_set_callback` lets a user set the callback logging function. + * By default, no callback function is set. + * So the `loggingf` function below fails if no callback is initialized. + */ +bool logging_set_callback(log_callback_f log_callback); + +/* + * `loggingf` forwards the input string to the initialized callback function. + * By default, no callback function is initialized, so `loggingf` returns error. + * Returns a boolean as integer: + * 0 false/error + * >0 true/success + * + * The function prototype is in "../include/log-defines.h" + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif // logging_h diff --git a/common/crypto/attestation-api/common/base64/base64.cpp b/common/crypto/attestation-api/common/base64/base64.cpp new file mode 100644 index 00000000..08bb6284 --- /dev/null +++ b/common/crypto/attestation-api/common/base64/base64.cpp @@ -0,0 +1,122 @@ +/* + base64.cpp and base64.h + + base64 encoding and decoding with C++. + + Version: 1.01.00 + + Copyright (C) 2004-2017 René Nyffenegger + + This source code is provided 'as-is', without any express or implied + warranty. In no event will the author be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this source code must not be misrepresented; you must not + claim that you wrote the original source code. If you use this source code + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original source code. + + 3. This notice may not be removed or altered from any source distribution. + + René Nyffenegger rene.nyffenegger@adp-gmbh.ch + +*/ + +#include "base64.h" +#include + +static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + +static inline bool is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +__attribute__((weak)) std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i <4) ; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) + { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = ( char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while((i++ < 3)) + ret += '='; + + } + + return ret; + +} + +__attribute__((weak)) std::string base64_decode(std::string const& encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; + + while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (i ==4) { + for (i = 0; i <4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + + char_array_3[0] = ( char_array_4[0] << 2 ) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = 0; j < i; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + + for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; + } + + return ret; +} diff --git a/common/crypto/attestation-api/common/base64/base64.h b/common/crypto/attestation-api/common/base64/base64.h new file mode 100644 index 00000000..dd1134c3 --- /dev/null +++ b/common/crypto/attestation-api/common/base64/base64.h @@ -0,0 +1,14 @@ +// +// base64 encoding and decoding with C++. +// Version: 1.01.00 +// + +#ifndef BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A +#define BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A + +#include + +std::string base64_encode(unsigned char const* , unsigned int len); +std::string base64_decode(std::string const& s); + +#endif /* BASE64_H_C0CE2A47_D10E_42C9_A27C_C883944E704A */ diff --git a/common/crypto/attestation-api/common/crypto/sha256.cpp b/common/crypto/attestation-api/common/crypto/sha256.cpp new file mode 100644 index 00000000..0ecb4b7c --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/sha256.cpp @@ -0,0 +1,22 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "types/types.h" +#include + +bool SHA256(const ByteArray& message, ByteArray& hash) +{ + SHA256_CTX c; + hash.resize(32); + SHA256_Init(&c); + SHA256_Update(&c, message.data(), message.size()); + SHA256_Final(hash.data(),&c); + return true; + +err: + return false; +} + diff --git a/common/crypto/attestation-api/common/crypto/sha256.h b/common/crypto/attestation-api/common/crypto/sha256.h new file mode 100644 index 00000000..b63a3b65 --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/sha256.h @@ -0,0 +1,8 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +bool SHA256(const ByteArray& message, ByteArray& hash); + diff --git a/common/crypto/attestation-api/common/crypto/verify_dcap_direct/CMakeLists.txt b/common/crypto/attestation-api/common/crypto/verify_dcap_direct/CMakeLists.txt new file mode 100644 index 00000000..e3982437 --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_dcap_direct/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright 2024 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +SET(DCAP_ROOT_CACERT_FILE DCAP_RootCA.pem) +SET(DCAP_CERTIFICATES_H_FILE dcap-certificates.h) + +SET(CERTIFICATE_INCLUDE_PATH ${CMAKE_BINARY_DIR} PARENT_SCOPE) + +SET(DCAP_ROOT_CACERT_URL "https://certificates.trustedservices.intel.com/Intel_SGX_Provisioning_Certification_RootCA.pem") + +FILE(DOWNLOAD + "https://certificates.trustedservices.intel.com/Intel_SGX_Provisioning_Certification_RootCA.pem" + ${CMAKE_BINARY_DIR}/${DCAP_ROOT_CACERT_FILE} + TLS_VERIFY ON + SHOW_PROGRESS + ) + +FILE(READ + ${CMAKE_BINARY_DIR}/${DCAP_ROOT_CACERT_FILE} + INTEL_ROOT_CA_PEM + ) + +FILE(WRITE ${CMAKE_BINARY_DIR}/${DCAP_CERTIFICATES_H_FILE} + " +#ifndef DCAP_CERTIFICATES_H +#define DCAP_CERTIFICATES_H + +/* + * Copyright 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +extern const char dcap_ca_cert_pem[] = +R\"MLT(${INTEL_ROOT_CA_PEM} +)MLT\" +; + +#endif +") diff --git a/common/crypto/attestation-api/common/crypto/verify_dcap_direct/get_dcap_certificate.cpp b/common/crypto/attestation-api/common/crypto/verify_dcap_direct/get_dcap_certificate.cpp new file mode 100644 index 00000000..e3fde2f2 --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_dcap_direct/get_dcap_certificate.cpp @@ -0,0 +1,14 @@ +/* + * Copyright 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "dcap-certificates.h" + +bool get_dcap_certificate(std::string& certificate) +{ + certificate = std::string(dcap_ca_cert_pem); + return true; +} diff --git a/common/crypto/attestation-api/common/crypto/verify_dcap_direct/get_dcap_certificate.h b/common/crypto/attestation-api/common/crypto/verify_dcap_direct/get_dcap_certificate.h new file mode 100644 index 00000000..30087ba6 --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_dcap_direct/get_dcap_certificate.h @@ -0,0 +1,7 @@ +/* + * Copyright 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +bool get_dcap_certificate(std::string& certificate); diff --git a/common/crypto/attestation-api/common/crypto/verify_ias_report/.gitignore b/common/crypto/attestation-api/common/crypto/verify_ias_report/.gitignore new file mode 100644 index 00000000..7979a60c --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_ias_report/.gitignore @@ -0,0 +1 @@ +ias-certificates.cpp diff --git a/common/crypto/attestation-api/common/crypto/verify_ias_report/CMakeLists.txt b/common/crypto/attestation-api/common/crypto/verify_ias_report/CMakeLists.txt new file mode 100644 index 00000000..77b0c26b --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_ias_report/CMakeLists.txt @@ -0,0 +1,39 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +SET(INTEL_ROOT_CACERT_FILE Intel_SGX_Attestation_RootCA.pem) +SET(IAS_CERTIFICATES_H_FILE ias-certificates.h) + +SET(CERTIFICATE_INCLUDE_PATH ${CMAKE_BINARY_DIR} PARENT_SCOPE) + +FILE(DOWNLOAD + https://certificates.trustedservices.intel.com/${INTEL_ROOT_CACERT_FILE} + ${CMAKE_BINARY_DIR}/${INTEL_ROOT_CACERT_FILE} + TLS_VERIFY ON + SHOW_PROGRESS + ) + +FILE(READ + ${CMAKE_BINARY_DIR}/${INTEL_ROOT_CACERT_FILE} + INTEL_ROOT_CA_PEM + ) + +FILE(WRITE ${CMAKE_BINARY_DIR}/${IAS_CERTIFICATES_H_FILE} + " +#ifndef IAS_CERTIFICATES_H +#define IAS_CERTIFICATES_H + +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +extern const char ias_report_signing_ca_cert_pem[] = +R\"MLT(${INTEL_ROOT_CA_PEM} +)MLT\" +; + +#endif +") diff --git a/common/crypto/attestation-api/common/crypto/verify_ias_report/verify-report.cpp b/common/crypto/attestation-api/common/crypto/verify_ias_report/verify-report.cpp new file mode 100644 index 00000000..a391cb92 --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_ias_report/verify-report.cpp @@ -0,0 +1,311 @@ +/* Copyright 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "verify-report.h" + +#include +#include +#include +#include +#include + +#include "ias-certificates.h" +#include "error.h" +#include "logging.h" + +// < JSON include +#define JSON_HAS_CPP_11 +#define JSON_NO_IO 1 +#include +#include "nlohmann/json.hpp" +using json = nlohmann::json; +// JSON include > + +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +//########### INTERNAL FUNCTIONS ######################################### +//######################################################################## + +/* EVP_DecodeBlock pads its output with \0 if the output length is not + a multiple of 3. Check if the base64 string is padded at the end + and adjust the output length. */ +static int EVP_DecodeBlock_wrapper(unsigned char* out, + int out_len, + const unsigned char* in, + int in_len) +{ + /* Use a temporary output buffer. We do not want to disturb the + original output buffer with extraneous \0 bytes. */ + unsigned char buf[in_len]; + + int ret = EVP_DecodeBlock(buf, in, in_len); + COND2ERR(ret == -1); + if (in[in_len - 1] == '=' && in[in_len - 2] == '=') + { + ret -= 2; + } + else if (in[in_len - 1] == '=') + { + ret -= 1; + } + + memcpy(out, buf, out_len); + return ret; + +err: + return -1; +} + +//######################################################################## +//########### INTERNAL FUNCTIONS ######################################### +//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + +#define IAS_QUOTE_STATUS_JSON_STRING "isvEnclaveQuoteStatus" + +struct qss +{ + const char* s; + size_t l; +}; + +#define MAKE_QSS_ITEM(x) \ + { \ + x, sizeof(x) - 1 \ + } +#define INIT_QS_ARRAY_ITEM(x, y) [x] = MAKE_QSS_ITEM(y) + +const struct qss quote_status[QS_NUMBER] = { + INIT_QS_ARRAY_ITEM(QS_INVALID, "INVALID"), + INIT_QS_ARRAY_ITEM(QS_OK, "OK"), + INIT_QS_ARRAY_ITEM(QS_GROUP_OUT_OF_DATE, "GROUP_OUT_OF_DATE"), + INIT_QS_ARRAY_ITEM(QS_CONFIGURATION_NEEDED, "CONFIGURATION_NEEDED"), + INIT_QS_ARRAY_ITEM(QS_SW_HARDENING_NEEDED, "SW_HARDENING_NEEDED"), + INIT_QS_ARRAY_ITEM(QS_CONFIGURATION_AND_SW_HARDENING_NEEDED, + "CONFIGURATION_AND_SW_HARDENING_NEEDED")}; + +quote_status_e get_quote_status(const char* ias_report, unsigned int ias_report_len) +{ + bool ret = false; + json root; + std::string ias_quote_status_str; + int i; + + CATCH(ret, root = json::parse(ias_report)); + COND2LOGERR(!ret, "invalid ias report json"); + + CATCH(ret, ias_quote_status_str = root[IAS_QUOTE_STATUS_JSON_STRING].template get()); + COND2LOGERR(!ret, "invalid ias quote status field"); + + for (i = 1; i < QS_NUMBER; i++) + { + if (0 == ias_quote_status_str.compare(quote_status[i].s)) + { + return (quote_status_e)i; + } + } + +err: + return QS_INVALID; +} + +int get_quote_from_report(const uint8_t* report, const int report_len, sgx_quote_t* quote) +{ + // Move report into \0 terminated buffer such that we can work + // with str* functions. + int buf_len = report_len + 1; + char buf[buf_len]; + char* p_begin = NULL; + char* p_end = NULL; + int ret = -1; + int quote_base64_len = 0; + uint8_t* quote_bin = NULL; + uint32_t quote_bin_len = 0; + + memcpy(buf, report, buf_len); + buf[report_len] = '\0'; + + const int json_string_max_len = 64; + const char json_string[json_string_max_len] = "\"isvEnclaveQuoteBody\":\""; + p_begin = strstr(buf, json_string); + COND2ERR(p_begin == NULL); + p_begin += strnlen(json_string, json_string_max_len); + p_end = strchr(p_begin, '"'); + COND2ERR(p_end == NULL); + + quote_base64_len = p_end - p_begin; + quote_bin = (uint8_t*)malloc(quote_base64_len); + quote_bin_len = quote_base64_len; + + ret = EVP_DecodeBlock(quote_bin, (unsigned char*)p_begin, quote_base64_len); + COND2ERR(ret == -1); + + quote_bin_len = ret; + COND2ERR(quote_bin_len > sizeof(sgx_quote_t)); + memset(quote, 0, sizeof(sgx_quote_t)); + memcpy(quote, quote_bin, sizeof(sgx_quote_t)); + free(quote_bin); + + // success + return 0; + +err: + return -1; +} + +verify_status_t verify_ias_report_signature(const char* ias_attestation_signing_cert_pem, + const char* ias_report, + unsigned int ias_report_len, + char* ias_signature, + unsigned int ias_signature_len) +{ + X509* crt = NULL; + int ret = -1; + int ias_signature_decoded_len = 2048; + unsigned char ias_signature_decoded[ias_signature_decoded_len]; + EVP_PKEY* key = NULL; + EVP_MD_CTX* ctx = NULL; + + BIO* crt_bio = BIO_new_mem_buf((void*)ias_attestation_signing_cert_pem, -1); + COND2ERR(crt_bio == NULL); + + crt = PEM_read_bio_X509(crt_bio, NULL, 0, NULL); + COND2ERR(crt == NULL); + + key = X509_get_pubkey(crt); + COND2ERR(key == NULL); + + ctx = EVP_MD_CTX_create(); + ret = EVP_VerifyInit_ex(ctx, EVP_sha256(), NULL); + COND2ERR(ret != 1); + + ret = EVP_VerifyUpdate(ctx, ias_report, ias_report_len); + COND2ERR(ret != 1); + + ret = EVP_DecodeBlock_wrapper(ias_signature_decoded, + ias_signature_decoded_len, + (unsigned char*)ias_signature, + ias_signature_len); + COND2ERR(ret == -1); + + ret = EVP_VerifyFinal(ctx, (unsigned char*)ias_signature_decoded, ret, key); + + EVP_MD_CTX_destroy(ctx); + EVP_PKEY_free(key); + X509_free(crt); + BIO_free(crt_bio); + + COND2ERR(ret != 1); // 1 == correct signature + + return VERIFY_SUCCESS; /* success */ + +err: + return VERIFY_FAILURE; +} + +verify_status_t verify_ias_certificate_chain(const char* cert_pem, const time_t untrusted_time) +{ + /* Using the IAS CA certificate as a root of trust. */ + /* Checking that cert is signed by CA. */ + + X509* cacrt = NULL; + X509* crt = NULL; + BIO* crt_bio = NULL; + BIO* cacrt_bio = NULL; + X509_STORE* s = NULL; + X509_STORE_CTX* ctx = NULL; + X509_VERIFY_PARAM* param; + int rc = -1; + + COND2ERR(cert_pem == NULL); + + crt_bio = BIO_new_mem_buf((void*)cert_pem, -1); + crt = PEM_read_bio_X509(crt_bio, NULL, 0, NULL); + COND2ERR(crt == NULL); + + cacrt_bio = BIO_new_mem_buf((void*)ias_report_signing_ca_cert_pem, -1); + cacrt = PEM_read_bio_X509(cacrt_bio, NULL, 0, NULL); + // the correct CA certificate is hard-coded, so this must never fail + assert(cacrt != NULL); + + //initialize store/context + s = X509_STORE_new(); + COND2ERR(s == NULL); + rc = X509_STORE_add_cert(s, cacrt); + COND2ERR(rc != 1); + ctx = X509_STORE_CTX_new(); + COND2ERR(ctx == NULL); + rc = X509_STORE_CTX_init(ctx, s, crt, NULL); + COND2ERR(rc != 1); + + //initialize time + param = X509_STORE_CTX_get0_param(ctx); + COND2ERR(param == NULL); + X509_VERIFY_PARAM_set_time(param, untrusted_time); + + rc = X509_verify_cert(ctx); + // check value after free + + X509_STORE_CTX_free(ctx); + X509_STORE_free(s); + X509_free(crt); + X509_free(cacrt); + BIO_free(crt_bio); + BIO_free(cacrt_bio); + + COND2ERR(rc <= 0); + + return VERIFY_SUCCESS; + +err: + return VERIFY_FAILURE; +} + +/** + * Check if isvEnclaveQuoteStatus is "OK" + * (cf. https://software.intel.com/sites/default/files/managed/7e/3b/ias-api-spec.pdf, + * pg. 24). + * + * @return 0 if verified successfully, 1 otherwise. + */ +verify_status_t verify_enclave_quote_status(const char* ias_report, + unsigned int ias_report_len, + unsigned int quote_status_flags) +{ + quote_status_e qs; + + qs = get_quote_status(ias_report, ias_report_len); + + switch (qs) + { + case QS_INVALID: + COND2ERR(1); + + case QS_OK: + return VERIFY_SUCCESS; + + case QS_GROUP_OUT_OF_DATE: + case QS_CONFIGURATION_NEEDED: + case QS_SW_HARDENING_NEEDED: + case QS_CONFIGURATION_AND_SW_HARDENING_NEEDED: + COND2ERR(0 == (quote_status_flags & (1 << qs))); + return VERIFY_SUCCESS; + + default: + COND2ERR(1); + } + +err: + // quote not ok + return VERIFY_FAILURE; +} diff --git a/common/crypto/attestation-api/common/crypto/verify_ias_report/verify-report.h b/common/crypto/attestation-api/common/crypto/verify_ias_report/verify-report.h new file mode 100644 index 00000000..a9fdc8e8 --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_ias_report/verify-report.h @@ -0,0 +1,70 @@ +/* Copyright 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef VERIFY_REPORT_H +#define VERIFY_REPORT_H + +#include +#include + +typedef enum +{ + VERIFY_SUCCESS, + VERIFY_FAILURE +} verify_status_t; + +typedef enum +{ + QS_INVALID, + QS_OK, + QS_GROUP_OUT_OF_DATE, + QS_CONFIGURATION_NEEDED, + QS_SW_HARDENING_NEEDED, + QS_CONFIGURATION_AND_SW_HARDENING_NEEDED, + QS_NUMBER +} quote_status_e; + +#define QSF_ACCEPT_GROUP_OUT_OF_DATE (1 << QS_GROUP_OUT_OF_DATE) +#define QSF_ACCEPT_CONFIGURATION_NEEDED (1 << QS_CONFIGURATION_NEEDED) +#define QSF_ACCEPT_SW_HARDENING_NEEDED (1 << QS_SW_HARDENING_NEEDED) +#define QSF_ACCEPT_CONFIGURATION_AND_SW_HARDENING_NEEDED \ + (1 << QS_CONFIGURATION_AND_SW_HARDENING_NEEDED) +#define QSF_ACCEPT_ALL UINT_MAX +#define QSF_REJECT_ALL (0) + +#ifdef __cplusplus +extern "C" { +#endif + +int get_quote_from_report(const uint8_t* report, const int report_len, sgx_quote_t* quote); +verify_status_t verify_enclave_quote_status(const char* ias_report, + unsigned int ias_report_len, + unsigned int quote_status_flags); +verify_status_t verify_ias_certificate_chain(const char* cert_pem, + const time_t untrusted_time); +verify_status_t verify_ias_report_signature(const char* ias_attestation_signing_cert_pem, + const char* ias_report, + unsigned int ias_report_len, + char* ias_signature, + unsigned int ias_signature_len); + +quote_status_e get_quote_status(const char* ias_report, unsigned int ias_report_len); +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/common/crypto/attestation-api/common/crypto/verify_ita_token/CMakeLists.txt b/common/crypto/attestation-api/common/crypto/verify_ita_token/CMakeLists.txt new file mode 100644 index 00000000..49457cb4 --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_ita_token/CMakeLists.txt @@ -0,0 +1,46 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +SET(ITA_ROOT_CACERT_FILE ITA_RootCA.jwk) +SET(ITA_CERTIFICATES_H_FILE ita-certificates.h) + +SET(CERTIFICATE_INCLUDE_PATH ${CMAKE_BINARY_DIR} PARENT_SCOPE) + +IF (NOT DEFINED ENV{ITA_ROOT_CACERT_URL}) + MESSAGE(WARNING "No ITA certs url in ITA_ROOT_CACERT_URL: an empty root cert will be used (DCAP verifications will fail)") + FILE(TOUCH + ${CMAKE_BINARY_DIR}/${ITA_ROOT_CACERT_FILE} + ) +ELSE() + FILE(DOWNLOAD + $ENV{ITA_ROOT_CACERT_URL} + ${CMAKE_BINARY_DIR}/${ITA_ROOT_CACERT_FILE} + TLS_VERIFY ON + SHOW_PROGRESS + ) +ENDIF() + +FILE(READ + ${CMAKE_BINARY_DIR}/${ITA_ROOT_CACERT_FILE} + INTEL_ROOT_CA_JWT + ) + +FILE(WRITE ${CMAKE_BINARY_DIR}/${ITA_CERTIFICATES_H_FILE} + " +#ifndef ITA_CERTIFICATES_H +#define ITA_CERTIFICATES_H + +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +extern const char ita_token_signing_ca_cert_jwt[] = +R\"MLT(${INTEL_ROOT_CA_JWT} +)MLT\" +; + +#endif +") diff --git a/common/crypto/attestation-api/common/crypto/verify_ita_token/verify-token.cpp b/common/crypto/attestation-api/common/crypto/verify_ita_token/verify-token.cpp new file mode 100644 index 00000000..539b9e1e --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_ita_token/verify-token.cpp @@ -0,0 +1,112 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "types/types.h" +#include "verify-token.h" +#include "ita-certificates.h" +#include "logging.h" +#include "error.h" + +#define JSON_HAS_CPP_11 +#define JSON_NO_IO 1 +#include +#include "nlohmann/json/single_include/nlohmann/json.hpp" + +#define JWT_DISABLE_PICOJSON +#include "jwt-cpp/include/jwt-cpp/traits/nlohmann-json/traits.h" +#include "jwt-cpp/include/jwt-cpp/jwt.h" + +bool get_ita_certificate(std::string& certificate) +{ + certificate = std::string(ita_token_signing_ca_cert_jwt); + return true; +} + +verify_status_t verify_ita_token_signature(const std::string token) +{ + + std::string cert; + std::string t(token); + get_ita_certificate(cert); + + COND2LOGERR(cert.length() <= 1, "Unable to verify ITA tokens: ITA root cert not provided"); + + try + { + auto decoded_token = jwt::decode(t); + //auto iat = decoded_token.get_issued_at().time_since_epoch().count(); + //auto exp = decoded_token.get_expires_at().time_since_epoch().count(); + //auto now = std::chrono::system_clock::time_point::clock::now().time_since_epoch().count(); + LOG_DEBUG("token decoded"); + //LOG_DEBUG("iat: %ld", iat); + //LOG_DEBUG("exp: %ld", exp); + //LOG_DEBUG("now: %ld", now); + LOG_DEBUG("keyid: %s", decoded_token.get_key_id().c_str()); + + jwt::jwks jwkeys = jwt::parse_jwks(cert); + auto jwkey = jwkeys.get_jwk(decoded_token.get_key_id()); + auto x5cert = jwkey.get_x5c_key_value(); + auto pemkey = jwt::helper::convert_base64_der_to_pem(x5cert); + LOG_DEBUG("pem: %s", pemkey.c_str()); + + auto verifier = jwt::verify().allow_algorithm(jwt::algorithm::ps384(pemkey, "", "", "")); + verifier.verify(decoded_token); + LOG_DEBUG("token verified"); + } + catch (const std::exception &exc) + { + LOG_ERROR("Exception: %s", exc.what()); + if(std::string(exc.what()).compare("token expired") == 0) + { + bool b; + int leeway = 30; // 30 seconds leeway + auto decoded_token = jwt::decode(t); + jwt::jwks jwkeys = jwt::parse_jwks(cert); + auto jwkey = jwkeys.get_jwk(decoded_token.get_key_id()); + auto x5cert = jwkey.get_x5c_key_value(); + auto pemkey = jwt::helper::convert_base64_der_to_pem(x5cert); + auto verifier = jwt::verify().allow_algorithm(jwt::algorithm::ps384(pemkey, "", "", "")); + verifier.leeway(leeway); + CATCH(b, verifier.verify(decoded_token)); + COND2LOGERR(!b, "failed token verification"); + + LOG_DEBUG("token verified, leeway: %d", leeway); + goto ok; + } + goto err; + } + +ok: + return VERIFY_SUCCESS; + + +err: + return VERIFY_FAILURE; +} + + +bool get_token_payload(const std::string token, std::string& payload) +{ + try + { + auto decoded_token = jwt::decode(token); + std::string header = decoded_token.get_header(); + LOG_INFO("%s", header.c_str()); + payload = decoded_token.get_payload(); + LOG_INFO("%s", payload.c_str()); + } + catch (const std::exception &exc) + { + LOG_ERROR("Exception: %s", exc.what()); + goto err; + } + + return true; + +err: + return false; +} + diff --git a/common/crypto/attestation-api/common/crypto/verify_ita_token/verify-token.h b/common/crypto/attestation-api/common/crypto/verify_ita_token/verify-token.h new file mode 100644 index 00000000..1f918546 --- /dev/null +++ b/common/crypto/attestation-api/common/crypto/verify_ita_token/verify-token.h @@ -0,0 +1,16 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +typedef enum +{ + VERIFY_SUCCESS, + VERIFY_FAILURE +} verify_status_t; + +bool get_ita_certificate(std::string& certificate); +verify_status_t verify_ita_token_signature(std::string token); +bool get_token_payload(std::string token, std::string& payload); + diff --git a/common/crypto/attestation-api/common/error.h b/common/crypto/attestation-api/common/error.h new file mode 100644 index 00000000..bba2c421 --- /dev/null +++ b/common/crypto/attestation-api/common/error.h @@ -0,0 +1,46 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef COND2ERR +#define COND2ERR(b) \ + do \ + { \ + if (b) \ + { \ + LOG_DEBUG("error at %s:%d\n", __FILE__, __LINE__); \ + goto err; \ + } \ + } while (0) +#endif //COND2ERR + +#ifndef COND2LOGERR +#define COND2LOGERR(b, fmt, ...) \ + do \ + { \ + if (b) \ + { \ + LOG_ERROR("error at %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ + goto err; \ + } \ + } while (0) +#endif //COND2LOGERR + +#ifndef CATCH +#define CATCH(b, expr) \ + do \ + { \ + try \ + { \ + expr; \ + b = true; \ + } \ + catch (const std::exception &exc) \ + { \ + LOG_ERROR("exception at %s:%d: %s\n", __FILE__, __LINE__, exc.what()); \ + b = false; \ + } \ + } while (0); +#endif //CATCH diff --git a/common/crypto/attestation-api/common/jwt-cpp b/common/crypto/attestation-api/common/jwt-cpp new file mode 160000 index 00000000..4a537e96 --- /dev/null +++ b/common/crypto/attestation-api/common/jwt-cpp @@ -0,0 +1 @@ +Subproject commit 4a537e969891dde542ad8b1a4a214955a83be29f diff --git a/common/crypto/attestation-api/common/jwt-cpp.patch b/common/crypto/attestation-api/common/jwt-cpp.patch new file mode 100644 index 00000000..da8da3ad --- /dev/null +++ b/common/crypto/attestation-api/common/jwt-cpp.patch @@ -0,0 +1,224 @@ +diff --git a/include/jwt-cpp/jwt.h b/include/jwt-cpp/jwt.h +index 211305e..3b00e2b 100644 +--- a/include/jwt-cpp/jwt.h ++++ b/include/jwt-cpp/jwt.h +@@ -72,11 +72,12 @@ + * JWS (JSON Web Signature) from [RFC7515](https://tools.ietf.org/html/rfc7515) + */ + namespace jwt { ++#ifndef SGX_JWT + /** + * Default system time point in UTC + */ + using date = std::chrono::system_clock::time_point; +- ++#endif + /** + * \brief Everything related to error codes issued by the library + */ +@@ -2148,8 +2149,10 @@ namespace jwt { + ~basic_claim() = default; + + JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::string_type s) : val(std::move(s)) {} ++#ifndef SGX_JWT + JWT_CLAIM_EXPLICIT basic_claim(const date& d) + : val(typename json_traits::integer_type(std::chrono::system_clock::to_time_t(d))) {} ++#endif + JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::array_type a) : val(std::move(a)) {} + JWT_CLAIM_EXPLICIT basic_claim(typename json_traits::value_type v) : val(std::move(v)) {} + JWT_CLAIM_EXPLICIT basic_claim(const set_t& s) : val(typename json_traits::array_type(s.begin(), s.end())) {} +@@ -2188,13 +2191,14 @@ namespace jwt { + */ + typename json_traits::string_type as_string() const { return json_traits::as_string(val); } + ++#ifndef SGX_JWT + /** + * Get the contained JSON value as a date + * \return content as date + * \throw std::bad_cast Content was not a date + */ + date as_date() const { return std::chrono::system_clock::from_time_t(as_int()); } +- ++#endif + /** + * Get the contained JSON value as an array + * \return content as array +@@ -2402,6 +2406,7 @@ namespace jwt { + + return aud.as_set(); + } ++#ifndef SGX_JWT + /** + * Get expires claim + * \return expires as a date in utc +@@ -2423,6 +2428,7 @@ namespace jwt { + * \throw std::bad_cast Claim was present but not a date (Should not happen in a valid token) + */ + date get_issued_at() const { return get_payload_claim("iat").as_date(); } ++#endif + /** + * Get id claim + * \return id as string +@@ -2780,6 +2786,7 @@ namespace jwt { + builder& set_audience(typename json_traits::string_type aud) { + return set_payload_claim("aud", typename json_traits::value_type(aud)); + } ++#ifndef SGX_JWT + /** + * Set expires at claim + * \param d Expires time +@@ -2798,6 +2805,7 @@ namespace jwt { + * \return *this to allow for method chaining + */ + builder& set_issued_at(const date& d) { return set_payload_claim("iat", basic_claim(d)); } ++#endif + /** + * Set id claim + * \param str ID to set +@@ -2898,10 +2906,15 @@ namespace jwt { + */ + template + struct verify_context { ++#ifndef SGX_JWT + verify_context(date ctime, const decoded_jwt& j, size_t l) + : current_time(ctime), jwt(j), default_leeway(l) {} + // Current time, retrieved from the verifiers clock and cached for performance and consistency + date current_time; ++#else ++ verify_context(const decoded_jwt& j, size_t l) ++ : jwt(j), default_leeway(l) {} ++#endif + // The jwt passed to the verifier + const decoded_jwt& jwt; + // The configured default leeway for this verification +@@ -2969,6 +2982,7 @@ namespace jwt { + } + }; + ++#ifndef SGX_JWT + /** + * Checks that the current time is before the time specified in the given + * claim. This is identical to how the "exp" check works. +@@ -3002,7 +3016,7 @@ namespace jwt { + } + } + }; +- ++#endif + /** + * Checks if the given set is a subset of the set inside the token. + * If the token value is a string it is traited as a set of a single element. +@@ -3053,11 +3067,16 @@ namespace jwt { + } + + static std::string to_lower_unicode(const std::string& str, const std::locale& loc) { ++#ifndef SGX_JWT + std::wstring_convert, wchar_t> conv; + auto wide = conv.from_bytes(str); + auto& f = std::use_facet>(loc); + f.tolower(&wide[0], &wide[0] + wide.size()); + return conv.to_bytes(wide); ++#else ++ // TODO - don't lowercase the string as locale support inside enclave is limited ++ return str; ++#endif + } + }; + } // namespace verify_ops +@@ -3066,7 +3085,11 @@ namespace jwt { + * Verifier class used to check if a decoded token contains all claims required by your application and has a valid + * signature. + */ ++#ifndef SGX_JWT + template ++#else ++ template ++#endif + class verifier { + public: + using basic_claim_t = basic_claim; +@@ -3099,8 +3122,10 @@ namespace jwt { + std::unordered_map claims; + /// Leeway time for exp, nbf and iat + size_t default_leeway = 0; ++#ifndef SGX_JWT + /// Instance of clock type + Clock clock; ++#endif + /// Supported algorithms + std::unordered_map> algs; + +@@ -3109,6 +3134,7 @@ namespace jwt { + * Constructor for building a new verifier instance + * \param c Clock instance + */ ++#ifndef SGX_JWT + explicit verifier(Clock c) : clock(c) { + claims["exp"] = [](const verify_ops::verify_context& ctx, std::error_code& ec) { + if (!ctx.jwt.has_expires_at()) return; +@@ -3132,6 +3158,7 @@ namespace jwt { + } + }; + } ++#endif + + /** + * Set default leeway to use. +@@ -3142,6 +3169,7 @@ namespace jwt { + default_leeway = leeway; + return *this; + } ++#ifndef SGX_JWT + /** + * Set leeway for expires at. + * If not specified the default leeway will be used. +@@ -3172,7 +3200,7 @@ namespace jwt { + claims["iat"] = verify_ops::date_after_claim{leeway}; + return *this; + } +- ++#endif + /** + * Set an type to check for. + * +@@ -3294,8 +3322,11 @@ namespace jwt { + } + algs.at(algo)->verify(data, sig, ec); + if (ec) return; +- ++#ifndef SGX_JWT + verify_ops::verify_context ctx{clock.now(), jwt, default_leeway}; ++#else ++ verify_ops::verify_context ctx{jwt, default_leeway}; ++#endif + for (auto& c : claims) { + ctx.claim_key = c.first; + c.second(ctx, ec); +@@ -3569,7 +3600,7 @@ namespace jwt { + }); + } + }; +- ++#ifndef SGX_JWT + /** + * Create a verifier using the given clock + * \param c Clock instance to use +@@ -3596,7 +3627,17 @@ namespace jwt { + verifier verify(default_clock c = {}) { + return verifier(c); + } +- ++#else ++ /** ++ * Create a verifier using the given clock ++ * \param c Clock instance to use ++ * \return verifier instance ++ */ ++ template ++ verifier verify() { ++ return verifier(); ++ } ++#endif + /** + * Return a builder instance to create a new token + */ diff --git a/common/crypto/attestation-api/common/logging b/common/crypto/attestation-api/common/logging new file mode 120000 index 00000000..897f0d0c --- /dev/null +++ b/common/crypto/attestation-api/common/logging @@ -0,0 +1 @@ +_nologging \ No newline at end of file diff --git a/common/crypto/attestation-api/common/nlohmann/json b/common/crypto/attestation-api/common/nlohmann/json new file mode 160000 index 00000000..3780b41d --- /dev/null +++ b/common/crypto/attestation-api/common/nlohmann/json @@ -0,0 +1 @@ +Subproject commit 3780b41dd070436f3f55327b0a88f27a52e2dfa8 diff --git a/common/crypto/attestation-api/common/scripts/common_utils.sh b/common/crypto/attestation-api/common/scripts/common_utils.sh new file mode 100644 index 00000000..9742e521 --- /dev/null +++ b/common/crypto/attestation-api/common/scripts/common_utils.sh @@ -0,0 +1,85 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +if [[ -z "$TERM" ]] || [[ "$TERM" == 'dumb' ]]; then + # to avoid 'tput: No value for $TERM and no -T specified' errors .. + cred= + cgrn= + cblu= + cmag= + cwht= + cbld= + bred= + bgrn= + bblu= + bwht= + crst= +else + cred=$(tput setaf 1) + cgrn=$(tput setaf 2) + cblu=$(tput setaf 4) + cmag=$(tput setaf 5) + cwht=$(tput setaf 7) + cbld=$(tput bold) + bred=$(tput setab 1) + bgrn=$(tput setab 2) + bblu=$(tput setab 4) + bwht=$(tput setab 7) + crst=$(tput sgr0) +fi + +function recho () { + echo "${cbld}${cred}"$@"${crst}" >&2 +} + +function becho () { + echo "${cbld}${cblu}"$@"${crst}" >&2 +} + +function gecho () { + echo "${cbld}${cgrn}"$@"${crst}" >&2 +} + +# Common reporting functions: say, yell & die +#----------------------------------------- +# they all write to stderr. if you want normal progres for stdout, just use echo +function say () { + echo "$(basename $0): $*" >&2; +} + +function yell () { + becho "$(basename $0): $*" >&2; +} + +function die() { + recho "$(basename $0): $*" >&2 + exit 111 +} + +function para() { + echo -e "\n" +} + +# Common functions to run commands +#----------------------------------------- +try() { + "$@" || die "test failed: $*" +} + +try_fail() { + recho "failure expected next" + (! "$@") || die "rev-test failed: $*" +} + +# Variant of try which stores commands stdout and stderr (or only stdout) in variable RESPONSE +try_r() { + say "$@" + export RESPONSE=$("$@" 2>&1) RESPONSE_TYPE="out+err" || die "test failed: $*" +} + +try_out_r() { + say "$@" + export RESPONSE=$("$@") RESPONSE_TYPE="out" || die "test failed: $*" +} + diff --git a/common/crypto/attestation-api/common/sgx-support/clocale b/common/crypto/attestation-api/common/sgx-support/clocale new file mode 100644 index 00000000..3edcc8ee --- /dev/null +++ b/common/crypto/attestation-api/common/sgx-support/clocale @@ -0,0 +1,59 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/*********** + +This is support code for SGX, mainly to keep the nlohmann json library unmodified. + +************/ + +#ifndef CLOCALE +#define CLOCALE + +typedef struct { + char *decimal_point; + char *thousands_sep; + char *grouping; + char *int_curr_symbol; + char *currency_symbol; + char *mon_decimal_point; + char *mon_thousands_sep; + char *mon_grouping; + char *positive_sign; + char *negative_sign; + char int_frac_digits; + char frac_digits; + char p_cs_precedes; + char p_sep_by_space; + char n_cs_precedes; + char n_sep_by_space; + char p_sign_posn; + char n_sign_posn; +} lconv; + +namespace std +{ + + using lconv = lconv; + static lconv l = + { + NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,0,0,0,0,0,0 + }; + + //char* setlocale(int category, const char* locale); + static lconv* localeconv() + { + return &l; + } + +} // std + +static lconv* localeconv() +{ + return std::localeconv(); +} + +#endif //CLOCALE diff --git a/common/crypto/attestation-api/common/types/hex_string.cpp b/common/crypto/attestation-api/common/types/hex_string.cpp new file mode 100644 index 00000000..78eff573 --- /dev/null +++ b/common/crypto/attestation-api/common/types/hex_string.cpp @@ -0,0 +1,156 @@ +/* Copyright 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "hex_string.h" +#include "error.h" +#include "logging.h" + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +static inline uint8_t HexToNibble(char hex, bool& ok) +{ + hex = toupper(hex); + + if (hex >= 'A' && hex <= 'F') { // A-F case + ok = true; + return 10 + (hex - 'A'); + } + if (hex >= '0' && hex <= '9') { // 0-9 case + ok = true; + return hex - '0'; + } + + LOG_ERROR("Hex digit is not valid: %c", hex); + ok = false; + return 0; +} // HexToNibble + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +static inline uint8_t HexToByte(const char* inHexDigits, bool& ok) +{ + bool b1, b2; + uint8_t c1 = HexToNibble(inHexDigits[0], b1); + uint8_t c2 = HexToNibble(inHexDigits[1], b2); + COND2ERR(b1 == false || b2 == false); + + ok = true; + return (c1 << 4) | c2; + +err: + LOG_ERROR("HexToNibble: %c %c -> %u %u", inHexDigits[0], inHexDigits[1], c1, c2); + ok = false; + return 0; +} // HexToByte + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +std::vector HexStringToBinary( + const std::string& inHexString + ) +{ + // Create a buffer to hold the binary data and use the array + // implementation to do the actual conversion + std::vector binaryData(inHexString.length() / 2); + COND2ERR(false == HexStringToBinary(&binaryData[0], binaryData.size(), inHexString)); + return binaryData; + +err: + LOG_ERROR("HexStringToBinary: str(%ld) %s to vect(%ld)", inHexString.length(), inHexString.c_str(), binaryData.size()); + binaryData.resize(0); + return binaryData; +} // HexStringToBinary + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +bool HexStringToBinary( + uint8_t* outBinaryData, + size_t inBinaryDataLength, + const std::string& inHexString + ) +{ + // Verify that the hex string is an even length + COND2LOGERR((inHexString.length() % 2) != 0, "Hex encoded string is not an even length"); + + { + const char* pHex = inHexString.c_str(); + size_t len = inHexString.length(); + bool b; + inBinaryDataLength = std::min(inBinaryDataLength, len / 2); + size_t pos = 0; + size_t opos = 0; + while (pos < len && opos < inBinaryDataLength) { + outBinaryData[opos++] = HexToByte(&pHex[pos], b); + COND2ERR(b == false); + pos += 2; + } + } + + return true; + +err: + LOG_ERROR("HexStringToBinary: str(%ld) %s", inHexString.length(), inHexString.c_str()); + return false; +} // HexStringToBinary + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +std::string BinaryToHexString( + const std::vector& inBinaryData + ) +{ + return BinaryToHexString(&inBinaryData[0], inBinaryData.size()); +} // BinaryToHexString + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +std::string BinaryToHexString( + const uint8_t* inBinaryData, + size_t inBinaryDataLength + ) +{ + static const char *hexDigits = "0123456789ABCDEF"; + + // Create a string and give a hint to its final size (twice the size + // of the input binary data) + std::string hexString; + hexString.reserve(inBinaryDataLength * 2); + + // Run through the binary data and convert to a hex string + std::for_each( + inBinaryData, + inBinaryData + inBinaryDataLength, + [&hexString](uint8_t inputByte) { + hexString.push_back(hexDigits[inputByte >> 4]); + hexString.push_back(hexDigits[inputByte & 0x0F]); + }); + + return hexString; +} // BinaryToHexString + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +bool IsHex(const uint8_t* inBinaryData, size_t inBinaryDataLength) +{ + for(int i=0; i +#include +#include + +// This macro calculates the length of the actual data portion of the +// hex-string encoding of a buffer with x bytes PLUS the additional byte +// needed for the string terminator. +#define HEX_STRING_SIZE(x) (static_cast(((x) * 2))) + +// Convert a hex string (i.e., a string of characters with values +// between '0'-'9', 'A'-'F') to an array of bytes +std::vector HexStringToBinary( + const std::string& inHexString + ); + +bool HexStringToBinary( + uint8_t* outBinaryData, + size_t inBinaryDataLength, + const std::string& inHexString + ); + +// Convert an array of bytes (represented as either a std::vector of +// bytes or a raw array) to a hex string. +std::string BinaryToHexString( + const std::vector& inBinaryData + ); +std::string BinaryToHexString( + const uint8_t* inBinaryData, + size_t inBinaryDataLength + ); + +bool IsHex(const uint8_t* inBinaryData, size_t inBinaryDataLength); +bool IsHex(const std::string s); + diff --git a/common/crypto/attestation-api/common/types/types.cpp b/common/crypto/attestation-api/common/types/types.cpp new file mode 100644 index 00000000..df66fdd5 --- /dev/null +++ b/common/crypto/attestation-api/common/types/types.cpp @@ -0,0 +1,85 @@ +/* Copyright 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "types/types.h" +#include "base64/base64.h" +#include "types/hex_string.h" + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// Simple conversion from ByteArray to std::string +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +std::string ByteArrayToString(const ByteArray& inArray) +{ + std::string outString; + std::transform(inArray.begin(), inArray.end(), std::back_inserter(outString), + [](unsigned char c) -> char { return (char)c; }); + + return outString; +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// Conversion from byte array to string array +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +void ByteArrayToStringArray(const ByteArray& inByteArray, StringArray& outStringArray) +{ + outStringArray.resize(0); + std::transform(inByteArray.begin(), inByteArray.end(), std::back_inserter(outStringArray), + [](unsigned char c) -> char { return (char)c; }); +} + +StringArray ByteArrayToStringArray(const ByteArray& inByteArray) +{ + StringArray outStringArray(0); + ByteArrayToStringArray(inByteArray, outStringArray); + return outStringArray; +} + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// Simple conversion from ByteArray to Base64EncodedString +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +Base64EncodedString ByteArrayToBase64EncodedString(const ByteArray& buf) +{ + return base64_encode(buf.data(), buf.size()); +} // ByteArrayToBase64EncodedString + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// Simple conversion from Base64EncodedString to ByteArray +ByteArray Base64EncodedStringToByteArray(const Base64EncodedString& encoded) +{ + std::string s = base64_decode(encoded); + ByteArray b; + std::transform(s.begin(), s.end(), std::back_inserter(b), + [](unsigned char c) -> char { return (uint8_t)c; }); + return b; +} // Base64EncodedStringToByteArray + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// Simple conversion from ByteArray to HexEncodedString +HexEncodedString ByteArrayToHexEncodedString(const ByteArray& buf) +{ + return BinaryToHexString(buf); +} // ByteArrayToHexEncodedString + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +// Simple conversion from HexEncodedString to ByteArray +// throws ValueError +ByteArray HexEncodedStringToByteArray(const HexEncodedString& encoded) +{ + return HexStringToBinary(encoded); +} // HexEncodedStringToByteArray diff --git a/common/crypto/attestation-api/common/types/types.h b/common/crypto/attestation-api/common/types/types.h new file mode 100644 index 00000000..168d695e --- /dev/null +++ b/common/crypto/attestation-api/common/types/types.h @@ -0,0 +1,76 @@ +/* Copyright 2018 Intel Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +//*** For binary unformatted data***// +typedef std::vector ByteArray; + +//*** For vector containing printable characters ***// +class StringArray : public std::vector +{ +public: + StringArray(const std::string& value) + { + assign(value); + }; + + StringArray(const size_t size) + { + resize(size); + std::vector::assign(size, '\0'); + }; + + void assign(const std::string& value) + { + std::vector::assign(value.begin(), value.end()); + } + + std::string str() + { + return std::string(this->data()); + }; +}; /* class StringArray */ + +//*** For printable base64 encoded string***// +typedef std::string Base64EncodedString; + +//*** For printable hex encoded string***// +typedef std::string HexEncodedString; + +// Simple conversion from ByteArray to String +std::string ByteArrayToString(const ByteArray& inArray); + +// Conversion from byte array to string array +void ByteArrayToStringArray(const ByteArray& inArray, StringArray& outStringArray); +StringArray ByteArrayToStringArray(const ByteArray& inArray); + +// Simple conversion from ByteArray to Base64EncodedString +Base64EncodedString ByteArrayToBase64EncodedString(const ByteArray& buf); + +// Simple conversion from Base64EncodedString to ByteArray +ByteArray Base64EncodedStringToByteArray(const Base64EncodedString& encoded); + +// Simple conversion from ByteArray to HexEncodedString +HexEncodedString ByteArrayToHexEncodedString(const ByteArray& buf); + +// Simple conversion from HexEncodedString to ByteArray +// throws ValuenError +ByteArray HexEncodedStringToByteArray(const HexEncodedString& encoded); diff --git a/common/crypto/attestation-api/conversion/attestation_to_evidence.sh b/common/crypto/attestation-api/conversion/attestation_to_evidence.sh new file mode 100755 index 00000000..14abd221 --- /dev/null +++ b/common/crypto/attestation-api/conversion/attestation_to_evidence.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +if [[ -z "${OAA_PATH}" ]]; then + echo "OAA_PATH not set" + exit -1 +fi + +CUR_SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +. ${OAA_PATH}/common/scripts/common_utils.sh +. ${CUR_SCRIPT_PATH}/tag_to_variable.sh +. ${CUR_SCRIPT_PATH}/simulated/a2e.sh +. ${CUR_SCRIPT_PATH}/epid/a2e.sh +. ${CUR_SCRIPT_PATH}/dcap/a2e.sh +. ${CUR_SCRIPT_PATH}/dcap-direct/a2e.sh + +tag_to_variable "ATTESTATION_TYPE_TAG" +tag_to_variable "ATTESTATION_TAG" +tag_to_variable "EVIDENCE_TAG" +tag_to_variable "SIMULATED_TYPE_TAG" +tag_to_variable "EPID_LINKABLE_TYPE_TAG" +tag_to_variable "EPID_UNLINKABLE_TYPE_TAG" +tag_to_variable "DCAP_SGX_TYPE_TAG" +tag_to_variable "DCAP_DIRECT_SGX_TYPE_TAG" + +########################################################### +# attestation_to_evidence +# input: attestation as parameter +# output: EVIDENCE variable +# +# This is the main function for a2e conversion. +########################################################### +function attestation_to_evidence() { + if [[ -z "$1" ]]; then + die "no argument provided" + fi + + say "Input Attestation: $1" + + ATTESTATION_TYPE=$(echo $1 | jq ".$ATTESTATION_TYPE_TAG" -r) + ATTESTATION=$(echo $1 | jq ".$ATTESTATION_TAG" -r) + + case "$ATTESTATION_TYPE" in + $SIMULATED_TYPE_TAG) + simulated_to_evidence "$ATTESTATION" + EVIDENCE=$SIMULATED_EVIDENCE + ;; + + $EPID_LINKABLE_TYPE_TAG) + ;& + $EPID_UNLINKABLE_TYPE_TAG) + b64quote_to_iasresponse "$ATTESTATION" + iasresponse_to_evidence "$IAS_RESPONSE" + EVIDENCE=$IAS_EVIDENCE + ;; + $DCAP_SGX_TYPE_TAG) + b64quote_to_itaresponse "$ATTESTATION" + itaresponse_to_evidence "$ITA_RESPONSE" + EVIDENCE=$ITA_EVIDENCE + ;; + $DCAP_DIRECT_SGX_TYPE_TAG) + b64quote_to_evidence "$ATTESTATION" + EVIDENCE=$DCAP_EVIDENCE + ;; + *) + die "error attestation type $ATTESTATION_TYPE" + ;; + esac + + #package evidence + EVIDENCE=$(jq -c -n --arg attestation_type "$ATTESTATION_TYPE" --arg evidence "$EVIDENCE" '{'\"$ATTESTATION_TYPE_TAG\"': $attestation_type, '\"$EVIDENCE_TAG\"': $evidence}') + + say "Output Evidence: $EVIDENCE" +} + +########################################################### +# Main (if script is directly called rather than included in other script) +# +# - expects attestation is sole command-line parameter +# - on success, return evidence on stdout +# Note: evidence is terminated with newline, depending on use-case +# this might have to be trimmed by consumer +# +########################################################### +(return 0 2>/dev/null) && sourced=1 || sourced=0 +if [ $sourced -eq "0" ]; then # i'm directly executed and not sourced in other program + function say() { # suppress normal output ... + : + } + attestation_to_evidence $1 + echo "${EVIDENCE}" +fi diff --git a/common/crypto/attestation-api/conversion/dcap-direct/a2e.sh b/common/crypto/attestation-api/conversion/dcap-direct/a2e.sh new file mode 100644 index 00000000..c7f09065 --- /dev/null +++ b/common/crypto/attestation-api/conversion/dcap-direct/a2e.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# Copyright 2024 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -ex + +CUR_SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +B64A_2_B64C=${CUR_SCRIPT_PATH}/b64attestation_to_b64collateral + +. ${CUR_SCRIPT_PATH}/../tag_to_variable.sh + + + +function b64quote_to_evidence() { + QUOTE=$1 + COLLATERAL=$(${B64A_2_B64C} $QUOTE) + UNTRUSTED_TIME_T=$(date +%s) + tag_to_variable "ATTESTATION_TAG" + tag_to_variable "COLLATERAL_TAG" + tag_to_variable "UNTRUSTED_TIME_T_TAG" + + DCAP_EVIDENCE=$(jq -c -n --arg attestation "$QUOTE" --arg collateral "$COLLATERAL" --arg untrusted_time_t "$UNTRUSTED_TIME_T" '{'\"$ATTESTATION_TAG\"': $attestation, '\"$COLLATERAL_TAG\"': $collateral, '\"$UNTRUSTED_TIME_T_TAG\"': $untrusted_time_t}') +} diff --git a/common/crypto/attestation-api/conversion/dcap-direct/b64attestation2b64collateral.cpp b/common/crypto/attestation-api/conversion/dcap-direct/b64attestation2b64collateral.cpp new file mode 100644 index 00000000..bac5012e --- /dev/null +++ b/common/crypto/attestation-api/conversion/dcap-direct/b64attestation2b64collateral.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "types/types.h" +#include "base64/base64.h" +#include "sgx_ql_lib_common.h" +#include "sgx_dcap_quoteverify.h" + +uint8_t* serialize_collateral(sgx_ql_qve_collateral_t* c) +{ + uint32_t collateral_size = sizeof(sgx_ql_qve_collateral_t) + c->pck_crl_issuer_chain_size + c->root_ca_crl_size + c->pck_crl_size + c->tcb_info_issuer_chain_size + c->tcb_info_size + c->qe_identity_issuer_chain_size + c->qe_identity_size; + fprintf(stderr, "calculated collateral size: %d\n", collateral_size); + + uint8_t* p = (uint8_t*)malloc(collateral_size); + if(p == NULL) return NULL; + memset(p, '\0', collateral_size); + + // NOTICE / WARNING: here we copy the entire data structure with "meaningless" pointers + // pointers will have to be adjusted at deserialization time + memcpy(p, (uint8_t*)c, sizeof(sgx_ql_qve_collateral_t)); + memcpy(p+sizeof(sgx_ql_qve_collateral_t), c->pck_crl_issuer_chain, c->pck_crl_issuer_chain_size); + memcpy(p+sizeof(sgx_ql_qve_collateral_t)+c->pck_crl_issuer_chain_size, c->root_ca_crl, c->root_ca_crl_size); + memcpy(p+sizeof(sgx_ql_qve_collateral_t)+c->pck_crl_issuer_chain_size+c->root_ca_crl_size, c->pck_crl, c->pck_crl_size); + memcpy(p+sizeof(sgx_ql_qve_collateral_t)+c->pck_crl_issuer_chain_size+c->root_ca_crl_size+c->pck_crl_size, c->tcb_info_issuer_chain, c->tcb_info_issuer_chain_size); + memcpy(p+sizeof(sgx_ql_qve_collateral_t)+c->pck_crl_issuer_chain_size+c->root_ca_crl_size+c->pck_crl_size+c->tcb_info_issuer_chain_size, c->tcb_info, c->tcb_info_size); + memcpy(p+sizeof(sgx_ql_qve_collateral_t)+c->pck_crl_issuer_chain_size+c->root_ca_crl_size+c->pck_crl_size+c->tcb_info_issuer_chain_size+c->tcb_info_size, c->qe_identity_issuer_chain, c->qe_identity_issuer_chain_size); + memcpy(p+sizeof(sgx_ql_qve_collateral_t)+c->pck_crl_issuer_chain_size+c->root_ca_crl_size+c->pck_crl_size+c->tcb_info_issuer_chain_size+c->tcb_info_size+c->qe_identity_issuer_chain_size, c->qe_identity, c->qe_identity_size); + + return p; +} + + +int main(int argc, char** argv) +{ + if(argc != 2) + { + printf("Usage: %s \n", argv[0]); + return -1; + } + + std::string s = base64_decode(argv[1]); + ByteArray attestation; + std::transform(s.begin(), s.end(), std::back_inserter(attestation), + [](unsigned char c) -> char { return (uint8_t)c; }); + + + uint8_t* p_collateral=NULL; + uint32_t collateral_size=0; + quote3_error_t ret = tee_qv_get_collateral(attestation.data(), attestation.size(), &p_collateral, &collateral_size); + if(ret != SGX_QL_SUCCESS) + { + printf("error getting collateral: %x\n", ret); + return -1; + } + + uint8_t* serialized_collateral = serialize_collateral((sgx_ql_qve_collateral_t*)p_collateral); + if(serialized_collateral == NULL) + { + printf("error allocating collateral"); + return -1; + } + std::string b64collateral = base64_encode((const unsigned char*)serialized_collateral, collateral_size); + puts(b64collateral.c_str()); + + fprintf(stderr, "[DEBUG] collateral major version %hu minor version %hu\n", + ((sgx_ql_qve_collateral_t*)p_collateral)->major_version, + ((sgx_ql_qve_collateral_t*)p_collateral)->minor_version); + fprintf(stderr, "[DEBUG] collateral size: %d\n", collateral_size); + fprintf(stderr, "[DEBUG] b64collateral size: %ld\n", b64collateral.length()); + + ret = tee_qv_free_collateral(p_collateral); + if(ret != SGX_QL_SUCCESS) + { + printf("error freeing collateral: %x\n", ret); + return -1; + } + free(serialized_collateral); + + return 0; +} diff --git a/common/crypto/attestation-api/conversion/dcap/a2e.sh b/common/crypto/attestation-api/conversion/dcap/a2e.sh new file mode 100755 index 00000000..8f88c780 --- /dev/null +++ b/common/crypto/attestation-api/conversion/dcap/a2e.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -ex + +CUR_SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +. ${CUR_SCRIPT_PATH}/../tag_to_variable.sh + +function check_collateral_folder() +{ + if [[ -z "${COLLATERAL_FOLDER}" ]]; then + echo "COLLATERAL_FOLDER not set for DCAP conversion" + exit -1 + fi +} + +########################################################### +# b64quote_to_iasresponse +# input: quote as parameter +# output: ITA_RESPONSE variable +########################################################### +function b64quote_to_itaresponse() { + check_collateral_folder + + tag_to_variable "QUOTE_TAG" + + #get api key + API_KEY_FILEPATH="${COLLATERAL_FOLDER}/ita_api_key.txt" + test -f ${API_KEY_FILEPATH} || die "no api key file ${API_KEY_FILEPATH}" + API_KEY=$(cat $API_KEY_FILEPATH) + + #get verification report + QUOTE=$1 + # contact IAS to get the verification report + ITA_RESPONSE=$(curl -s -H "Accept: application/json" -H "Content-Type: application/json" -H "x-api-key:$API_KEY" -X POST -d '{"quote":"'$QUOTE'"}' https://api-poc-user1.project-amber-smas.com/appraisal/v1/attest ) +} + +########################################################### +# itaresponse_to_evidence +# input: ita response as parameter +# output: ITA_EVIDENCE variable +########################################################### +function itaresponse_to_evidence() { + tag_to_variable "ITA_TOKEN_TAG" + ITA_RESPONSE="$1" + ITA_TOKEN=$(echo $ITA_RESPONSE | jq ".token" -r) + JSON_ITA_RESPONSE=$(jq -c -n --arg tok "$ITA_TOKEN" '{'\"$ITA_TOKEN_TAG\"': $tok}') + #set output + ITA_EVIDENCE=$JSON_ITA_RESPONSE +} diff --git a/common/crypto/attestation-api/conversion/define_to_variable.sh b/common/crypto/attestation-api/conversion/define_to_variable.sh new file mode 100755 index 00000000..5f7bc125 --- /dev/null +++ b/common/crypto/attestation-api/conversion/define_to_variable.sh @@ -0,0 +1,18 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +########################################################### +# define_to_variable +# input: file with C #define, #define string as parameters +# output: variable named #define string +########################################################### +function define_to_variable() { + if [[ ! -f $1 ]]; then + echo "no file $1 to extract define" + exit -1 + fi + printf -v $2 "$(awk '/.*#define.* '$2' / { print $3 }' < $1 | sed 's/"//g')" +} diff --git a/common/crypto/attestation-api/conversion/enclave_to_mrenclave.sh b/common/crypto/attestation-api/conversion/enclave_to_mrenclave.sh new file mode 100755 index 00000000..1746d269 --- /dev/null +++ b/common/crypto/attestation-api/conversion/enclave_to_mrenclave.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +########################################################### +# enclave_to_mrenclave +# input: non-signed enclave file path, enclave configuration file as parameters +# output: MRENCLAVE variable +########################################################### +function enclave_to_mrenclave() { + if [[ ! -f $1 ]]; then + echo "missing enclave file path" + exit -1 + fi + if [[ ! -f $2 ]]; then + echo "missing enclave configuration file path" + exit -1 + fi + + TMP1=$(mktemp) + TMP2=$(mktemp) + sgx_sign gendata -enclave $1 -config $2 -out $TMP1 + dd if=$TMP1 bs=1 skip=188 of=$TMP2 count=32 + MRENCLAVE=$(hex -c $TMP2) +} diff --git a/common/crypto/attestation-api/conversion/epid/a2e.sh b/common/crypto/attestation-api/conversion/epid/a2e.sh new file mode 100755 index 00000000..aa919068 --- /dev/null +++ b/common/crypto/attestation-api/conversion/epid/a2e.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -ex + +function check_collateral_folder() +{ + if [[ -z "${COLLATERAL_FOLDER}" ]]; then + echo "COLLATERAL_FOLDER not set for EPID conversion" + exit -1 + fi +} + +########################################################### +# b64quote_to_iasresponse +# input: quote as parameter +# output: IAS_RESPONSE variable +########################################################### +function b64quote_to_iasresponse() { + check_collateral_folder + + #get api key + API_KEY_FILEPATH="${COLLATERAL_FOLDER}/api_key.txt" + test -f ${API_KEY_FILEPATH} || die "no api key file ${API_KEY_FILEPATH}" + API_KEY=$(cat $API_KEY_FILEPATH) + + #get verification report + QUOTE=$1 + # contact IAS to get the verification report + IAS_RESPONSE=$(curl -s -H "Content-Type: application/json" -H "Ocp-Apim-Subscription-Key:$API_KEY" -X POST -d '{"isvEnclaveQuote":"'$QUOTE'"}' https://api.trustedservices.intel.com/sgx/dev/attestation/v4/report -i) + # check status (as there may be multiple header, we rather check presence of relevant fields) + echo "$IAS_RESPONSE" | grep "X-IASReport-Signature" >/dev/null || die "IAS Response error" + echo "$IAS_RESPONSE" | grep "X-IASReport-Signing-Certificate" >/dev/null || die "IAS Response error" +} + +########################################################### +# iasresponse_to_evidence +# input: ias response as parameter +# output: IAS_EVIDENCE variable +########################################################### +function iasresponse_to_evidence() { + IAS_RESPONSE="$1" + UNTRUSTED_TIME_T=$(date +%s) + tag_to_variable "IAS_SIGNATURE_TAG" + tag_to_variable "IAS_CERTIFICATES_TAG" + tag_to_variable "IAS_REPORT_TAG" + tag_to_variable "UNTRUSTED_TIME_T_TAG" + + #encode relevant info in json format + IAS_SIGNATURE=$(echo "$IAS_RESPONSE" | grep -Po 'X-IASReport-Signature: \K[^ ]+' | tr -d '\r') + IAS_CERTIFICATES=$(echo "$IAS_RESPONSE" | grep -Po 'X-IASReport-Signing-Certificate: \K[^ ]+') + IAS_REPORT=$(echo "$IAS_RESPONSE" | grep -Po '{"id":[^ ]+') + JSON_IAS_RESPONSE=$(jq -c -n --arg sig "$IAS_SIGNATURE" --arg cer "$IAS_CERTIFICATES" --arg rep "$IAS_REPORT" --arg untrusted_time_t "$UNTRUSTED_TIME_T" '{'\"$IAS_SIGNATURE_TAG\"': $sig, '\"$IAS_CERTIFICATES_TAG\"': $cer, '\"$IAS_REPORT_TAG\"': $rep, '\"$UNTRUSTED_TIME_T_TAG\"': $untrusted_time_t}') + #set output + IAS_EVIDENCE=$JSON_IAS_RESPONSE +} diff --git a/common/crypto/attestation-api/conversion/simulated/a2e.sh b/common/crypto/attestation-api/conversion/simulated/a2e.sh new file mode 100755 index 00000000..6a878701 --- /dev/null +++ b/common/crypto/attestation-api/conversion/simulated/a2e.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +########################################################### +# simulated_to_evidence +# input: evidence as parameter +# output: SIMULATED_EVIDENCE variable +########################################################### +function simulated_to_evidence() { + SIMULATED_EVIDENCE=$1 +} diff --git a/common/crypto/attestation-api/conversion/tag_to_variable.sh b/common/crypto/attestation-api/conversion/tag_to_variable.sh new file mode 100644 index 00000000..d843eeef --- /dev/null +++ b/common/crypto/attestation-api/conversion/tag_to_variable.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Copyright 2024 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +set -e + +if [[ -z "${OAA_PATH}" ]]; then + echo "OAA_PATH not set" + exit -1 +fi + +CUR_SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +. ${CUR_SCRIPT_PATH}/define_to_variable.sh + +########################################################### +# get_tag_make_variable +# input: tag string (e.g, "TAG_X") as parameter +# output: tag string variable (e.g., TAG_X) +########################################################### +function tag_to_variable() { + TAGS_PATH="${OAA_PATH}/include/attestation_tags.h" + define_to_variable "$TAGS_PATH" "$1" +} + diff --git a/common/crypto/attestation-api/docker/Dockerfile b/common/crypto/attestation-api/docker/Dockerfile new file mode 100644 index 00000000..3b30a45c --- /dev/null +++ b/common/crypto/attestation-api/docker/Dockerfile @@ -0,0 +1,146 @@ +# ------------------------------------------------------------------------------ +# Copyright 2024 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ------------------------------------------------------------------------------ + +FROM ubuntu:22.04 +ARG UBUNTU_VERSION=22.04 +ARG UBUNTU_NAME=jammy + +ENV TERM=screen-256color + +RUN apt-get update \ + && apt-get install -y -q \ + build-essential \ + debhelper \ + git \ + libcurl4-openssl-dev \ + pkgconf \ + python-is-python3 \ + wget \ + zip + +RUN echo "deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu ${UBUNTU_NAME} main" | tee /etc/apt/sources.list.d/intel-sgx.list +RUN cat /etc/apt/sources.list.d/intel-sgx.list +RUN wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | apt-key add + +ENV DEBIAN_FRONTEND="noninteractive" +RUN apt-get update +RUN apt-get install -y -q \ + libboost-dev \ + libboost-system-dev \ + libboost-thread-dev \ + protobuf-c-compiler \ + libprotobuf-c-dev \ + protobuf-compiler + +ARG SGX=2.25 +ARG OPENSSL=3.0.14 +ARG SGXSSL=3.0_Rev4 + +RUN apt-get install -y \ + # We do not need daemons like AESMD as we run them on host (side-steps also + # issues with config of /etc/aesmd.conf like proxy ..). Without this option + # aesmd and lots of other plugsin are automatically pulled in. + # See SGX Installation notes and, in particular, linux/installer/docker/Dockerfile + # in linux-sgx git repo of sdk/psw source. + --no-install-recommends \ + libsgx-urts \ + libsgx-uae-service \ + libsgx-dcap-ql-dev \ + libsgx-dcap-quote-verify-dev + +# Install SGX SDK +WORKDIR /opt/intel +RUN SGX_SDK_BIN_REPO=https://download.01.org/intel-sgx/sgx-linux/${SGX}/distro/ubuntu${UBUNTU_VERSION}-server \ + && SGX_SDK_BIN_FILE=$(wget -P /tmp --delete-after --spider --recursive --level=1 --no-parent ${SGX_SDK_BIN_REPO} 2>&1 | perl -ne 'if (m|'${SGX_SDK_BIN_REPO}'/(sgx_linux_x64_sdk.*)|) { print "$1\n"; }') \ + && wget -q -P /tmp ${SGX_SDK_BIN_REPO}/${SGX_SDK_BIN_FILE} \ + && chmod +x /tmp/${SGX_SDK_BIN_FILE} \ + && echo -e "no\n/opt/intel" | /tmp/${SGX_SDK_BIN_FILE} \ + && rm /tmp/${SGX_SDK_BIN_FILE} + +ENV SGX_SDK=/opt/intel/sgxsdk + +# ----------------------------------------------------------------- +# LVI mitigations, needed to compile sgxssl, requires a +# recent version of binutils (>= 2.32). Ubuntu 18.04 only +# has 2.30 but Intel ships binary distro for 2.32.51.20190719 +# ----------------------------------------------------------------- +WORKDIR /opt/intel +RUN SGX_SDK_BINUTILS_REPO=https://download.01.org/intel-sgx/sgx-linux/${SGX} \ + && SGX_SDK_BINUTILS_FILE=$(wget -P /tmp --delete-after --spider --recursive --level=1 --no-parent ${SGX_SDK_BINUTILS_REPO} 2>&1 | perl -ne 'if (m|'${SGX_SDK_BINUTILS_REPO}'/(as.ld.objdump.*)|) { print "$1\n"; }') \ + && wget -q -P /tmp ${SGX_SDK_BINUTILS_REPO}/${SGX_SDK_BINUTILS_FILE} \ + && mkdir sgxsdk.extras \ + && cd sgxsdk.extras \ + && tar -zxf /tmp/${SGX_SDK_BINUTILS_FILE} \ + && rm /tmp/${SGX_SDK_BINUTILS_FILE} + +ENV PATH="/opt/intel/sgxsdk.extras/external/toolset/ubuntu${UBUNTU_VERSION}:${PATH}" + +# ----------------------------------------------------------------- +# SGXSSL +# Note that the SGX_MODE variable only determines the mode for +# running tests. We do not want the tests to run in HW mode here. +# This allows us to keep this image mode-agnostic. +# ----------------------------------------------------------------- +WORKDIR /tmp +RUN . /opt/intel/sgxsdk/environment \ + && git clone --depth 1 --branch ${SGXSSL} 'https://github.com/intel/intel-sgx-ssl.git' \ + && wget -q -P /tmp/intel-sgx-ssl/openssl_source https://www.openssl.org/source/openssl-${OPENSSL}.tar.gz \ + && cd /tmp/intel-sgx-ssl/Linux \ + && bash -c "make SKIP_INTELCPU_CHECK=TRUE SGX_MODE=SIM NO_THREADS=1 DESTDIR=/opt/intel/sgxssl VERBOSE=0 all &> /dev/null" \ + && make install \ + && make clean \ + && rm -rf /tmp/intel-sgx-ssl + +ENV SGX_SSL="/opt/intel/sgxssl" + +# ----------------------------------------------------------------- +# SGX DCAP Primitives +# ----------------------------------------------------------------- +RUN apt-get update +RUN apt-get install -y \ + basez \ + clang \ + cmake \ + curl \ + libsgx-dcap-default-qpl \ + #libsgx-dcap-default-qpl-dev adds libdcap_quoteprov.so and /usr/include/sgx_default_quote_provider.h + libsgx-dcap-default-qpl-dev \ + jq \ + libssl-dev \ + vim + +ARG DCAP=1.19 +ENV DCAP_PRIMITIVES=/tmp/SGXDataCenterAttestationPrimitives + +RUN git clone https://github.com/intel/SGXDataCenterAttestationPrimitives.git ${DCAP_PRIMITIVES} \ + && cd ${DCAP_PRIMITIVES}/QuoteVerification \ + && git checkout DCAP_${DCAP} \ + && git submodule update --init --recursive + +RUN cd ${DCAP_PRIMITIVES}/QuoteGeneration \ + && ./download_prebuilt.sh \ + && make GEN_STATIC=1 + +RUN cd ${DCAP_PRIMITIVES}/QuoteVerification/QVL/Src \ + && ./release -DBUILD_ENCLAVE=ON -DBUILD_TESTS=OFF ; ./release -DBUILD_ENCLAVE=ON -DBUILD_ATTESTATION_APP=OFF -DBUILD_TESTS=OFF + +RUN echo '{\n\ + "pccs_url": "https://localhost:8081/sgx/certification/v4/", \n\ + "collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v4/",\n\ + "use_secure_cert": false\n\ + }' > /etc/sgx_default_qcnl.conf + +WORKDIR /project diff --git a/common/crypto/attestation-api/docker/Makefile b/common/crypto/attestation-api/docker/Makefile new file mode 100644 index 00000000..cb63b2c7 --- /dev/null +++ b/common/crypto/attestation-api/docker/Makefile @@ -0,0 +1,9 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +DOCKER_BUILD_ARGS= + +build: + docker build ${DOCKER_BUILD_ARGS} --tag oaa-dev . + diff --git a/common/crypto/attestation-api/evidence/verify-dcap-direct-evidence.cpp b/common/crypto/attestation-api/evidence/verify-dcap-direct-evidence.cpp new file mode 100644 index 00000000..59a6086e --- /dev/null +++ b/common/crypto/attestation-api/evidence/verify-dcap-direct-evidence.cpp @@ -0,0 +1,268 @@ +/* + * Copyright 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "types/types.h" +#include "types/hex_string.h" +#include "error.h" +#include "logging.h" +#include "crypto/sha256.h" +#include "crypto/verify_dcap_direct/get_dcap_certificate.h" +#include "base64/base64.h" +#include "attestation_tags.h" + +#include "sgx_quote_3.h" +#include "SgxEcdsaAttestation/QuoteVerification.h" +#include "QuoteGeneration/quote_wrapper/common/inc/sgx_ql_lib_common.h" +#include "CertVerification/CertificateChain.h" + +// < JSON include +#define JSON_HAS_CPP_11 +#define JSON_NO_IO 1 +#include +#include "nlohmann/json.hpp" +using json = nlohmann::json; +// JSON include > + +#include "PckParser/CrlStore.h" +#include "../../AttestationCommons/include/Utils/TimeUtils.h" + +/******************************************************** + * Internal function to modify "in-place" the collateral + * data structure, so that pointers point to buffers + * appended to the structure + *******************************************************/ +void deserialize_collateral(uint8_t* p) +{ + sgx_ql_qve_collateral_t* c = (sgx_ql_qve_collateral_t*)p; + + c->pck_crl_issuer_chain = (char*)p + sizeof(sgx_ql_qve_collateral_t); + c->root_ca_crl = (char*)c->pck_crl_issuer_chain + c->pck_crl_issuer_chain_size; + c->pck_crl = (char*)c->root_ca_crl + c->root_ca_crl_size; + c->tcb_info_issuer_chain = (char*)c->pck_crl + c->pck_crl_size; + c->tcb_info = (char*)c->tcb_info_issuer_chain + c->tcb_info_issuer_chain_size; + c->qe_identity_issuer_chain = (char*)c->tcb_info + c->tcb_info_size; + c->qe_identity = (char*)c->qe_identity_issuer_chain + c->qe_identity_issuer_chain_size; +} + + +bool verify_dcap_direct_evidence(ByteArray& evidence, ByteArray& expected_statement, ByteArray& expected_code_id) +{ + ByteArray quote; + ByteArray certification_data; + uint32_t certification_data_size; + uint16_t certification_data_type; + ByteArray collateral; + time_t untrusted_time; + bool b; + Status qvl_status; + sgx_ql_qve_collateral_t* p_collateral; + + { + //parse evidence + json root; + std::string evidence_str((char*)evidence.data(), evidence.size()); + LOG_DEBUG("evidence: %s", evidence_str.c_str()); + CATCH(b, root = json::parse(evidence_str)); + COND2LOGERR(!b, "bad dcap evidence json"); + + //get attestation + std::string b64attestation_str; + std::string attestation_str; + CATCH(b, b64attestation_str = root[ATTESTATION_TAG].template get()); + COND2LOGERR(!b, "no attestation for dcap direct verification"); + attestation_str = base64_decode(b64attestation_str); + std::transform(attestation_str.begin(), attestation_str.end(), + std::back_inserter(quote), + [](unsigned char c) -> char { return (uint8_t)c; }); + + //get collateral + std::string b64collateral_str; + std::string collateral_str; + CATCH(b, b64collateral_str = root[COLLATERAL_TAG].template get()); + COND2LOGERR(!b, "no collateral for dcap direct verification"); + collateral_str = base64_decode(b64collateral_str); + std::transform(collateral_str.begin(), collateral_str.end(), + std::back_inserter(collateral), + [](unsigned char c) -> char { return (uint8_t)c; }); + //adjust the collateral structure pointers + deserialize_collateral(collateral.data()); + p_collateral = (sgx_ql_qve_collateral_t*)collateral.data(); + LOG_DEBUG("collateral version: %u\n", p_collateral->version); + LOG_DEBUG("collateral major %hu minor %hu\n", + p_collateral->major_version, p_collateral->minor_version); + LOG_DEBUG("collateral size %ld\n", collateral.size()); + + //get untrusted time for verification + unsigned long long timeull; + std::string time_str; + CATCH(b, time_str = root[UNTRUSTED_TIME_T_TAG].template get()); + COND2LOGERR(!b, "no untrusted-time for dcap direct verification"); + timeull = std::stoull(time_str); + COND2LOGERR(sizeof(timeull) != sizeof(time_t), "error: ull and time_t have different sizes" ); + untrusted_time = *((time_t*)(&timeull)); + LOG_DEBUG("untrusted time str: %s\n", time_str.c_str()); + LOG_DEBUG("untrusted time ull: %llu\n", timeull); + } + + //verify quote + { + qvl_status = sgxAttestationGetQECertificationDataSize(quote.data(), quote.size(), &certification_data_size); + COND2LOGERR(qvl_status != STATUS_OK, + "error certification data size: %x", qvl_status); + + certification_data.resize(certification_data_size); + + qvl_status = sgxAttestationGetQECertificationData( + quote.data(), quote.size(), + certification_data.size(), certification_data.data(), + &certification_data_type); + COND2LOGERR(qvl_status != STATUS_OK, + "error certification data: %x", qvl_status); + + std::string dcap_ca_certificate; + get_dcap_certificate(dcap_ca_certificate); + std::string certification_data_str(certification_data.begin(), certification_data.end()); + std::string root_ca_crl_str; + std::string pck_crl_str; + + // we check up to the last but one char (because, if hex form, it could be a space) + if(IsHex((const uint8_t*)p_collateral->root_ca_crl, p_collateral->root_ca_crl_size-1)) + { + root_ca_crl_str = + std::string(p_collateral->root_ca_crl, p_collateral->root_ca_crl_size); + } + else + { + char c = p_collateral->root_ca_crl[p_collateral->root_ca_crl_size-1]; + uint32_t size = p_collateral->root_ca_crl_size; + size -= (std::isspace(c) ? 1 : 0); + root_ca_crl_str = BinaryToHexString((const uint8_t*)p_collateral->root_ca_crl, size); + if(p_collateral->major_version == 3 && p_collateral->minor_version == 0) + LOG_WARNING("WARNING: root ca crl is not hex but collateral version is 3.0 (so it should be)\n"); + } + + // we check up to the last but one char (because, if hex form, it could be a space) + if(IsHex((const uint8_t*)p_collateral->pck_crl, p_collateral->pck_crl_size-1)) + { + pck_crl_str = + std::string(p_collateral->pck_crl, p_collateral->pck_crl_size); + } + else + { + char c = p_collateral->pck_crl[p_collateral->pck_crl_size-1]; + uint32_t size = p_collateral->pck_crl_size; + size -= (std::isspace(c) ? 1 : 0); + pck_crl_str = BinaryToHexString((const uint8_t*)p_collateral->pck_crl, p_collateral->pck_crl_size); + if(p_collateral->major_version == 3 && p_collateral->minor_version == 0) + LOG_WARNING("WARNING: pck crl is not hex but collateral version is 3.0 (so it should be)\n"); + } + + const std::array crls{{ + root_ca_crl_str.c_str(), pck_crl_str.c_str()}}; + + LOG_DEBUG("dcap_ca_certificate: %s\n", dcap_ca_certificate.c_str()); + LOG_DEBUG("Certification data type: %hu\n", certification_data_type); + LOG_DEBUG("Certification data: %s\n", certification_data_str.c_str()); + LOG_DEBUG("root_ca_crl_str (%ld): %s\n", root_ca_crl_str.length(), root_ca_crl_str.c_str()); + LOG_DEBUG("pck_crl_str(%ld): %s\n", pck_crl_str.length(), pck_crl_str.c_str()); + + { + // debug CRLS + time_t currentTime = intel::sgx::dcap::getCurrentTime((const time_t*)&untrusted_time); + intel::sgx::dcap::pckparser::CrlStore rootCaCrl; + intel::sgx::dcap::pckparser::CrlStore intermediateCrl; + COND2LOGERR(!rootCaCrl.parse(crls[0]), "error parsing rootcacrsl"); + COND2LOGERR(!intermediateCrl.parse(crls[1]), "error parsing intermediateCrl"); + LOG_DEBUG("rootCaCrl.getValidity().notBeforeTime: %llu\n", *((unsigned long long*)(&(rootCaCrl.getValidity().notBeforeTime)))); + LOG_DEBUG("rootCaCrl.getValidity().notAfterTime: %llu\n", *((unsigned long long*)(&(rootCaCrl.getValidity().notAfterTime)))); + LOG_DEBUG("currentTime: %llu\n", *((unsigned long long*)¤tTime)); + + LOG_DEBUG("intermediateCrl.getValidity().notBeforeTime: %llu\n", *((unsigned long long*)(&(intermediateCrl.getValidity().notBeforeTime)))); + LOG_DEBUG("intermediateCrl.getValidity().notAfterTime: %llu\n", *((unsigned long long*)(&(intermediateCrl.getValidity().notAfterTime)))); + } + + qvl_status = sgxAttestationVerifyPCKCertificate( + certification_data_str.c_str(), + crls.data(), + dcap_ca_certificate.c_str(), + &untrusted_time); + COND2LOGERR(qvl_status != STATUS_OK, + "error PCK certificate verification: %x", qvl_status); + + qvl_status = sgxAttestationVerifyTCBInfo( + p_collateral->tcb_info, + p_collateral->tcb_info_issuer_chain, + crls[0], + dcap_ca_certificate.c_str(), + &untrusted_time); + COND2LOGERR(qvl_status != STATUS_OK, + "error TCB info verification: %x", qvl_status); + + qvl_status = sgxAttestationVerifyEnclaveIdentity( + p_collateral->qe_identity, + p_collateral->qe_identity_issuer_chain, + crls[0], + dcap_ca_certificate.c_str(), + &untrusted_time); + COND2LOGERR(qvl_status != STATUS_OK, + "error QE identity verification: %x", qvl_status); + + intel::sgx::dcap::CertificateChain chain; + qvl_status = chain.parse((const char*)certification_data.data()); + COND2LOGERR(qvl_status != STATUS_OK, + "error parsing certification data: %x", qvl_status); + + qvl_status = sgxAttestationVerifyQuote( + quote.data(), + quote.size(), + chain.getPckCert()->getPem().c_str(), + crls[1], + p_collateral->tcb_info, + p_collateral->qe_identity); + COND2LOGERR( + //these checks are mostly the verification policy + //TODO: define and implement better strategy for verification + qvl_status != STATUS_OK && + qvl_status != STATUS_TCB_OUT_OF_DATE, + "error quote verification: %x", qvl_status); + } + + // verify code id and statement + { + //prepare code id + sgx_quote3_t* q = (sgx_quote3_t*)quote.data(); + std::string code_id = BinaryToHexString((const uint8_t*)&q->report_body.mr_enclave, sizeof(sgx_measurement_t)); + std::string expected_hex_id((char*)expected_code_id.data(), expected_code_id.size()); + LOG_DEBUG("quote version: %hu\n", q->header.version); + LOG_DEBUG("Code id in quote: %s\n", code_id.c_str()); + LOG_DEBUG("Expected code id: %s\n", expected_hex_id.c_str()); + + //prepare statements + std::string hex_report_data = BinaryToHexString((const uint8_t*)&q->report_body.report_data, sizeof(sgx_report_data_t)); + ByteArray hash; + COND2ERR(false == SHA256(expected_statement, hash)); + std::string expected_hex_report_data_str = ByteArrayToHexEncodedString(hash); + expected_hex_report_data_str.append(expected_hex_report_data_str.length(), '0'); + LOG_DEBUG("report data: %s\n", hex_report_data.c_str()); + LOG_DEBUG("expected report data: %s\n", expected_hex_report_data_str.c_str()); + + // code check + COND2LOGERR(0 != code_id.compare(expected_hex_id), "expected code id mismatch"); + + //statement check + COND2LOGERR(0 != hex_report_data.compare(expected_hex_report_data_str), "expected statement mismatch"); + } + + return true; + +err: + return false; +} diff --git a/common/crypto/attestation-api/evidence/verify-dcap-direct-evidence.h b/common/crypto/attestation-api/evidence/verify-dcap-direct-evidence.h new file mode 100644 index 00000000..03174ce4 --- /dev/null +++ b/common/crypto/attestation-api/evidence/verify-dcap-direct-evidence.h @@ -0,0 +1,7 @@ +/* + * Copyright 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +bool verify_dcap_direct_evidence(ByteArray& evidence, ByteArray& expected_statement, ByteArray& expected_code_id); diff --git a/common/crypto/attestation-api/evidence/verify-dcap-evidence.cpp b/common/crypto/attestation-api/evidence/verify-dcap-evidence.cpp new file mode 100644 index 00000000..de730925 --- /dev/null +++ b/common/crypto/attestation-api/evidence/verify-dcap-evidence.cpp @@ -0,0 +1,104 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "types/types.h" +#include "crypto/verify_ita_token/verify-token.h" +#include "error.h" +#include "logging.h" +#include "crypto/sha256.h" +#include "attestation_tags.h" + +// < JSON include +#define JSON_HAS_CPP_11 +#define JSON_NO_IO 1 +#include +#include "nlohmann/json.hpp" +using json = nlohmann::json; +// JSON include > + + +bool verify_dcap_evidence(ByteArray& evidence, ByteArray& expected_statement, ByteArray& expected_code_id) +{ + std::string evidence_str((char*)evidence.data(), evidence.size()); + std::string ita_token_str; + std::string ita_payload_str; + verify_status_t vs; + bool b; + + LOG_DEBUG("evidence: %s", evidence_str.c_str()); + + // get ITA token + { + //parse evidence + json root; + CATCH(b, root = json::parse(evidence_str)); + COND2LOGERR(!b, "bad dcap evidence json"); + + //get ita token + CATCH(b, ita_token_str = root[ITA_TOKEN_TAG].template get()); + COND2LOGERR(!b, "no ita token in dcap verification"); + LOG_DEBUG("ita token: %s\n", ita_token_str.c_str()); + } + + // verify ITA token signature + { + //get token payload + b = get_token_payload(ita_token_str, ita_payload_str); + COND2LOGERR(!b, "cannot get ita payload"); + + //verify ita token + vs = verify_ita_token_signature(ita_token_str); + COND2LOGERR(vs == VERIFY_FAILURE, "token verification failed"); + } + + // verify mrenclave and statement + { + json root; + CATCH(b, root = json::parse(ita_payload_str)); + COND2LOGERR(!b, "bad ita payload json"); + + //prepare external mrenclave + std::string sgx_mrenclave; + CATCH(b, sgx_mrenclave = root["sgx_mrenclave"].template get()); + COND2LOGERR(!b, "no sgx_mrenclave in ita payload"); + COND2LOGERR(sgx_mrenclave.length() == 0, "sgx_mrenclave is empty"); + std::transform(sgx_mrenclave.begin(), sgx_mrenclave.end(), sgx_mrenclave.begin(), ::toupper); + LOG_DEBUG("sgx_mrenclave: %s\n", sgx_mrenclave.c_str()); + + //prepare expected mrenclave + std::string expected_hex_id((char*)expected_code_id.data(), expected_code_id.size()); + std::transform(expected_hex_id.begin(), expected_hex_id.end(), expected_hex_id.begin(), ::toupper); + + //check mrenclaves + COND2LOGERR(0 != sgx_mrenclave.compare(expected_hex_id), + "expected code id %s mismatch %s", expected_hex_id.c_str(), sgx_mrenclave.c_str()); + + //prepare external report data + std::string sgx_report_data; + CATCH(b, sgx_report_data = root["sgx_report_data"].template get()); + COND2LOGERR(!b, "no sgx_report_data in ita payload"); + COND2LOGERR(sgx_report_data.length() == 0, "sgx_report_data is empty"); + std::transform(sgx_report_data.begin(), sgx_report_data.end(), sgx_report_data.begin(), ::toupper); + LOG_DEBUG("sgx_report_data: %s\n", sgx_report_data.c_str()); + + //prepare expected report data + ByteArray hash; + std::string expected_hex_report_data_str; + COND2ERR(false == SHA256(expected_statement, hash)); + expected_hex_report_data_str = ByteArrayToHexEncodedString(hash); + expected_hex_report_data_str.append(expected_hex_report_data_str.length(), '0'); //double length with 0s + std::transform(expected_hex_report_data_str.begin(), expected_hex_report_data_str.end(), expected_hex_report_data_str.begin(), ::toupper); + + COND2LOGERR(0 != sgx_report_data.compare(expected_hex_report_data_str), + "expected statement %s mismatch %s", expected_hex_report_data_str.c_str(), sgx_report_data.c_str()); + } + + return true; + +err: + return false; +} diff --git a/common/crypto/attestation-api/evidence/verify-dcap-evidence.h b/common/crypto/attestation-api/evidence/verify-dcap-evidence.h new file mode 100644 index 00000000..a0f628b6 --- /dev/null +++ b/common/crypto/attestation-api/evidence/verify-dcap-evidence.h @@ -0,0 +1,7 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +bool verify_dcap_evidence(ByteArray& evidence, ByteArray& expected_statement, ByteArray& expected_code_id); diff --git a/common/crypto/attestation-api/evidence/verify-evidence.cpp b/common/crypto/attestation-api/evidence/verify-evidence.cpp new file mode 100644 index 00000000..91875468 --- /dev/null +++ b/common/crypto/attestation-api/evidence/verify-evidence.cpp @@ -0,0 +1,88 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "verify-evidence.h" +#include +#include +#include "attestation_tags.h" +#include "error.h" +#include "logging.h" +#include "types/types.h" +#include "verify-ias-evidence.h" +#include "verify-dcap-evidence.h" +#include "verify-dcap-direct-evidence.h" + +// < JSON include +#define JSON_HAS_CPP_11 +#define JSON_NO_IO 1 +#include +#include "nlohmann/json.hpp" +using json = nlohmann::json; +// JSON include > + +bool verify_evidence(uint8_t* evidence, + uint32_t evidence_length, + uint8_t* expected_statement, + uint32_t expected_statement_length, + uint8_t* expected_code_id, + uint32_t expected_code_id_length) +{ + bool ret = false; + json root; + std::string attestation_type; + std::string evidence_field; + std::string evidence_str((char*)evidence, evidence_length); + ByteArray ba_expected_statement( + expected_statement, expected_statement + expected_statement_length); + ByteArray ba_expected_code_id(expected_code_id, expected_code_id + expected_code_id_length); + + CATCH(ret, root = json::parse(evidence_str)); + COND2LOGERR(!ret, "invalid evidence json"); + + CATCH(ret, attestation_type = root[ATTESTATION_TYPE_TAG].template get()); + COND2LOGERR(!ret, "invalid (or missing) attestation type field"); + + CATCH(ret, evidence_field = root[EVIDENCE_TAG].template get()); + COND2LOGERR(!ret, "invalid evidence field"); + + if (0 == attestation_type.compare(SIMULATED_TYPE_TAG)) + { + // nothing to check + ret = true; + } + + if (0 == attestation_type.compare(EPID_LINKABLE_TYPE_TAG) || + 0 == attestation_type.compare(EPID_UNLINKABLE_TYPE_TAG)) + { + ByteArray ba_evidence(evidence_field.begin(), evidence_field.end()); + bool b = verify_ias_evidence(ba_evidence, ba_expected_statement, ba_expected_code_id); + COND2ERR(b == false); + ret = true; + } + + if (0 == attestation_type.compare(DCAP_SGX_TYPE_TAG)) + { + ByteArray ba_evidence(evidence_field.begin(), evidence_field.end()); + bool b = verify_dcap_evidence(ba_evidence, ba_expected_statement, ba_expected_code_id); + COND2ERR(b == false); + ret = true; + } + + if (0 == attestation_type.compare(DCAP_DIRECT_SGX_TYPE_TAG)) + { + ByteArray ba_evidence(evidence_field.begin(), evidence_field.end()); + bool b = verify_dcap_direct_evidence(ba_evidence, ba_expected_statement, ba_expected_code_id); + COND2ERR(b == false); + ret = true; + } + + COND2LOGERR(ret == false, "bad attestation type: %s", attestation_type.c_str()); + + return true; + +err: + return false; +} diff --git a/common/crypto/attestation-api/evidence/verify-ias-evidence.cpp b/common/crypto/attestation-api/evidence/verify-ias-evidence.cpp new file mode 100644 index 00000000..e49fe9d1 --- /dev/null +++ b/common/crypto/attestation-api/evidence/verify-ias-evidence.cpp @@ -0,0 +1,240 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "error.h" +#include "logging.h" +#include "base64/base64.h" +#include "crypto/verify_ias_report/verify-report.h" +#include "types/types.h" +#include "crypto/sha256.h" +#include "attestation_tags.h" + +// < JSON include +#define JSON_HAS_CPP_11 +#define JSON_NO_IO 1 +#include +#include "nlohmann/json.hpp" +using json = nlohmann::json; +// JSON include > + +static bool unwrap_ias_evidence(const std::string& evidence_str, + std::string& ias_signature, + std::string& ias_certificates, + std::string& ias_report, + std::string& untrusted_time_str) +{ + json root; + bool ret; + + CATCH(ret, root = json::parse(evidence_str)); + COND2LOGERR(!ret, "invalid ias evidence json"); + + CATCH(ret, ias_signature = root[IAS_SIGNATURE_TAG].template get()); + COND2LOGERR(!ret, "invalid ias_signature field"); + + CATCH(ret, ias_certificates = root[IAS_CERTIFICATES_TAG].template get()); + COND2LOGERR(!ret, "invalid ias_certificates field"); + + CATCH(ret, ias_report = root[IAS_REPORT_TAG].template get()); + COND2LOGERR(!ret, "invalid ias_report field"); + + CATCH(ret, untrusted_time_str = root[UNTRUSTED_TIME_T_TAG].template get()); + COND2LOGERR(!ret, "invalid untrusted time field"); + + return true; + +err: + LOG_DEBUG("ias evidence: %s\n", evidence_str.c_str()); + return false; +} + +static void replace_all_substrings( + std::string& s, const std::string& substring, const std::string& replace_with) +{ + size_t pos = 0; + while (1) + { + pos = s.find(substring, pos); + if (pos == std::string::npos) + break; + + s.replace(pos, substring.length(), replace_with); + } +} + +static void url_decode_ias_certificate(std::string& s) +{ + replace_all_substrings(s, "%20", " "); + replace_all_substrings(s, "%0A", "\n"); + replace_all_substrings(s, "%2B", "+"); + replace_all_substrings(s, "%3D", "="); + replace_all_substrings(s, "%2F", "/"); +} + +static bool split_certificates( + std::string& ias_certificates, std::vector& ias_certificate_vector) +{ + // ias certificates should have 2 certificates "-----BEGIN CERTIFICATE----- [...] -----END + // CERTIFICATE-----\n" + std::string cert_start("-----BEGIN CERTIFICATE-----"); + std::string cert_end("-----END CERTIFICATE-----\n"); + size_t cur = 0, start = 0, end = 0; + + ias_certificate_vector.clear(); + + url_decode_ias_certificate(ias_certificates); + + while (1) + { + start = ias_certificates.find(cert_start, cur); + if (start == std::string::npos) + { + break; + } + + end = ias_certificates.find(cert_end, cur); + if (end == std::string::npos) + { + break; + } + end += cert_end.length(); + + ias_certificate_vector.push_back(ias_certificates.substr(start, end)); + cur = end; + } + + COND2LOGERR(ias_certificate_vector.size() != 2, "unexpected number of IAS certificates"); + + return true; + +err: + return false; +} + +static bool extract_hex_from_report( + const std::string& ias_report, size_t offset, size_t size, std::string& hex) +{ + std::string b64quote; + ByteArray bin_quote; + ByteArray ba; + bool ret = false; + json root; + + CATCH(ret, root = json::parse(ias_report)); + COND2LOGERR(!ret, "invalid ias_report json"); + + CATCH(ret, b64quote = root["isvEnclaveQuoteBody"].template get()); + COND2LOGERR(!ret, "invalid isvEnclaveQuoteBody field"); + + bin_quote = Base64EncodedStringToByteArray(b64quote); + COND2LOGERR(bin_quote.size() != offsetof(sgx_quote_t, signature_len), "unexpected quote size"); + ba = ByteArray(bin_quote.data() + offset, bin_quote.data() + offset + size); + hex = ByteArrayToHexEncodedString(ba); + + return true; + +err: + return false; +} + +bool verify_ias_evidence( + ByteArray& evidence, ByteArray& expected_statement, ByteArray& expected_code_id) +{ + time_t untrusted_time = 0; + std::string evidence_str((char*)evidence.data(), evidence.size()); + std::string expected_hex_id((char*)expected_code_id.data(), expected_code_id.size()); + + std::string ias_signature, ias_certificates, ias_report, untrusted_time_str; + std::vector ias_certificate_vector; + + // get evidence data + COND2ERR( + false == unwrap_ias_evidence(evidence_str, ias_signature, ias_certificates, ias_report, untrusted_time_str)); + + // split certs + COND2ERR(false == split_certificates(ias_certificates, ias_certificate_vector)); + + { + //get time + unsigned long long timeull = std::stoull(untrusted_time_str); + COND2LOGERR(sizeof(timeull) != sizeof(time_t), "error: ull and time_t have different sizes" ); + untrusted_time = *((time_t*)(&timeull)); + LOG_DEBUG("untrusted time: %llu\n", timeull); + } + + { + // verify report status + const unsigned int flags = QSF_ACCEPT_GROUP_OUT_OF_DATE | QSF_ACCEPT_CONFIGURATION_NEEDED | + QSF_ACCEPT_SW_HARDENING_NEEDED | + QSF_ACCEPT_CONFIGURATION_AND_SW_HARDENING_NEEDED; + COND2LOGERR(VERIFY_SUCCESS != + verify_enclave_quote_status(ias_report.c_str(), ias_report.length(), flags), + "invalid quote status"); + } + + { + // check root cert + const int root_certificate_index = 1; + verify_status_t v; + bool ret; + CATCH(ret, v = verify_ias_certificate_chain(ias_certificate_vector[root_certificate_index].c_str(), untrusted_time)); + COND2LOGERR(!ret, "verify root cert exception"); + COND2LOGERR(VERIFY_SUCCESS != v, "invalid root certificate"); + } + + { + // check signing cert + const int signing_certificate_index = 0; + verify_status_t v; + bool ret; + CATCH(ret, v = verify_ias_certificate_chain(ias_certificate_vector[signing_certificate_index].c_str(), untrusted_time)); + COND2LOGERR(!ret, "verify intermediate cert exception"); + COND2LOGERR(VERIFY_SUCCESS != v, "invalid intermediate certificate"); + + // check signature + COND2LOGERR( + VERIFY_SUCCESS != verify_ias_report_signature( + ias_certificate_vector[signing_certificate_index].c_str(), + ias_report.c_str(), ias_report.length(), + (char*)ias_signature.c_str(), ias_signature.length()), + "invalid report signature"); + } + + { + // check code id + std::string hex_id; + COND2ERR(false == + extract_hex_from_report(ias_report, + offsetof(sgx_quote_t, report_body) + offsetof(sgx_report_body_t, mr_enclave), + sizeof(sgx_measurement_t), hex_id)); + LOG_DEBUG("code id comparision: found '%s' (len=%ld) / expected '%s' (len=%ld)", + hex_id.c_str(), hex_id.length(), expected_hex_id.c_str(), expected_hex_id.length()); + COND2LOGERR(0 != hex_id.compare(expected_hex_id), "expected code id mismatch"); + } + + { + // check report data + std::string hex_report_data, expected_hex_report_data_str; + ByteArray hash; + COND2ERR(false == + extract_hex_from_report(ias_report, + offsetof(sgx_quote_t, report_body) + offsetof(sgx_report_body_t, report_data), + sizeof(sgx_report_data_t), hex_report_data)); + COND2ERR(false == SHA256(expected_statement, hash)); + expected_hex_report_data_str = ByteArrayToHexEncodedString(hash); + expected_hex_report_data_str.append(expected_hex_report_data_str.length(), '0'); + COND2LOGERR(0 != hex_report_data.compare(expected_hex_report_data_str), + "expected statement mismatch"); + } + + // TODO: check attributes of attestation (e.g., DEBUG flag disabled in release mode) + + return true; + +err: + return false; +} + diff --git a/common/crypto/attestation-api/evidence/verify-ias-evidence.h b/common/crypto/attestation-api/evidence/verify-ias-evidence.h new file mode 100644 index 00000000..52debdbe --- /dev/null +++ b/common/crypto/attestation-api/evidence/verify-ias-evidence.h @@ -0,0 +1,7 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +bool verify_ias_evidence(ByteArray& evidence, ByteArray& expected_statement, ByteArray& expected_code_id); diff --git a/common/crypto/attestation-api/include/attestation.h b/common/crypto/attestation-api/include/attestation.h new file mode 100644 index 00000000..0cc9d0f0 --- /dev/null +++ b/common/crypto/attestation-api/include/attestation.h @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +bool init_attestation(uint8_t* params, uint32_t params_length); + +bool get_attestation(uint8_t* statement, + uint32_t statement_length, + uint8_t* attestation, + uint32_t attestation_max_length, + uint32_t* attestation_length); diff --git a/common/crypto/attestation-api/include/attestation_tags.h b/common/crypto/attestation-api/include/attestation_tags.h new file mode 100644 index 00000000..5a5ffe40 --- /dev/null +++ b/common/crypto/attestation-api/include/attestation_tags.h @@ -0,0 +1,34 @@ +/* + * Copyright 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#define ATTESTATION_TYPE_TAG "attestation_type" + +#define SIMULATED_TYPE_TAG "simulated" + +#define EPID_PREFIX_TAG "epid" +#define EPID_LINKABLE_TYPE_TAG "epid-linkable" +#define EPID_UNLINKABLE_TYPE_TAG "epid-unlinkable" +#define SPID_TAG "hex_spid" +#define SIG_RL_TAG "sig_rl" +#define IAS_SIGNATURE_TAG "ias_signature" +#define IAS_CERTIFICATES_TAG "ias_certificates" +#define IAS_REPORT_TAG "ias_report" + +#define ATTESTATION_TAG "attestation" +#define QUOTE_TAG "quote" +#define EVIDENCE_TAG "evidence" + +#define DCAP_PREFIX_TAG "dcap" +#define DCAP_DIRECT_PREFIX_TAG "dcap-direct" + +#define DCAP_SGX_TYPE_TAG "dcap-sgx" +#define DCAP_DIRECT_SGX_TYPE_TAG "dcap-direct-sgx" + +#define ITA_TOKEN_TAG "ita-token" +#define COLLATERAL_TAG "collateral" +#define UNTRUSTED_TIME_T_TAG "untrusted-time-t" diff --git a/common/crypto/attestation-api/include/verify-evidence.h b/common/crypto/attestation-api/include/verify-evidence.h new file mode 100644 index 00000000..81caa4c8 --- /dev/null +++ b/common/crypto/attestation-api/include/verify-evidence.h @@ -0,0 +1,24 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool verify_evidence(uint8_t* evidence, + uint32_t evidence_length, + uint8_t* expected_statement, + uint32_t expected_statement_length, + uint8_t* expected_code_id, + uint32_t expected_code_id_length); + +#ifdef __cplusplus +} +#endif diff --git a/common/crypto/attestation-api/ocalls/attestation-ocalls.c b/common/crypto/attestation-api/ocalls/attestation-ocalls.c new file mode 100644 index 00000000..88a4eb76 --- /dev/null +++ b/common/crypto/attestation-api/ocalls/attestation-ocalls.c @@ -0,0 +1,99 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "error.h" +#include "logging.h" +#include "sgx_quote.h" +#include "sgx_dcap_ql_wrapper.h" + +void ocall_init_quote(uint8_t* target, uint32_t target_len, uint8_t* egid, uint32_t egid_len, uint32_t* sgxret) +{ + COND2LOGERR(target == NULL, "null sgx target info"); + + if(egid != NULL) //this means: EPID + { + int ret = sgx_init_quote((sgx_target_info_t*)target, (sgx_epid_group_id_t*)egid); + *sgxret = ret; + COND2LOGERR(ret != SGX_SUCCESS, "error sgx_init_quote: %x", ret); + } + else // no egid means: DCAP + { + quote3_error_t qe3_ret; + qe3_ret = sgx_qe_get_target_info((sgx_target_info_t*)target); + *sgxret = qe3_ret; + COND2LOGERR(qe3_ret != SGX_QL_SUCCESS, "error sgx_qe_get_target_info: %x", qe3_ret); + } + return; + +err: + ; // nothing to do +} + +void ocall_get_quote(uint8_t* spid, + uint32_t spid_len, + uint8_t* sig_rl, + uint32_t sig_rl_len, + uint32_t sign_type, + uint8_t* report, + uint32_t report_len, + uint8_t* quote, + uint32_t max_quote_len, + uint32_t* actual_quote_len, + uint32_t* sgxret) +{ + if(spid != NULL) // this means: EPID + { + int ret; + uint32_t required_quote_size = 0; + ret = sgx_calc_quote_size(sig_rl, sig_rl_len, &required_quote_size); + *sgxret = ret; + COND2LOGERR(ret != SGX_SUCCESS, "error sgx_calc_quote_size: %x", ret); + COND2LOGERR( + required_quote_size > max_quote_len, + "error not enough buffer for quote: required %d max %d", + required_quote_size, max_quote_len); + + ret = sgx_get_quote( + (const sgx_report_t*)report, + (sgx_quote_sign_type_t)sign_type, + (const sgx_spid_t*)spid, // spid + NULL, // nonce + sig_rl, // sig_rl + sig_rl_len, // sig_rl_size + NULL, // p_qe_report + (sgx_quote_t*)quote, required_quote_size); + *sgxret = ret; + COND2LOGERR(ret != SGX_SUCCESS, "error sgx_get_quote: %x", ret); + *actual_quote_len = required_quote_size; + } + else // this means DCAP + { + quote3_error_t qe3_ret; + uint32_t required_quote_size = 0; + qe3_ret = sgx_qe_get_quote_size(&required_quote_size); + *sgxret = qe3_ret; + COND2LOGERR(qe3_ret != SGX_QL_SUCCESS, "error sgx_qe_get_quote_size: %x", qe3_ret); + COND2LOGERR( + required_quote_size > max_quote_len, + "error not enough buffer for quote: required %d max %d", + required_quote_size, max_quote_len); + + qe3_ret = sgx_qe_get_quote( + (const sgx_report_t*)report, + required_quote_size, + quote); + *sgxret = qe3_ret; + COND2LOGERR(qe3_ret != SGX_QL_SUCCESS, "error sgx_qe_get_quote: %x", qe3_ret); + *actual_quote_len = required_quote_size; + } + + return; + +err: + // if anything wrong, no quote + *actual_quote_len = 0; +} diff --git a/common/crypto/attestation-api/ocalls/attestation-ocalls.edl b/common/crypto/attestation-api/ocalls/attestation-ocalls.edl new file mode 100644 index 00000000..1cb40f10 --- /dev/null +++ b/common/crypto/attestation-api/ocalls/attestation-ocalls.edl @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +enclave +{ + untrusted + { + void ocall_init_quote( + [out, size=target_len] uint8_t *target, uint32_t target_len, + [out, size=egid_len] uint8_t *egid, uint32_t egid_len, + [out, count=1] uint32_t *ret); + + void ocall_get_quote( + [in, size=spid_len] uint8_t *spid, uint32_t spid_len, + [in, size=sig_rl_len] uint8_t *sig_rl, uint32_t sig_rl_len, + uint32_t sign_type, + [in, size=report_len] uint8_t *report, uint32_t report_len, + [out, size=max_quote_len] uint8_t *quote, uint32_t max_quote_len, + [out] uint32_t *actual_quote_len, + [out, count=1] uint32_t *ret); + }; +}; diff --git a/common/crypto/attestation-api/test/CMakeLists.txt b/common/crypto/attestation-api/test/CMakeLists.txt new file mode 100644 index 00000000..3965ac0c --- /dev/null +++ b/common/crypto/attestation-api/test/CMakeLists.txt @@ -0,0 +1,150 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +# pkg_check_modules needed to set OPENSSL_LDFLAGS +find_package(PkgConfig REQUIRED) +pkg_check_modules (OPENSSL REQUIRED openssl>=1.1.0g) + +# Put test artifacts under /tests subdirectory +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests) + +################################################################################################## +## Verify Evidence test app: +## this application tests evidence from input files +################################################################################################## + +SET(VERIFY_EVIDENCE_APP verify_evidence_app) + +ADD_EXECUTABLE(${VERIFY_EVIDENCE_APP} + ${VERIFY_EVIDENCE_APP}/main.cpp + ${VERIFY_EVIDENCE_APP}/test.cpp + common/test-utils.cpp + ) + +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP} BEFORE PRIVATE "../common") # OAA common +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP} PRIVATE "../include") +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP} PRIVATE "common") # test common +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP} PRIVATE ${LOGGING_UNTRUSTED_INCLUDE_PATH}) +TARGET_LINK_LIBRARIES(${VERIFY_EVIDENCE_APP} ${LOGGING_UNTRUSTED_LIB}) +# Link the untrusted test application against the untrusted library and openssl +TARGET_LINK_LIBRARIES(${VERIFY_EVIDENCE_APP} + # we assume that the libraries are located one level up + "-L${CMAKE_CURRENT_BINARY_DIR}/.." + "-Wl,--start-group" ${OPENSSL_LDFLAGS} "-lu-one-attestation" "-Wl,--end-group" + ) + +################################################################################################### +## Attestation app: +## this application performs a sim/hw attestation from input files and writes output on file +################################################################################################### + +SET(GET_ATTESTATION_APP "get_attestation_app") + +ADD_SUBDIRECTORY(${GET_ATTESTATION_APP}/enclave) + +INCLUDE ("${GET_ATTESTATION_APP}/enclave/CMakeVariables.txt") + +# ENCLAVE_EDL is defined in the enclave subdirectory +SGX_EDGE_UNTRUSTED(${ENCLAVE_EDL} ENCLAVE_EDGE_SOURCES) + +ADD_EXECUTABLE(${GET_ATTESTATION_APP} + ${GET_ATTESTATION_APP}/app/main.cpp + common/test-utils.cpp + ${ENCLAVE_EDGE_SOURCES}) + +# Make sure the enclave builds before the test app that links it +ADD_DEPENDENCIES(${GET_ATTESTATION_APP} test_enclave) + +TARGET_INCLUDE_DIRECTORIES(${GET_ATTESTATION_APP} PRIVATE "$ENV{SGX_SDK}/include") +TARGET_INCLUDE_DIRECTORIES(${GET_ATTESTATION_APP} PRIVATE "$ENV{SGX_SSL}/include") +TARGET_INCLUDE_DIRECTORIES(${GET_ATTESTATION_APP} BEFORE PRIVATE "../common") # OAA common +TARGET_INCLUDE_DIRECTORIES(${GET_ATTESTATION_APP} PRIVATE ${LOGGING_UNTRUSTED_INCLUDE_PATH}) +TARGET_INCLUDE_DIRECTORIES(${GET_ATTESTATION_APP} PRIVATE "common") # test common + +TARGET_LINK_LIBRARIES(${GET_ATTESTATION_APP} -Wl,-L,$ENV{SGX_SDK}/lib64) +TARGET_LINK_LIBRARIES(${GET_ATTESTATION_APP} -Wl,-L,$ENV{SGX_SSL}/lib64) +TARGET_LINK_LIBRARIES(${GET_ATTESTATION_APP} + # we assume that the libraries are located one level up + "-L${CMAKE_CURRENT_BINARY_DIR}/.." + "-lu-one-attestation" + ) +TARGET_LINK_LIBRARIES(${GET_ATTESTATION_APP} ${URTS_LIBRARY_NAME} ${UAE_SERVICE_LIBRARY_NAME}) +TARGET_LINK_LIBRARIES(${GET_ATTESTATION_APP} sgx_usgxssl ${SGX_EPID_LIB} sgx_dcap_ql) +TARGET_LINK_LIBRARIES(${GET_ATTESTATION_APP} ${LOGGING_UNTRUSTED_LIB}) + +## dcap_quoteprov necessary for dcap logging +#TARGET_LINK_LIBRARIES(${GET_ATTESTATION_APP} dcap_quoteprov) + +################################################################################################## +## Verify Evidence test enclave app: +## this application tests evidence from input files +################################################################################################## + +SET(VERIFY_EVIDENCE_APP_ENCLAVE verify_evidence_app_enclave) + +ADD_SUBDIRECTORY(${VERIFY_EVIDENCE_APP}/enclave) + +INCLUDE ("${VERIFY_EVIDENCE_APP}/enclave/CMakeVariables.txt") + +# ENCLAVE_EDL is defined in the enclave subdirectory +SGX_EDGE_UNTRUSTED(${ENCLAVE_EDL} VERIFY_ENCLAVE_EDGE_SOURCES) +MESSAGE("VERIFY_ENCLAVE_EDGE_SOURCES: ${VERIFY_ENCLAVE_EDGE_SOURCES}") + +ADD_EXECUTABLE(${VERIFY_EVIDENCE_APP_ENCLAVE} + ${VERIFY_EVIDENCE_APP}/main.cpp + ${VERIFY_EVIDENCE_APP}/test-enclave.cpp + common/test-utils.cpp + ${VERIFY_ENCLAVE_EDGE_SOURCES} + ) + +# Make sure this app builds after get_attestation_app (because it has another enclave and build variables may conflict) +ADD_DEPENDENCIES(${VERIFY_EVIDENCE_APP_ENCLAVE} ${GET_ATTESTATION_APP}) + +# Make sure the enclave builds before the test app that links it +ADD_DEPENDENCIES(${VERIFY_EVIDENCE_APP_ENCLAVE} test_verify_enclave) + +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP_ENCLAVE} PRIVATE "$ENV{SGX_SDK}/include") +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP_ENCLAVE} PRIVATE "$ENV{SGX_SSL}/include") +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP_ENCLAVE} BEFORE PRIVATE "../common") # OAA common +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP_ENCLAVE} PRIVATE ${LOGGING_UNTRUSTED_INCLUDE_PATH}) +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP_ENCLAVE} PRIVATE "common") # test common + +TARGET_INCLUDE_DIRECTORIES(${VERIFY_EVIDENCE_APP_ENCLAVE} PRIVATE "../include") + +TARGET_LINK_LIBRARIES(${VERIFY_EVIDENCE_APP_ENCLAVE} -Wl,-L,$ENV{SGX_SDK}/lib64) +TARGET_LINK_LIBRARIES(${VERIFY_EVIDENCE_APP_ENCLAVE} -Wl,-L,$ENV{SGX_SSL}/lib64) +TARGET_LINK_LIBRARIES(${VERIFY_EVIDENCE_APP_ENCLAVE} + # we assume that the libraries are located one level up + "-L${CMAKE_CURRENT_BINARY_DIR}/.." + "-lu-one-attestation" + ) +TARGET_LINK_LIBRARIES(${VERIFY_EVIDENCE_APP_ENCLAVE} ${URTS_LIBRARY_NAME} ${UAE_SERVICE_LIBRARY_NAME}) +TARGET_LINK_LIBRARIES(${VERIFY_EVIDENCE_APP_ENCLAVE} sgx_usgxssl ${SGX_EPID_LIB} sgx_dcap_ql) +TARGET_LINK_LIBRARIES(${VERIFY_EVIDENCE_APP_ENCLAVE} ${LOGGING_UNTRUSTED_LIB}) + +## dcap_quoteprov necessary for logging +#TARGET_LINK_LIBRARIES(${VERIFY_EVIDENCE_APP_ENCLAVE} dcap_quoteprov) + +################################################################################# +## Test +################################################################################# + +SET(ATTESTED_EVIDENCE_TEST_FILE "attested_evidence_test.sh") +ADD_CUSTOM_COMMAND( + TARGET ${GET_ATTESTATION_APP} + PRE_BUILD + COMMAND cp ${ATTESTED_EVIDENCE_TEST_FILE} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + COMMAND cp ${GET_ATTESTATION_APP}/enclave/test_enclave.config.xml ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + COMMAND mkdir -p ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../conversion && cp -r ../conversion/* ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/../conversion + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + +# Register this application as a test +ADD_TEST( + NAME ${ATTESTED_EVIDENCE_TEST_FILE} + COMMAND bash -c "OAA_PATH=${CMAKE_CURRENT_SOURCE_DIR}/../ ./${ATTESTED_EVIDENCE_TEST_FILE}" + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + ) + diff --git a/common/crypto/attestation-api/test/attested_evidence_test.sh b/common/crypto/attestation-api/test/attested_evidence_test.sh new file mode 100755 index 00000000..8ff53848 --- /dev/null +++ b/common/crypto/attestation-api/test/attested_evidence_test.sh @@ -0,0 +1,293 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +# *** README *** +# This script is meant to run as part of the build. +# The script is transferred to the folder where other test binaries will be located, +# and it will orchestrate the test. +# Orchestration involves: preparing input file for init_attestation, +# calling get_attestation, calling attestation_to_evidence, calling verify_evidence. + +set -e + +if [[ -z "${OAA_PATH}" ]]; then + echo "OAA_PATH not set" + exit -1 +fi + +. ${OAA_PATH}/common/scripts/common_utils.sh +. ${OAA_PATH}/conversion/tag_to_variable.sh + +DEFINES_FILEPATH="${OAA_PATH}/test/common/test-defines.h" +TAGS_FILEPATH="${OAA_PATH}/include/attestation_tags.h" + + +function init_environment() +{ + . ../conversion/attestation_to_evidence.sh + . ../conversion/define_to_variable.sh + . ../conversion/enclave_to_mrenclave.sh +} + +function remove_artifacts() +{ + rm -rf *.txt +} + +function orchestrate() +{ + #get attestation + ./get_attestation_app + define_to_variable "${DEFINES_FILEPATH}" "GET_ATTESTATION_OUTPUT" + [ -f ${GET_ATTESTATION_OUTPUT} ] || die "no output from get_attestation" + + #translate attestation (note: attestation_to_evidence defines the EVIDENCE variable) + ATTESTATION=$(cat ${GET_ATTESTATION_OUTPUT}) + attestation_to_evidence "${ATTESTATION}" + + define_to_variable "${DEFINES_FILEPATH}" "EVIDENCE_FILE" + echo ${EVIDENCE} > ${EVIDENCE_FILE} + + #verify evidence + ./verify_evidence_app + + #verify evidence in enclave + ./verify_evidence_app_enclave +} + +#function orchestrate_with_go_conversion() +#{ +# #get attestation +# ./get_attestation_app +# define_to_variable "${DEFINES_FILEPATH}" "GET_ATTESTATION_OUTPUT" +# [ -f ${GET_ATTESTATION_OUTPUT} ] || die "no output from get_attestation" +# +# #translate attestation (note: attestation_to_evidence defines the EVIDENCE variable) +# ATTESTATION=$(cat ${GET_ATTESTATION_OUTPUT}) +# GO_CONVERSION_CMD="go run ${FPC_PATH}/common/crypto/attestation-api/test/conversion_app_go/main.go" +# EVIDENCE=$(${GO_CONVERSION_CMD} "${ATTESTATION}") +# +# define_to_variable "${DEFINES_FILEPATH}" "EVIDENCE_FILE" +# echo ${EVIDENCE} > ${EVIDENCE_FILE} +# +# #verify evidence +# ./verify_evidence_app +#} +# +#function orchestrate_with_go_verification() +#{ +# #get attestation +# ./get_attestation_app +# define_to_variable "${DEFINES_FILEPATH}" "GET_ATTESTATION_OUTPUT" +# [ -f ${GET_ATTESTATION_OUTPUT} ] || die "no output from get_attestation" +# +# #translate attestation (note: attestation_to_evidence defines the EVIDENCE variable) +# ATTESTATION=$(cat ${GET_ATTESTATION_OUTPUT}) +# attestation_to_evidence "${ATTESTATION}" +# +# define_to_variable "${DEFINES_FILEPATH}" "EVIDENCE_FILE" +# echo ${EVIDENCE} > ${EVIDENCE_FILE} +# +# #verify evidence +# go run -tags WITH_PDO_CRYPTO ${FPC_PATH}/common/crypto/attestation-api/test/verify_evidence_app_go/main.go +#} + +function check_collateral_epid() +{ + if [[ -z "${COLLATERAL_FOLDER}" ]]; then + echo "COLLATERAL_FOLDER for EPID not set" + exit -1 + fi + + SPID_TYPE_FILEPATH="${COLLATERAL_FOLDER}/spid_type.txt" + test -f ${SPID_TYPE_FILEPATH} || die "no spid type file ${SPID_TYPE_FILEPATH}" + + SPID_FILEPATH="${COLLATERAL_FOLDER}/spid.txt" + test -f ${SPID_FILEPATH} || die "no spid file ${SPID_FILEPATH}" +} + +function epid_test() +{ + say "Testing EPID SGX attestations" + + #check collateral + check_collateral_epid + init_environment + + #prepare input + remove_artifacts + define_to_variable "${DEFINES_FILEPATH}" "CODE_ID_FILE" + define_to_variable "${DEFINES_FILEPATH}" "STATEMENT_FILE" + define_to_variable "${DEFINES_FILEPATH}" "STATEMENT" + define_to_variable "${DEFINES_FILEPATH}" "INIT_DATA_INPUT" + + define_to_variable "${DEFINES_FILEPATH}" "UNSIGNED_ENCLAVE_FILENAME" + enclave_to_mrenclave ${UNSIGNED_ENCLAVE_FILENAME} test_enclave.config.xml + echo -n "$MRENCLAVE" > ${CODE_ID_FILE} + echo -n ${STATEMENT} > ${STATEMENT_FILE} + + #get spid type + SPID_TYPE=$(cat $SPID_TYPE_FILEPATH) + + #get spid + SPID=$(cat $SPID_FILEPATH) + + define_to_variable "${TAGS_FILEPATH}" "SPID_TAG" + define_to_variable "${TAGS_FILEPATH}" "SIG_RL_TAG" + echo -n "{\"${ATTESTATION_TYPE_TAG}\": \"$SPID_TYPE\", \"${SPID_TAG}\": \"$SPID\", \"${SIG_RL_TAG}\":\"\"}" > ${INIT_DATA_INPUT} + + #run attestation generation/conversion/verification tests + orchestrate + + #run attestation generation/conversion/verification tests (same as before, though with Go-based conversion) + #orchestrate_with_go_conversion + + say "Test success" +} + +function check_collateral_dcap() +{ + if [[ -z "${COLLATERAL_FOLDER}" ]]; then + echo "COLLATERAL_FOLDER for DCAP not set" + exit -1 + fi + + ATTESTATION_TYPE_FILEPATH="${COLLATERAL_FOLDER}/attestation_type.txt" + test -f ${ATTESTATION_TYPE_FILEPATH} || die "no attestation type file ${ATTESTATION_TYPE_FILEPATH}" + + API_KEY_FILEPATH="${COLLATERAL_FOLDER}/ita_api_key.txt" + test -f ${API_KEY_FILEPATH} || die "no api key file ${API_KEY_FILEPATH}" +} + +function dcap_test() +{ + say "Testing DCAP SGX attestations" + + #check collateral + check_collateral_dcap + init_environment + + #prepare input + remove_artifacts + define_to_variable "${DEFINES_FILEPATH}" "CODE_ID_FILE" + define_to_variable "${DEFINES_FILEPATH}" "STATEMENT_FILE" + define_to_variable "${DEFINES_FILEPATH}" "STATEMENT" + define_to_variable "${DEFINES_FILEPATH}" "INIT_DATA_INPUT" + + define_to_variable "${DEFINES_FILEPATH}" "UNSIGNED_ENCLAVE_FILENAME" + enclave_to_mrenclave ${UNSIGNED_ENCLAVE_FILENAME} test_enclave.config.xml + echo -n "$MRENCLAVE" > ${CODE_ID_FILE} + echo -n ${STATEMENT} > ${STATEMENT_FILE} + + #get attestation type + ATTESTATION_TYPE=$(cat $ATTESTATION_TYPE_FILEPATH) + + echo -n "{\"${ATTESTATION_TYPE_TAG}\": \"$ATTESTATION_TYPE\"}" > ${INIT_DATA_INPUT} + + #run attestation generation/conversion/verification tests + orchestrate + + say "Test success" +} + +function dcap_direct_test() +{ + say "Testing DCAP-DIRECT SGX attestations" + + init_environment + + #prepare input + remove_artifacts + define_to_variable "${DEFINES_FILEPATH}" "CODE_ID_FILE" + define_to_variable "${DEFINES_FILEPATH}" "STATEMENT_FILE" + define_to_variable "${DEFINES_FILEPATH}" "STATEMENT" + define_to_variable "${DEFINES_FILEPATH}" "INIT_DATA_INPUT" + + define_to_variable "${DEFINES_FILEPATH}" "UNSIGNED_ENCLAVE_FILENAME" + enclave_to_mrenclave ${UNSIGNED_ENCLAVE_FILENAME} test_enclave.config.xml + echo -n "$MRENCLAVE" > ${CODE_ID_FILE} + echo -n ${STATEMENT} > ${STATEMENT_FILE} + + #get attestation type + tag_to_variable "DCAP_DIRECT_SGX_TYPE_TAG" + ATTESTATION_TYPE="$DCAP_DIRECT_SGX_TYPE_TAG" + + echo -n "{\"${ATTESTATION_TYPE_TAG}\": \"$ATTESTATION_TYPE\"}" > ${INIT_DATA_INPUT} + + #run attestation generation/conversion/verification tests + orchestrate + + say "Test success" +} + + +function simulated_test() +{ + say "Testing simulated attestation" + init_environment + + #prepare input + remove_artifacts + define_to_variable "${DEFINES_FILEPATH}" "CODE_ID_FILE" + define_to_variable "${DEFINES_FILEPATH}" "STATEMENT_FILE" + define_to_variable "${DEFINES_FILEPATH}" "STATEMENT" + define_to_variable "${DEFINES_FILEPATH}" "INIT_DATA_INPUT" + + define_to_variable "${TAGS_FILEPATH}" "ATTESTATION_TYPE_TAG" + define_to_variable "${TAGS_FILEPATH}" "SIMULATED_TYPE_TAG" + + echo -n "this is ignored" > ${CODE_ID_FILE} + echo -n "also ignored" > ${STATEMENT_FILE} + echo -n "{\"${ATTESTATION_TYPE_TAG}\": \"${SIMULATED_TYPE_TAG}\"}" > ${INIT_DATA_INPUT} + + #run attestation generation/conversion/verification tests + orchestrate + + #run attestation generation/conversion/verification tests (same as before, though with Go-based conversion) + #orchestrate_with_go_conversion + + #run attestation generation/conversion/verification tests (same as before, though with Go-based verification) + #orchestrate_with_go_verification + + say "Test success" + +} + +simulated_test + +####################################### +# hw mode test +####################################### +if [[ ${SGX_MODE} == "HW" ]]; then + + if [[ ! -z "${SKIP_TEST_EPID+x}" ]]; then + say "Skipping EPID attestation test" + else + say "Testing HW-mode EPID attestation" + init_environment + epid_test + fi + + if [[ ! -z "${SKIP_TEST_DCAP_DIRECT+x}" ]]; then + say "Skipping DCAP-DIRECT attestation test" + else + say "Testing HW-mode DCAP-DIRECT attestation" + init_environment + dcap_direct_test + fi + + if [[ ! -z "${SKIP_TEST_DCAP+x}" ]]; then + say "Skipping DCAP attestation test" + else + say "Testing HW-mode DCAP attestation" + init_environment + dcap_test + fi + +else + say "Skipping actual attestation test" +fi + +say "Test successful." +exit 0 diff --git a/common/crypto/attestation-api/test/common/test-defines.h b/common/crypto/attestation-api/test/common/test-defines.h new file mode 100644 index 00000000..31ad222f --- /dev/null +++ b/common/crypto/attestation-api/test/common/test-defines.h @@ -0,0 +1,17 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#define ENCLAVE_FILENAME "test_enclave.signed.so" +#define VERIFY_ENCLAVE_FILENAME "test_verify_enclave.signed.so" +#define UNSIGNED_ENCLAVE_FILENAME "libtest_enclave.so" +#define INIT_DATA_INPUT "init_attestation_input.txt" +#define GET_ATTESTATION_OUTPUT "get_attestation_output.txt" +#define STATEMENT "1234567890" +#define STATEMENT_FILE "statement.txt" +#define CODE_ID_FILE "code_id.txt" +#define EVIDENCE_FILE "verify_evidence_input.txt" diff --git a/common/crypto/attestation-api/test/common/test-utils.cpp b/common/crypto/attestation-api/test/common/test-utils.cpp new file mode 100644 index 00000000..7dcd7021 --- /dev/null +++ b/common/crypto/attestation-api/test/common/test-utils.cpp @@ -0,0 +1,55 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test-utils.h" +#include +#include + +#include "error.h" +#include "logging.h" + +bool load_file(const char* filename, char* buffer, uint32_t buffer_length, uint32_t* written_bytes) +{ + uint32_t file_size, bytes_read; + struct stat s; + + FILE* fp = fopen(filename, "r"); + COND2LOGERR(fp == NULL, "can't open file"); + + COND2LOGERR(0 > fstat(fileno(fp), &s), "cannot stat file"); + file_size = s.st_size; + COND2LOGERR(file_size > buffer_length, "buffer too small"); + + bytes_read = fread(buffer, 1, file_size, fp); + COND2LOGERR(bytes_read != file_size, "read bytes don't match file size"); + *written_bytes = bytes_read; + + fclose(fp); + return true; + +err: + if (fp) + fclose(fp); + + return false; +} + +bool save_file(const char* filename, const char* buffer, uint32_t buffer_length) +{ + FILE* fpo; + uint32_t bytes; + fpo = fopen(filename, "w+"); + COND2LOGERR(fpo == NULL, "can't open file"); + bytes = fwrite(buffer, sizeof(uint8_t), buffer_length, fpo); + COND2LOGERR(bytes != buffer_length, "error bytes written"); + fclose(fpo); + return true; +err: + if (fpo) + fclose(fpo); + + return false; +} diff --git a/common/crypto/attestation-api/test/common/test-utils.h b/common/crypto/attestation-api/test/common/test-utils.h new file mode 100644 index 00000000..e2897bc6 --- /dev/null +++ b/common/crypto/attestation-api/test/common/test-utils.h @@ -0,0 +1,12 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +bool load_file(const char* filename, char* buffer, uint32_t buffer_length, uint32_t* written_bytes); +bool save_file(const char* filename, const char* buffer, uint32_t buffer_length); diff --git a/common/crypto/attestation-api/test/conversion_app_go/main.go b/common/crypto/attestation-api/test/conversion_app_go/main.go new file mode 100644 index 00000000..aa5e0c23 --- /dev/null +++ b/common/crypto/attestation-api/test/conversion_app_go/main.go @@ -0,0 +1,74 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +// this tool is meant to be used in `$FPC_PATH/common/crypto/attestation-api/test` to ensure compatibility +// with the shell-based attestation conversion implementation in `$FPC_PATH/common/crypto/attestation-api/conversion`. +package main + +import ( + "fmt" + "os" + + "github.com/hyperledger/fabric-private-chaincode/internal/attestation" + "github.com/hyperledger/fabric-private-chaincode/internal/protos" + "github.com/hyperledger/fabric-private-chaincode/internal/utils" + "github.com/pkg/errors" +) + +func printHelp() { + fmt.Printf( + `Usage: %s [] +convert attestation to evidence in (base64-encoded) Credentials protobuf +`, + os.Args[0]) +} + +func main() { + + // get input + if len(os.Args) < 2 { + printHelp() + exitIfError(fmt.Errorf("expect argument")) + } + + // convert + output, err := convert([]byte(os.Args[1])) + exitIfError(err) + + // return output + fmt.Printf("%s\n", string(output)) +} + +func exitIfError(err error) { + if err != nil { + fmt.Fprintf(os.Stderr, "ERROR: %v\n", err) + os.Exit(1) + } +} + +func convert(input []byte) ([]byte, error) { + credentials := &protos.Credentials{ + SerializedAttestedData: nil, + Attestation: input, + Evidence: nil, + } + credentialsOnlyAttestation := utils.MarshallProtoBase64(credentials) + + // conversion + converter := attestation.NewDefaultCredentialConverter() + credentialsStringOut, err := converter.ConvertCredentials(credentialsOnlyAttestation) + if err != nil { + return nil, errors.Wrap(err, "ERROR: couldn't convert credentials") + } + + credentialsOut, err := utils.UnmarshalCredentials(credentialsStringOut) + if err != nil { + return nil, errors.Wrap(err, "ERROR: couldn't unmarshal credentials") + } + + // return to stdout + return credentialsOut.Evidence, nil +} diff --git a/common/crypto/attestation-api/test/get_attestation_app/app/main.cpp b/common/crypto/attestation-api/test/get_attestation_app/app/main.cpp new file mode 100644 index 00000000..9bb523e8 --- /dev/null +++ b/common/crypto/attestation-api/test/get_attestation_app/app/main.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "error.h" +#include "logging.h" +#include "sgx_eid.h" +#include "sgx_error.h" +#include "sgx_urts.h" +#include "test-defines.h" +#include "test-utils.h" +#include "test_enclave_u.h" + +int main() +{ + sgx_launch_token_t token = {0}; + int updated = 0; + sgx_enclave_id_t global_eid = 0; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + const uint32_t buffer_length = 1 << 20; + uint8_t attestation[buffer_length]; + uint32_t attestation_length = 0; + uint32_t params_length = 0; + int b; + char params_buf[buffer_length]; + //std::string params; + + ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL); + if (ret != SGX_SUCCESS) + { + puts("error creating enclave"); + exit(-1); + } + + COND2LOGERR(false == load_file(INIT_DATA_INPUT, params_buf, buffer_length, ¶ms_length), + "error loading params"); + + //assuming it's a string, let's null terminate it + //params = std::string(params_buf, params_length); + params_buf[params_length] = '\0'; + + LOG_INFO("Testing init attestation\n"); + //init_att(global_eid, &b, (uint8_t*)params.c_str(), params.length()); + init_att(global_eid, &b, (uint8_t*)params_buf, params_length); + COND2LOGERR(!b, "init_attestation failed"); + + LOG_INFO("Testing get attestation\n"); + get_att(global_eid, &b, (uint8_t*)STATEMENT, strlen(STATEMENT), attestation, (1<<13), + &attestation_length); + COND2LOGERR(!b, "get_attestation failed"); + + COND2LOGERR(false == save_file(GET_ATTESTATION_OUTPUT, (char*)attestation, attestation_length), + "error saving attestation"); + sgx_destroy_enclave(global_eid); + + LOG_INFO("Test Successful\n"); + return 0; + +err: + sgx_destroy_enclave(global_eid); + return -1; +} diff --git a/common/crypto/attestation-api/test/get_attestation_app/enclave/CMakeLists.txt b/common/crypto/attestation-api/test/get_attestation_app/enclave/CMakeLists.txt new file mode 100644 index 00000000..da044b3a --- /dev/null +++ b/common/crypto/attestation-api/test/get_attestation_app/enclave/CMakeLists.txt @@ -0,0 +1,74 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +CMAKE_MINIMUM_REQUIRED(VERSION 3.2 FATAL_ERROR) + +INCLUDE ("CMakeVariables.txt") + +SET(ENCLAVE_NAME test_enclave) +PROJECT(${ENCLAVE_NAME} C CXX) + +add_definitions(-DENCLAVE_CODE) + +FILE(GLOB ENCLAVE_HEADERS *.h) +FILE(GLOB ENCLAVE_EDL *.edl) +FILE(GLOB ENCLAVE_CONFIG *.xml) +FILE(GLOB ENCLAVE_LDS *.lds) +FILE(GLOB ENCLAVE_SOURCES + *.cpp + ) + +SGX_EDGE_TRUSTED(${ENCLAVE_EDL} ENCLAVE_EDGE_SOURCES) +SET(ENCLAVE_EDL ${ENCLAVE_EDL} PARENT_SCOPE) + +ADD_LIBRARY(${ENCLAVE_NAME} SHARED ${ENCLAVE_HEADERS} ${ENCLAVE_SOURCES} ${ENCLAVE_EDGE_SOURCES} ${ENCLAVE_EDL}) + +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PUBLIC ${SGX_SDK}/include) +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PUBLIC ${SGX_SDK}/include/tlibc) +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PUBLIC "../../../include") +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PUBLIC ${LOGGING_TRUSTED_INCLUDE_PATH}) + +TARGET_COMPILE_OPTIONS(${ENCLAVE_NAME} PRIVATE $<$:-nostdinc++>) +TARGET_COMPILE_OPTIONS(${ENCLAVE_NAME} PRIVATE ${COMMON_CXX_FLAGS}) + +TARGET_LINK_DIRECTORIES(${ENCLAVE_NAME} PRIVATE ${SGX_SDK}/lib64) + +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--no-undefined) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -nostdlib) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -nodefaultlibs) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -nostartfiles) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-Bstatic) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-Bsymbolic) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--no-undefined) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-pie,-eenclave_entry) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--export-dynamic) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--defsym,__ImageBase=0) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--version-script=${ENCLAVE_LDS}) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-L,${SGX_SDK}/lib64) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-L,${SGX_SSL}/lib64) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--whole-archive -lsgx_tsgxssl -Wl,--no-whole-archive) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--whole-archive -l${TRTS_LIBRARY_NAME} -Wl,--no-whole-archive) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} + # we assume that the libraries are located 3 levels up + "-L${CMAKE_CURRENT_BINARY_DIR}/../../.." + -Wl,--start-group + ${LOGGING_TRUSTED_LIB} + -lt-one-attestation + sgx_tsgxssl_crypto + sgx_tstdc + sgx_tcxx + sgx_tcrypto + ${SERVICE_LIBRARY_NAME} + -Wl,--end-group + ) + +SET(ENCLAVE_SIGNING_KEY "${ENCLAVE_NAME}.sign.pem") +SGX_SIGN_ENCLAVE(${ENCLAVE_NAME} ${ENCLAVE_SIGNING_KEY} ${ENCLAVE_CONFIG}) + +ADD_CUSTOM_COMMAND( + TARGET ${ENCLAVE_NAME} + PRE_BUILD + COMMAND openssl genrsa -3 -out ${ENCLAVE_SIGNING_KEY} 3072 + ) + diff --git a/common/crypto/attestation-api/test/get_attestation_app/enclave/CMakeVariables.txt b/common/crypto/attestation-api/test/get_attestation_app/enclave/CMakeVariables.txt new file mode 100644 index 00000000..bb98f50b --- /dev/null +++ b/common/crypto/attestation-api/test/get_attestation_app/enclave/CMakeVariables.txt @@ -0,0 +1,100 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +################################################################################ +# Checks +################################################################################ + +IF (NOT DEFINED ENV{SGX_MODE}) + SET(SGX_MODE "SIM") +ELSE() + SET(SGX_MODE $ENV{SGX_MODE}) +ENDIF() + +IF (NOT DEFINED ENV{SGX_SDK}) + SET(SGX_SDK "/opt/intel/sgxsdk") +ELSE() + SET(SGX_SDK "$ENV{SGX_SDK}") +ENDIF() + +IF (NOT DEFINED ENV{SGX_SSL}) + SET(SGX_SSL "/opt/intel/sgxssl") +ELSE() + SET(SGX_SSL "$ENV{SGX_SSL}") +ENDIF() + + +SET(SGX_EDGER "${SGX_SDK}/bin/x64/sgx_edger8r") +SET(SGX_SIGN "${SGX_SDK}/bin/x64/sgx_sign") + +SET(SGX_SEARCH_PATH "${SGX_SDK}/include:${SGX_SSL}/include") +SET(SGX_ENCLAVE_INCLUDE "${SGX_SDK}/include" + "${SGX_SDK}/include/tlibc" + "${SGX_SDK}/include/libcxx") + +#ADD_COMPILE_OPTIONS($<$:-std=c++11>) + +################################################################################ +# Internal SGX Variables +################################################################################ + +IF (${SGX_MODE} STREQUAL "SIM") + #ADD_COMPILE_DEFINITIONS(SGX_SIMULATOR=1) + SET(TRTS_LIBRARY_NAME "sgx_trts_sim") + SET(URTS_LIBRARY_NAME "sgx_urts_sim") + SET(UAE_SERVICE_LIBRARY_NAME "sgx_uae_service_sim") + SET(SERVICE_LIBRARY_NAME "sgx_tservice_sim") + SET(SGX_EPID_LIB sgx_epid_sim) +ELSE() + SET(TRTS_LIBRARY_NAME "sgx_trts") + SET(URTS_LIBRARY_NAME "sgx_urts") + SET(UAE_SERVICE_LIBRARY_NAME "sgx_uae_service") + SET(SERVICE_LIBRARY_NAME "sgx_tservice") + SET(SGX_EPID_LIB sgx_epid) +ENDIF() + +################################################################################ +# Functions +################################################################################ + +FUNCTION(SGX_EDGE_TRUSTED EDL EDGE_FILES) + GET_FILENAME_COMPONENT(EDL_BASE_NAME ${EDL} NAME_WE) + GET_FILENAME_COMPONENT(EDL_DIR_NAME ${EDL} DIRECTORY) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + + SET (EDGE_FILES_LIST "${CMAKE_CURRENT_BINARY_DIR}/${EDL_BASE_NAME}_t.h" "${CMAKE_CURRENT_BINARY_DIR}/${EDL_BASE_NAME}_t.c") + SET (${EDGE_FILES} ${EDGE_FILES_LIST} PARENT_SCOPE) + ADD_CUSTOM_COMMAND( OUTPUT ${EDGE_FILES_LIST} + COMMAND "${SGX_EDGER}" --trusted ${EDL} --search-path ${SGX_SEARCH_PATH} --search-path ${EDL_DIR_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${EDL} + ) +ENDFUNCTION() + +FUNCTION(SGX_EDGE_UNTRUSTED EDL EDGE_FILES) + GET_FILENAME_COMPONENT(EDL_BASE_NAME ${EDL} NAME_WE) + GET_FILENAME_COMPONENT(EDL_DIR_NAME ${EDL} DIRECTORY) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + + SET (EDGE_FILES_LIST "${CMAKE_CURRENT_BINARY_DIR}/${EDL_BASE_NAME}_u.h" "${CMAKE_CURRENT_BINARY_DIR}/${EDL_BASE_NAME}_u.c") + SET (${EDGE_FILES} ${EDGE_FILES_LIST} PARENT_SCOPE) + ADD_CUSTOM_COMMAND( OUTPUT ${EDGE_FILES_LIST} + COMMAND "${SGX_EDGER}" --untrusted ${EDL} --search-path ${SGX_SEARCH_PATH} --search-path ${EDL_DIR_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${EDL} + ) +ENDFUNCTION() + +FUNCTION(SGX_SIGN_ENCLAVE TARGET KEY_FILE CONFIG) + SET (ENCLAVE $) + + SET (SIGNED_ENCLAVE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${TARGET}.signed${CMAKE_SHARED_LIBRARY_SUFFIX}) + SET (SIGNED_ENCLAVE ${SIGNED_ENCLAVE} PARENT_SCOPE) + SET (SIGNED_ENCLAVE_METADATA ${SIGNED_ENCLAVE}".meta") + ADD_CUSTOM_COMMAND( TARGET ${TARGET} + POST_BUILD + COMMAND "${SGX_SIGN}" sign -key "${KEY_FILE}" -enclave "${ENCLAVE}" -out "${SIGNED_ENCLAVE}" -dumpfile ${SIGNED_ENCLAVE_METADATA} -config "${CONFIG}" > /dev/null + ) +ENDFUNCTION() + diff --git a/common/crypto/attestation-api/test/get_attestation_app/enclave/test.cpp b/common/crypto/attestation-api/test/get_attestation_app/enclave/test.cpp new file mode 100644 index 00000000..36e990f5 --- /dev/null +++ b/common/crypto/attestation-api/test/get_attestation_app/enclave/test.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test.h" +#include "attestation.h" +#include "logging.h" +#include "test_enclave_t.h" + +int init_att(uint8_t* params, uint32_t params_length) +{ + LOG_DEBUG("Testing init attestation"); + return init_attestation(params, params_length); +} + +int get_att(uint8_t* statement, + uint32_t statement_length, + uint8_t* attestation, + uint32_t attestation_max_length, + uint32_t* attestation_length) +{ + LOG_DEBUG("Testing get attestation"); + return get_attestation( + statement, statement_length, attestation, attestation_max_length, attestation_length); +} diff --git a/common/crypto/attestation-api/test/get_attestation_app/enclave/test.h b/common/crypto/attestation-api/test/get_attestation_app/enclave/test.h new file mode 100644 index 00000000..6fa11bff --- /dev/null +++ b/common/crypto/attestation-api/test/get_attestation_app/enclave/test.h @@ -0,0 +1,15 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif +int test(); +#if defined(__cplusplus) +} +#endif diff --git a/common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.config.xml b/common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.config.xml new file mode 100644 index 00000000..3938529e --- /dev/null +++ b/common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.config.xml @@ -0,0 +1,18 @@ + + + + 0 + 0 + 0x40000 + 0x100000 + 10 + 1 + + 0 + 0 + 0xFFFFFFFF + diff --git a/common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.edl b/common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.edl new file mode 100644 index 00000000..5ae4e875 --- /dev/null +++ b/common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.edl @@ -0,0 +1,21 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +enclave { + from "sgx_tstdc.edl" import *; + from "../../../ocalls/attestation-ocalls.edl" import *; + from "../../../common/logging/ocalls/logging.edl" import *; + + trusted { + public int init_att( + [in, size=params_length] uint8_t* params, uint32_t params_length); + public int get_att( + [in, size=statement_length] uint8_t* statement, uint32_t statement_length, + [out, size=attestation_max_length] uint8_t* attestation, uint32_t attestation_max_length, + [out] uint32_t* attestation_length); + }; +}; + diff --git a/common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.lds b/common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.lds new file mode 100644 index 00000000..829f4968 --- /dev/null +++ b/common/crypto/attestation-api/test/get_attestation_app/enclave/test_enclave.lds @@ -0,0 +1,15 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_enclave.so +{ + global: + g_global_data_sim; + g_global_data; + test_enclave_entry; + local: + *; +}; diff --git a/common/crypto/attestation-api/test/verify_evidence_app/enclave/CMakeLists.txt b/common/crypto/attestation-api/test/verify_evidence_app/enclave/CMakeLists.txt new file mode 100644 index 00000000..c091ce3b --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/enclave/CMakeLists.txt @@ -0,0 +1,78 @@ +# Copyright 2020 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +CMAKE_MINIMUM_REQUIRED(VERSION 3.2 FATAL_ERROR) + +INCLUDE ("CMakeVariables.txt") + +SET(ENCLAVE_NAME test_verify_enclave) +PROJECT(${ENCLAVE_NAME} C CXX) + +add_definitions(-DENCLAVE_CODE) + +FILE(GLOB ENCLAVE_HEADERS *.h) +FILE(GLOB ENCLAVE_EDL *.edl) +FILE(GLOB ENCLAVE_CONFIG *.xml) +FILE(GLOB ENCLAVE_LDS *.lds) +FILE(GLOB ENCLAVE_SOURCES + *.cpp + ) + +SGX_EDGE_TRUSTED(${ENCLAVE_EDL} ENCLAVE_EDGE_SOURCES) +SET(ENCLAVE_EDL ${ENCLAVE_EDL} PARENT_SCOPE) + +ADD_LIBRARY(${ENCLAVE_NAME} SHARED ${ENCLAVE_HEADERS} ${ENCLAVE_SOURCES} ${ENCLAVE_EDGE_SOURCES}) + +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PRIVATE "../../../include") +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PUBLIC ${SGX_SDK}/include) +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PUBLIC ${SGX_SDK}/include/libcxx) +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PRIVATE ${SGX_SDK}/include/tlibc) +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PUBLIC ${LOGGING_TRUSTED_INCLUDE_PATH}) + +TARGET_INCLUDE_DIRECTORIES(${ENCLAVE_NAME} PRIVATE ${SGX_SSL}/include) + +TARGET_COMPILE_OPTIONS(${ENCLAVE_NAME} PRIVATE $<$:-nostdinc++>) +TARGET_COMPILE_OPTIONS(${ENCLAVE_NAME} PRIVATE ${COMMON_CXX_FLAGS}) +TARGET_COMPILE_OPTIONS(${ENCLAVE_NAME} PRIVATE -nostdinc) + +TARGET_LINK_DIRECTORIES(${ENCLAVE_NAME} PRIVATE ${SGX_SDK}/lib64) + +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--no-undefined) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -nostdlib) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -nodefaultlibs) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -nostartfiles) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-Bstatic) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-Bsymbolic) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--no-undefined) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-pie,-eenclave_entry) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--export-dynamic) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--defsym,__ImageBase=0) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--version-script=${ENCLAVE_LDS}) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-L,${SGX_SDK}/lib64) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,-L,${SGX_SSL}/lib64) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--whole-archive -lsgx_tsgxssl -Wl,--no-whole-archive) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} -Wl,--whole-archive -l${TRTS_LIBRARY_NAME} -Wl,--no-whole-archive) +TARGET_LINK_LIBRARIES(${ENCLAVE_NAME} + # we assume that the libraries are located 3 levels up + "-L${CMAKE_CURRENT_BINARY_DIR}/../../.." + -Wl,--start-group + ${LOGGING_TRUSTED_LIB} + -lt-one-attestation + sgx_tsgxssl_crypto + sgx_tstdc + sgx_tcxx + sgx_tcrypto + ${SERVICE_LIBRARY_NAME} + -Wl,--end-group + ) + +SET(ENCLAVE_SIGNING_KEY "${ENCLAVE_NAME}.sign.pem") +SGX_SIGN_ENCLAVE(${ENCLAVE_NAME} ${ENCLAVE_SIGNING_KEY} ${ENCLAVE_CONFIG}) + +ADD_CUSTOM_COMMAND( + TARGET ${ENCLAVE_NAME} + PRE_BUILD + COMMAND openssl genrsa -3 -out ${ENCLAVE_SIGNING_KEY} 3072 + ) + diff --git a/common/crypto/attestation-api/test/verify_evidence_app/enclave/CMakeVariables.txt b/common/crypto/attestation-api/test/verify_evidence_app/enclave/CMakeVariables.txt new file mode 100644 index 00000000..d101643d --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/enclave/CMakeVariables.txt @@ -0,0 +1,99 @@ +# Copyright 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +################################################################################ +# Checks +################################################################################ + +IF (NOT DEFINED ENV{SGX_MODE}) + SET(SGX_MODE "SIM") +ELSE() + SET(SGX_MODE $ENV{SGX_MODE}) +ENDIF() + +IF (NOT DEFINED ENV{SGX_SDK}) + SET(SGX_SDK "/opt/intel/sgxsdk") +ELSE() + SET(SGX_SDK "$ENV{SGX_SDK}") +ENDIF() + +IF (NOT DEFINED ENV{SGX_SSL}) + SET(SGX_SSL "/opt/intel/sgxssl") +ELSE() + SET(SGX_SSL "$ENV{SGX_SSL}") +ENDIF() + + +SET(SGX_EDGER "${SGX_SDK}/bin/x64/sgx_edger8r") +SET(SGX_SIGN "${SGX_SDK}/bin/x64/sgx_sign") + +SET(SGX_SEARCH_PATH "${SGX_SDK}/include:${SGX_SSL}/include") +SET(SGX_ENCLAVE_INCLUDE "${SGX_SDK}/include" + "${SGX_SDK}/include/tlibc" + "${SGX_SDK}/include/libcxx") + +#ADD_COMPILE_OPTIONS($<$:-std=c++11>) + +################################################################################ +# Internal SGX Variables +################################################################################ + +IF (${SGX_MODE} STREQUAL "SIM") + SET(TRTS_LIBRARY_NAME "sgx_trts_sim") + SET(URTS_LIBRARY_NAME "sgx_urts_sim") + SET(UAE_SERVICE_LIBRARY_NAME "sgx_uae_service_sim") + SET(SERVICE_LIBRARY_NAME "sgx_tservice_sim") + SET(SGX_EPID_LIB sgx_epid_sim) +ELSE() + SET(TRTS_LIBRARY_NAME "sgx_trts") + SET(URTS_LIBRARY_NAME "sgx_urts") + SET(UAE_SERVICE_LIBRARY_NAME "sgx_uae_service") + SET(SERVICE_LIBRARY_NAME "sgx_tservice") + SET(SGX_EPID_LIB sgx_epid) +ENDIF() + +################################################################################ +# Functions +################################################################################ + +FUNCTION(SGX_EDGE_TRUSTED EDL EDGE_FILES) + GET_FILENAME_COMPONENT(EDL_BASE_NAME ${EDL} NAME_WE) + GET_FILENAME_COMPONENT(EDL_DIR_NAME ${EDL} DIRECTORY) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + + SET (EDGE_FILES_LIST "${CMAKE_CURRENT_BINARY_DIR}/${EDL_BASE_NAME}_t.h" "${CMAKE_CURRENT_BINARY_DIR}/${EDL_BASE_NAME}_t.c") + SET (${EDGE_FILES} ${EDGE_FILES_LIST} PARENT_SCOPE) + ADD_CUSTOM_COMMAND( OUTPUT ${EDGE_FILES_LIST} + COMMAND "${SGX_EDGER}" --trusted ${EDL} --search-path ${SGX_SEARCH_PATH} --search-path ${EDL_DIR_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${EDL} + ) +ENDFUNCTION() + +FUNCTION(SGX_EDGE_UNTRUSTED EDL EDGE_FILES) + GET_FILENAME_COMPONENT(EDL_BASE_NAME ${EDL} NAME_WE) + GET_FILENAME_COMPONENT(EDL_DIR_NAME ${EDL} DIRECTORY) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + + SET (EDGE_FILES_LIST "${CMAKE_CURRENT_BINARY_DIR}/${EDL_BASE_NAME}_u.h" "${CMAKE_CURRENT_BINARY_DIR}/${EDL_BASE_NAME}_u.c") + SET (${EDGE_FILES} ${EDGE_FILES_LIST} PARENT_SCOPE) + ADD_CUSTOM_COMMAND( OUTPUT ${EDGE_FILES_LIST} + COMMAND "${SGX_EDGER}" --untrusted ${EDL} --search-path ${SGX_SEARCH_PATH} --search-path ${EDL_DIR_NAME} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${EDL} + ) +ENDFUNCTION() + +FUNCTION(SGX_SIGN_ENCLAVE TARGET KEY_FILE CONFIG) + SET (ENCLAVE $) + + SET (SIGNED_ENCLAVE ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${TARGET}.signed${CMAKE_SHARED_LIBRARY_SUFFIX}) + SET (SIGNED_ENCLAVE ${SIGNED_ENCLAVE} PARENT_SCOPE) + SET (SIGNED_ENCLAVE_METADATA ${SIGNED_ENCLAVE}".meta") + ADD_CUSTOM_COMMAND( TARGET ${TARGET} + POST_BUILD + COMMAND "${SGX_SIGN}" sign -key "${KEY_FILE}" -enclave "${ENCLAVE}" -out "${SIGNED_ENCLAVE}" -dumpfile ${SIGNED_ENCLAVE_METADATA} -config "${CONFIG}" > /dev/null + ) +ENDFUNCTION() + diff --git a/common/crypto/attestation-api/test/verify_evidence_app/enclave/test.cpp b/common/crypto/attestation-api/test/verify_evidence_app/enclave/test.cpp new file mode 100644 index 00000000..de5d2881 --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/enclave/test.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "stdbool.h" +#include "verify-evidence.h" +#include "logging.h" +#include "test_verify_enclave_t.h" + + +bool verify_ev(uint8_t* evidence, + uint32_t evidence_length, + uint8_t* expected_statement, + uint32_t expected_statement_length, + uint8_t* expected_code_id, + uint32_t expected_code_id_length) +{ + return verify_evidence( + evidence, + evidence_length, + expected_statement, + expected_statement_length, + expected_code_id, + expected_code_id_length); +} diff --git a/common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.config.xml b/common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.config.xml new file mode 100644 index 00000000..49123765 --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.config.xml @@ -0,0 +1,18 @@ + + + + 0 + 0 + 0x40000 + 0x100000 + 1 + 1 + + 0 + 0 + 0xFFFFFFFF + diff --git a/common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.edl b/common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.edl new file mode 100644 index 00000000..d60db14b --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.edl @@ -0,0 +1,20 @@ +/* + * Copyright 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "stdbool.h" + +enclave { + from "sgx_tstdc.edl" import *; + from "../../../ocalls/attestation-ocalls.edl" import *; + from "../../../common/logging/ocalls/logging.edl" import *; + + trusted { + public bool verify_ev( + [in, size=evidence_length] uint8_t* evidence, uint32_t evidence_length, + [in, size=expected_statement_length] uint8_t* expected_statement, uint32_t expected_statement_length, + [in, size=expected_code_id_length] uint8_t* expected_code_id, uint32_t expected_code_id_length); + }; +}; diff --git a/common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.lds b/common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.lds new file mode 100644 index 00000000..2adb435d --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/enclave/test_verify_enclave.lds @@ -0,0 +1,15 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +test_verify_enclave.so +{ + global: + g_global_data_sim; + g_global_data; + test_verify_enclave_entry; + local: + *; +}; diff --git a/common/crypto/attestation-api/test/verify_evidence_app/main.cpp b/common/crypto/attestation-api/test/verify_evidence_app/main.cpp new file mode 100644 index 00000000..996acf29 --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/main.cpp @@ -0,0 +1,19 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test.h" + +int main() +{ + bool b = test(); + if (b) + { + // success + return 0; + } + // error + return -1; +} diff --git a/common/crypto/attestation-api/test/verify_evidence_app/test-enclave.cpp b/common/crypto/attestation-api/test/verify_evidence_app/test-enclave.cpp new file mode 100644 index 00000000..a503798e --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/test-enclave.cpp @@ -0,0 +1,112 @@ +/* + * Copyright 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test.h" +#include +#include "error.h" +#include "logging.h" +#include "test-defines.h" +#include "test-utils.h" + +#include + +#include "attestation_tags.h" +#include "verify-evidence.h" + +#include "sgx_eid.h" +#include "sgx_error.h" +#include "sgx_urts.h" +#include "test-defines.h" +#include "test-utils.h" +#include "test_verify_enclave_u.h" + +bool test() +{ + sgx_launch_token_t token = {0}; + int updated = 0; + sgx_enclave_id_t global_eid = 0; + sgx_status_t ret = SGX_ERROR_UNEXPECTED; + + ret = sgx_create_enclave(VERIFY_ENCLAVE_FILENAME, 1, &token, &updated, &global_eid, NULL); + if (ret != SGX_SUCCESS) + { + puts("error creating enclave"); + exit(-1); + } + + uint32_t buffer_length = 1 << 20; + char buffer[buffer_length]; + uint32_t filled_size; + std::string jsonevidence; + std::string expected_statement; + std::string expected_code_id; + std::string wrong_expected_statement; + std::string wrong_expected_code_id; + + COND2LOGERR(!load_file(EVIDENCE_FILE, buffer, buffer_length, &filled_size), + "can't read input evidence " EVIDENCE_FILE); + jsonevidence = std::string(buffer, filled_size); + + COND2LOGERR(!load_file(STATEMENT_FILE, buffer, buffer_length, &filled_size), + "can't read input statement " STATEMENT_FILE); + expected_statement = std::string(buffer, filled_size); + + COND2LOGERR(!load_file(CODE_ID_FILE, buffer, buffer_length, &filled_size), + "can't read input code id " CODE_ID_FILE); + expected_code_id = std::string(buffer, filled_size); + + wrong_expected_statement = std::string("wrong statement"); + wrong_expected_code_id = + std::string("BADBADBADBAD9E317C4F7312A0D644FFC052F7645350564D43586D8102663358"); + + bool b, expected_b; + // test normal situation + expected_b = true; b = !expected_b; + ret = verify_ev(global_eid, &b, + (uint8_t*)jsonevidence.c_str(), jsonevidence.length(), + (uint8_t*)expected_statement.c_str(), expected_statement.length(), + (uint8_t*)expected_code_id.c_str(), expected_code_id.length()); + COND2LOGERR(ret != SGX_SUCCESS, "sgx error: %x", ret); + COND2LOGERR(b != expected_b, "correct evidence failed"); + + // this test succeeds for simulated attestations, and fails for real ones + // test with wrong statement + expected_b = (jsonevidence.find(SIMULATED_TYPE_TAG) == std::string::npos ? false : true); + b = !expected_b; + if (expected_b == false) + { + LOG_WARNING("next test expected to fail"); + } + ret = verify_ev(global_eid, &b, + (uint8_t*)jsonevidence.c_str(), jsonevidence.length(), + (uint8_t*)wrong_expected_statement.c_str(), wrong_expected_statement.length(), + (uint8_t*)expected_code_id.c_str(), expected_code_id.length()); + COND2LOGERR(ret != SGX_SUCCESS, "sgx error: %x", ret); + COND2LOGERR(b != expected_b, "evidence with bad statement succeeded"); + + // this test succeeds for simulated attestations, and fails for real ones + // test with wrong code id + expected_b = (jsonevidence.find(SIMULATED_TYPE_TAG) == std::string::npos ? false : true); + b = !expected_b; + if (expected_b == false) + { + LOG_WARNING("next test expected to fail"); + } + ret = verify_ev(global_eid, &b, + (uint8_t*)jsonevidence.c_str(), jsonevidence.length(), + (uint8_t*)expected_statement.c_str(), expected_statement.length(), + (uint8_t*)wrong_expected_code_id.c_str(), wrong_expected_code_id.length()); + COND2LOGERR(ret != SGX_SUCCESS, "sgx error: %x", ret); + COND2LOGERR(b != expected_b, "evidence with bad code id succeeded"); + + sgx_destroy_enclave(global_eid); + + LOG_INFO("Test Successful\n"); + return true; + +err: + return false; +} diff --git a/common/crypto/attestation-api/test/verify_evidence_app/test.cpp b/common/crypto/attestation-api/test/verify_evidence_app/test.cpp new file mode 100644 index 00000000..d2db1903 --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/test.cpp @@ -0,0 +1,80 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "test.h" +#include +#include "error.h" +#include "logging.h" +#include "test-defines.h" +#include "test-utils.h" + +#include "attestation_tags.h" +#include "verify-evidence.h" + +bool test() +{ + uint32_t buffer_length = 1 << 20; + char buffer[buffer_length]; + uint32_t filled_size; + std::string jsonevidence; + std::string expected_statement; + std::string expected_code_id; + std::string wrong_expected_statement; + std::string wrong_expected_code_id; + + COND2LOGERR(!load_file(EVIDENCE_FILE, buffer, buffer_length, &filled_size), + "can't read input evidence " EVIDENCE_FILE); + jsonevidence = std::string(buffer, filled_size); + + COND2LOGERR(!load_file(STATEMENT_FILE, buffer, buffer_length, &filled_size), + "can't read input statement " STATEMENT_FILE); + expected_statement = std::string(buffer, filled_size); + + COND2LOGERR(!load_file(CODE_ID_FILE, buffer, buffer_length, &filled_size), + "can't read input code id " CODE_ID_FILE); + expected_code_id = std::string(buffer, filled_size); + + wrong_expected_statement = std::string("wrong statement"); + wrong_expected_code_id = + std::string("BADBADBADBAD9E317C4F7312A0D644FFC052F7645350564D43586D8102663358"); + + bool b, expected_b; + // test normal situation + b = verify_evidence((uint8_t*)jsonevidence.c_str(), jsonevidence.length(), + (uint8_t*)expected_statement.c_str(), expected_statement.length(), + (uint8_t*)expected_code_id.c_str(), expected_code_id.length()); + COND2LOGERR(!b, "correct evidence failed"); + + // this test succeeds for simulated attestations, and fails for real ones + // test with wrong statement + expected_b = (jsonevidence.find(SIMULATED_TYPE_TAG) == std::string::npos ? false : true); + if (expected_b == false) + { + LOG_WARNING("next test expected to fail"); + } + b = verify_evidence((uint8_t*)jsonevidence.c_str(), jsonevidence.length(), + (uint8_t*)wrong_expected_statement.c_str(), wrong_expected_statement.length(), + (uint8_t*)expected_code_id.c_str(), expected_code_id.length()); + COND2LOGERR(b != expected_b, "evidence with bad statement succeeded"); + + // this test succeeds for simulated attestations, and fails for real ones + // test with wrong code id + expected_b = (jsonevidence.find(SIMULATED_TYPE_TAG) == std::string::npos ? false : true); + if (expected_b == false) + { + LOG_WARNING("next test expected to fail"); + } + b = verify_evidence((uint8_t*)jsonevidence.c_str(), jsonevidence.length(), + (uint8_t*)expected_statement.c_str(), expected_statement.length(), + (uint8_t*)wrong_expected_code_id.c_str(), wrong_expected_code_id.length()); + COND2LOGERR(b != expected_b, "evidence with bad code id succeeded"); + + LOG_INFO("Test Successful\n"); + return true; + +err: + return false; +} diff --git a/common/crypto/attestation-api/test/verify_evidence_app/test.h b/common/crypto/attestation-api/test/verify_evidence_app/test.h new file mode 100644 index 00000000..99d5015b --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app/test.h @@ -0,0 +1,9 @@ +/* + * Copyright 2020 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +bool test(); diff --git a/common/crypto/attestation-api/test/verify_evidence_app_go/main.go b/common/crypto/attestation-api/test/verify_evidence_app_go/main.go new file mode 100644 index 00000000..ee050d53 --- /dev/null +++ b/common/crypto/attestation-api/test/verify_evidence_app_go/main.go @@ -0,0 +1,70 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +// this tool is meant to be used in `$FPC_PATH/common/crypto/attestation-api/test` to ensure compatibility +// with the shell-based attestation verification implementation in `$FPC_PATH/common/crypto/attestation-api/evidence`. +package main + +import ( + "fmt" + "os" + "strings" + + "github.com/hyperledger/fabric-private-chaincode/internal/attestation" + "github.com/hyperledger/fabric-private-chaincode/internal/attestation/epid/pdo" + "github.com/hyperledger/fabric-private-chaincode/internal/attestation/simulation" + "github.com/hyperledger/fabric-private-chaincode/internal/protos" + "github.com/pkg/errors" + "google.golang.org/protobuf/types/known/anypb" +) + +func main() { + + evidenceJson, err := readFile("verify_evidence_input.txt") + exitIfError(err) + + statementJson, err := readFile("statement.txt") + exitIfError(err) + + expectedMrenclave, err := readFile("code_id.txt") + exitIfError(err) + + verifier := attestation.NewCredentialVerifier( + simulation.NewSimulationVerifier(), + pdo.NewEpidLinkableVerifier(), + pdo.NewEpidUnlinkableVerifier(), + ) + + cred := &protos.Credentials{ + SerializedAttestedData: &anypb.Any{ + Value: []byte(statementJson), + }, + Evidence: []byte(evidenceJson), + } + + err = verifier.VerifyCredentials(cred, expectedMrenclave) + exitIfError(err) +} + +func exitIfError(err error) { + if err != nil { + fmt.Fprintf(os.Stderr, "ERROR: %v\n", err) + os.Exit(1) + } +} + +func readFile(path string) (string, error) { + content, err := os.ReadFile(path) + if err != nil { + return "", errors.Wrapf(err, "could not read %s", path) + } + + if len(content) == 0 { + return "", errors.Errorf("empty file %s", path) + } + + return strings.TrimSuffix(string(content), "\n"), nil +} diff --git a/docker/pdo_services_base.dockerfile b/docker/pdo_services_base.dockerfile index a039fe6f..b7da30d9 100644 --- a/docker/pdo_services_base.dockerfile +++ b/docker/pdo_services_base.dockerfile @@ -20,9 +20,9 @@ FROM pdo_base:${PDO_VERSION} ARG UBUNTU_VERSION=22.04 ARG UBUNTU_NAME=jammy -ARG SGX=2.22 -ARG OPENSSL=3.0.12 -ARG SGXSSL=3.0_Rev1 +ARG SGX=2.25 +ARG OPENSSL=3.0.14 +ARG SGXSSL=3.0_Rev4 RUN echo "deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu ${UBUNTU_NAME} main" >> /etc/apt/sources.list \ && wget -qO - https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key | apt-key add - \ @@ -36,6 +36,8 @@ RUN echo "deb [arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu ${U --no-install-recommends \ libsgx-urts \ libsgx-uae-service \ + libsgx-dcap-ql-dev \ + libsgx-dcap-quote-verify-dev \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* @@ -84,6 +86,52 @@ RUN . /opt/intel/sgxsdk/environment \ ENV SGX_SSL="/opt/intel/sgxssl" + +# ----------------------------------------------------------------- +# SGX DCAP Primitives +# ----------------------------------------------------------------- +RUN apt-get update +RUN apt-get install -y -q \ + libboost-dev \ + libboost-system-dev \ + libboost-thread-dev \ + protobuf-c-compiler \ + libprotobuf-c-dev \ + protobuf-compiler +RUN apt-get install -y \ + basez \ + clang \ + cmake \ + curl \ + libsgx-dcap-default-qpl \ + #libsgx-dcap-default-qpl-dev adds libdcap_quoteprov.so and /usr/include/sgx_default_quote_provider.h + libsgx-dcap-default-qpl-dev \ + jq \ + libssl-dev \ + vim + +ARG DCAP=1.19 +ENV DCAP_PRIMITIVES=/tmp/SGXDataCenterAttestationPrimitives + +RUN git clone https://github.com/intel/SGXDataCenterAttestationPrimitives.git ${DCAP_PRIMITIVES} \ + && cd ${DCAP_PRIMITIVES}/QuoteVerification \ + && git checkout DCAP_${DCAP} \ + && git submodule update --init --recursive + +RUN cd ${DCAP_PRIMITIVES}/QuoteGeneration \ + && ./download_prebuilt.sh \ + && make GEN_STATIC=1 + +RUN cd ${DCAP_PRIMITIVES}/QuoteVerification/QVL/Src \ + && ./release -DBUILD_ENCLAVE=ON -DBUILD_TESTS=OFF ; ./release -DBUILD_ENCLAVE=ON -DBUILD_ATTESTATION_APP=OFF -DBUILD_TESTS=OFF + +RUN echo '{\n\ + "pccs_url": "https://localhost:8081/sgx/certification/v4/", \n\ + "collateral_service": "https://api.trustedservices.intel.com/sgx/certification/v4/",\n\ + "use_secure_cert": false\n\ + }' > /etc/sgx_default_qcnl.conf + + # ----------------------------------------------------------------- # ----------------------------------------------------------------- WORKDIR /project/pdo @@ -99,4 +147,7 @@ RUN useradd -m -u $UID -g $GID -d /project/pdo -o -s /bin/bash $UNAME RUN chown --recursive $UNAME:$UNAME /project/pdo USER $UNAME +#this is necessary for git operations such as "git describe --tags" from the new user +RUN git config --global --add safe.directory ${DCAP_PRIMITIVES} + ENTRYPOINT ["/bin/bash"] From 77a17c7300fa6b39bdd531bb7ab7b24d58d76a61 Mon Sep 17 00:00:00 2001 From: Bruno Vavala Date: Sat, 19 Oct 2024 00:38:40 +0000 Subject: [PATCH 2/2] integrate use of attestation api in eservice enclave Signed-off-by: Bruno Vavala --- build/cmake/SGX.cmake | 2 +- common/cmake/CommonVariables.cmake | 5 +++ eservice/lib/libpdo_enclave/enclave.edl | 1 + eservice/lib/libpdo_enclave/signup.edl | 5 +++ .../lib/libpdo_enclave/signup_enclave.cpp | 26 +++++++++++++ eservice/lib/libpdo_enclave/signup_enclave.h | 5 +++ .../pdo/eservice/enclave/enclave/enclave.h | 2 +- .../pdo/eservice/enclave/enclave/signup.cpp | 37 +++++++++++++++++++ eservice/setup.py | 3 +- 9 files changed, 83 insertions(+), 3 deletions(-) diff --git a/build/cmake/SGX.cmake b/build/cmake/SGX.cmake index 73447aae..370a1cc0 100644 --- a/build/cmake/SGX.cmake +++ b/build/cmake/SGX.cmake @@ -110,7 +110,7 @@ ENDIF() SET(SGX_TRUSTED_LIBS sgx_tstdc sgx_tcxx sgx_tcrypto ${SERVICE_LIBRARY_NAME}) SET(SGX_UNTRUSTED_LIBS ${URTS_LIBRARY_NAME} pthread) -SET(SGX_SEARCH_PATH "${SGX_SDK}/include:${SGX_SSL}/include") +SET(SGX_SEARCH_PATH "${SGX_SDK}/include:${SGX_SSL}/include:$ENV{PDO_SOURCE_ROOT}/common") SET(SGX_TRUSTED_INCLUDE_DIRS "${SGX_SDK}/include" "${SGX_SDK}/include/tlibc" diff --git a/common/cmake/CommonVariables.cmake b/common/cmake/CommonVariables.cmake index 7cbd95a5..1b54dce6 100644 --- a/common/cmake/CommonVariables.cmake +++ b/common/cmake/CommonVariables.cmake @@ -29,6 +29,9 @@ SET(C_COMMON_LIB_NAME cpdo-common) SET(U_COMMON_LIB_NAME updo-common) SET(T_COMMON_LIB_NAME tpdo-common) +# import attestation lib variables U_ONE_ATTESTATION_LIB_NAME, T_ONE_ATTESTATION_LIB_NAME +INCLUDE("${COMMON_SOURCE_DIR}/crypto/attestation-api/CMakeVariables.txt") + SET(INTERPRETER_LIB_NAME pdo-contract) # Block store library does not depend on sgx at all @@ -78,6 +81,7 @@ LIST(APPEND COMMON_CLIENT_LIBS pthread lmdb) LIST(APPEND COMMON_UNTRUSTED_LIBS ${U_COMMON_LIB_NAME}) LIST(APPEND COMMON_UNTRUSTED_LIBS ${U_CRYPTO_LIB_NAME}) LIST(APPEND COMMON_UNTRUSTED_LIBS ${BLOCK_STORE_LIB_NAME}) +LIST(APPEND COMMON_UNTRUSTED_LIBS ${U_ONE_ATTESTATION_LIB_NAME}) LIST(APPEND COMMON_UNTRUSTED_LIBS pthread lmdb) # ----------------------------------------------------------------- @@ -88,4 +92,5 @@ LIST(APPEND COMMON_TRUSTED_LIBS ${T_COMMON_LIB_NAME}) LIST(APPEND COMMON_TRUSTED_LIBS ${T_CRYPTO_LIB_NAME}) LIST(APPEND COMMON_TRUSTED_LIBS ${BLOCK_STORE_LIB_NAME}) LIST(APPEND COMMON_TRUSTED_LIBS ${COMMON_INTERPRETER_LIBRARIES}) +LIST(APPEND COMMON_TRUSTED_LIBS ${T_ONE_ATTESTATION_LIB_NAME}) LIST(APPEND COMMON_TRUSTED_LIBS lmdb) diff --git a/eservice/lib/libpdo_enclave/enclave.edl b/eservice/lib/libpdo_enclave/enclave.edl index 34801b39..4fe6338c 100644 --- a/eservice/lib/libpdo_enclave/enclave.edl +++ b/eservice/lib/libpdo_enclave/enclave.edl @@ -20,4 +20,5 @@ enclave { from "signup.edl" import *; from "contract.edl" import *; from "block_store.edl" import *; + from "crypto/attestation-api/ocalls/attestation-ocalls.edl" import *; }; diff --git a/eservice/lib/libpdo_enclave/signup.edl b/eservice/lib/libpdo_enclave/signup.edl index 31a43210..cc867f50 100644 --- a/eservice/lib/libpdo_enclave/signup.edl +++ b/eservice/lib/libpdo_enclave/signup.edl @@ -30,6 +30,11 @@ enclave { public pdo_err_t ecall_CreateEnclaveData( [in] const sgx_target_info_t* inTargetInfo, [in, string] const char* inOriginatorPublicKeyHash, + [in, size=inAttestationParamsSize] uint8_t* inAttestationParams, + size_t inAttestationParamsSize, + [out, size=inAllocatedAttestationSize] uint8_t* outAttestation, + size_t inAllocatedAttestationSize, + [out] size_t* outAttestationSize, [out, size=inAllocatedPublicEnclaveDataSize] char* outPublicEnclaveData, size_t inAllocatedPublicEnclaveDataSize, [out] size_t* outPublicEnclaveDataSize, diff --git a/eservice/lib/libpdo_enclave/signup_enclave.cpp b/eservice/lib/libpdo_enclave/signup_enclave.cpp index 00fd3880..186b2893 100644 --- a/eservice/lib/libpdo_enclave/signup_enclave.cpp +++ b/eservice/lib/libpdo_enclave/signup_enclave.cpp @@ -40,6 +40,8 @@ #include "enclave_utils.h" #include "signup_enclave.h" +#include "attestation-api/include/attestation.h" + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // XX Declaration of static helper functions XX // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX @@ -109,6 +111,11 @@ pdo_err_t ecall_CalculatePublicEnclaveDataSize(size_t* pPublicEnclaveDataSize) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX pdo_err_t ecall_CreateEnclaveData(const sgx_target_info_t* inTargetInfo, const char* inOriginatorPublicKeyHash, + uint8_t* inAttestationParams, + size_t inAttestationParamsSize, + uint8_t* outAttestation, + size_t inAllocatedAttestationSize, + size_t* outAttestationSize, char* outPublicEnclaveData, size_t inAllocatedPublicEnclaveDataSize, size_t* outPublicEnclaveDataSize, @@ -158,6 +165,16 @@ pdo_err_t ecall_CreateEnclaveData(const sgx_target_info_t* inTargetInfo, sgx_report_data_t reportData = {0}; CreateSignupReportData(inOriginatorPublicKeyHash, enclaveData, &reportData); + // get serialized statement (which will be later hashed to create report data) + std::string hashString; + hashString.append(enclaveData.get_serialized_signing_key()); + hashString.append(enclaveData.get_serialized_encryption_key()); + std::transform(inOriginatorPublicKeyHash, + inOriginatorPublicKeyHash + strlen(inOriginatorPublicKeyHash), std::back_inserter(hashString), + [](char c) { + return c; // do nothing + }); + sgx_status_t ret = sgx_create_report(inTargetInfo, &reportData, outEnclaveReport); pdo::error::ThrowSgxError(ret, "Failed to create enclave report"); @@ -187,6 +204,15 @@ pdo_err_t ecall_CreateEnclaveData(const sgx_target_info_t* inTargetInfo, strncpy_s(outPublicEnclaveData, inAllocatedPublicEnclaveDataSize, enclaveData.get_public_data().c_str(), enclaveData.get_public_data_size()); + + bool b = init_attestation(inAttestationParams, inAttestationParamsSize); + pdo::error::ThrowIf(b == false, "Error in init attestation"); + + uint32_t as; + b = get_attestation((uint8_t*)hashString.c_str(), hashString.length(), outAttestation, inAllocatedAttestationSize, &as); + *outAttestationSize = (size_t)as; + pdo::error::ThrowIf(b == false, "Error in attestation"); + } catch (pdo::error::Error& e) { diff --git a/eservice/lib/libpdo_enclave/signup_enclave.h b/eservice/lib/libpdo_enclave/signup_enclave.h index 8dcabbc1..e37314ae 100644 --- a/eservice/lib/libpdo_enclave/signup_enclave.h +++ b/eservice/lib/libpdo_enclave/signup_enclave.h @@ -29,6 +29,11 @@ extern pdo_err_t ecall_CalculatePublicEnclaveDataSize(size_t* pPublicEnclaveData // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX extern pdo_err_t ecall_CreateEnclaveData(const sgx_target_info_t* inTargetInfo, const char* inOriginatorPublicKeyHash, + uint8_t* inAttestationParams, + size_t inAttestationParamsSize, + uint8_t* outAttestation, + size_t inAllocatedAttestationSize, + size_t* outAttestationSize, char* outPublicEnclaveData, size_t inAllocatedPublicEnclaveDataSize, size_t* outPublicEnclaveDataSize, diff --git a/eservice/pdo/eservice/enclave/enclave/enclave.h b/eservice/pdo/eservice/enclave/enclave/enclave.h index 0ce063a3..86272e84 100644 --- a/eservice/pdo/eservice/enclave/enclave/enclave.h +++ b/eservice/pdo/eservice/enclave/enclave/enclave.h @@ -103,6 +103,7 @@ namespace pdo { { return this->threadId; } + sgx_spid_t spid; protected: void LoadEnclave(); @@ -116,7 +117,6 @@ namespace pdo { size_t sealedSignupDataSize; std::string signatureRevocationList; - sgx_spid_t spid; sgx_target_info_t reportTargetInfo; sgx_epid_group_id_t epidGroupId; diff --git a/eservice/pdo/eservice/enclave/enclave/signup.cpp b/eservice/pdo/eservice/enclave/enclave/signup.cpp index c79b8438..d8f25ec0 100644 --- a/eservice/pdo/eservice/enclave/enclave/signup.cpp +++ b/eservice/pdo/eservice/enclave/enclave/signup.cpp @@ -26,6 +26,8 @@ #include "pdo_error.h" #include "types.h" #include "zero.h" +#include "jsonvalue.h" +#include "hex_string.h" #include "enclave/enclave.h" #include "enclave/base.h" @@ -134,11 +136,24 @@ pdo_err_t pdo::enclave_api::enclave_data::CreateEnclaveData( size_t computed_public_enclave_data_size; size_t computed_sealed_enclave_data_size; + std::string hex_spid = BinaryToHexString(g_Enclave[0].spid.id, 16); + std::string attestation_params = + std::string("{\"attestation_type\": \"epid-linkable\", \"hex_spid\": \"") + + hex_spid + + std::string("\", \"sig_rl\": \"\"}") + ; + ByteArray attestation; + attestation.resize(1 << 12); + size_t attestation_size; + sresult = g_Enclave[0].CallSgx( [enclaveid, &presult, target_info, inOriginatorPublicKeyHash, + &attestation_params, + &attestation, + &attestation_size, &outPublicEnclaveData, &computed_public_enclave_data_size, &sealed_enclave_data_buffer, @@ -150,6 +165,11 @@ pdo_err_t pdo::enclave_api::enclave_data::CreateEnclaveData( &presult, &target_info, inOriginatorPublicKeyHash.c_str(), + (uint8_t*)(attestation_params.c_str()), + attestation_params.length(), + attestation.data(), + attestation.size(), + &attestation_size, outPublicEnclaveData.data(), outPublicEnclaveData.size(), &computed_public_enclave_data_size, @@ -175,6 +195,23 @@ pdo_err_t pdo::enclave_api::enclave_data::CreateEnclaveData( g_Enclave[0].CreateQuoteFromReport(&enclave_report, enclave_quote_buffer); outEnclaveQuote = ByteArrayToBase64EncodedString(enclave_quote_buffer); + + { + const char* pvalue = nullptr; + std::string a(attestation.begin(), attestation.end()); + + JsonValue parsed(json_parse_string(a.c_str())); + pdo::error::ThrowIfNull(parsed.value, "failed to parse serialized attestation; badly formed JSON"); + + JSON_Object* data_object = json_value_get_object(parsed); + pdo::error::ThrowIfNull(data_object, "invalid serialized attestation; missing root object"); + + pvalue = json_object_dotget_string(data_object, "attestation"); + pdo::error::ThrowIfNull(pvalue, "invalid serialized attestation; missing attestation"); + + outEnclaveQuote.assign(pvalue); + } + } catch (pdo::error::Error& e) { pdo::enclave_api::base::SetLastError(e.what()); result = e.error_code(); diff --git a/eservice/setup.py b/eservice/setup.py index 96768840..c5505a1e 100644 --- a/eservice/setup.py +++ b/eservice/setup.py @@ -100,6 +100,7 @@ libraries = [ 'updo-common', + 'u-one-attestation', 'pdo-lmdb-block-store', 'lmdb' ] @@ -109,7 +110,7 @@ else : libraries += ['sgx_urts', 'sgx_uae_service'] -libraries += ['sgx_usgxssl'] +libraries += ['sgx_usgxssl', 'sgx_dcap_ql'] module_files = [ os.path.join(module_src_path, 'pdo_enclave_internal.i'),