diff --git a/demos/remote_attestation/CMakeLists.txt b/demos/remote_attestation/CMakeLists.txt index 3cb53a83..5760062c 100644 --- a/demos/remote_attestation/CMakeLists.txt +++ b/demos/remote_attestation/CMakeLists.txt @@ -1,17 +1,18 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.5) -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") -PROJECT(REMOTE_ATTESTATION LANGUAGES CXX VERSION 0.0.1) +MESSAGE(STATUS "Build Mode: ${BUILD_MODE}") +ADD_COMPILE_OPTIONS(-std=c++11) +if(BUILD_MODE STREQUAL "Debug") + ADD_COMPILE_OPTIONS(-O0 -g2 -DDEBUG -UNDEBUG -UEDEBUG) +endif() + +PROJECT(REMOTE_ATTESTATION LANGUAGES CXX VERSION 0.1.0) MESSAGE(STATUS "BINARY dir " ${CMAKE_CURRENT_BINARY_DIR}) MESSAGE(STATUS "SOURCE dir " ${CMAKE_CURRENT_SOURCE_DIR}) SET(SGXSDK_INSTALL_DIR /opt/intel/sgxsdk) SET(OCCLUM_INSTALL_DIR /usr/local/occlum/x86_64-linux-musl) -if(BUILD_MODE STREQUAL "Debug") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -g2 -DDEBUG -UNDEBUG -UEDEBUG") -endif() - FILE(GLOB LIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/lib/src/*.cpp) SET(RALIB occlumra) @@ -33,14 +34,14 @@ FILE(GLOB APP_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/app/*.cpp) ADD_EXECUTABLE(${DEMOAPP} ${APP_SRCS}) TARGET_INCLUDE_DIRECTORIES( ${DEMOAPP} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/app + ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/lib/include ${SGXSDK_INSTALL_DIR}/include ${OCCLUM_INSTALL_DIR}/include ) TARGET_LINK_LIBRARIES(${DEMOAPP} -L${CMAKE_CURRENT_BINARY_DIR} -l${RALIB} - -L${OCCLUM_INSTALL_DIR}/lib -lcurl + -L${OCCLUM_INSTALL_DIR}/lib -lcurl -lcrypto -Wl,-rpath=${CMAKE_CURRENT_BINARY_DIR}:${OCCLUM_INSTALL_DIR}/lib ) ADD_DEPENDENCIES(${DEMOAPP} ${RALIB}) diff --git a/demos/remote_attestation/README.md b/demos/remote_attestation/README.md index ea7b90cf..532c7e65 100644 --- a/demos/remote_attestation/README.md +++ b/demos/remote_attestation/README.md @@ -29,8 +29,8 @@ Build the code in debug mode with "--debug", otherwise it's in Relese mode by de **Step 2.** Run this demo on Occlum -Build the occlum image and run the RA test application. +Build the occlum image and run the RA test application. Log level is "off" by default. ``` -./run_on_occlum.sh +./run_on_occlum.sh [off|trace] ``` diff --git a/demos/remote_attestation/app/ra_config.h b/demos/remote_attestation/app/ra_config.h index 5a2e3fb5..cf48b06b 100644 --- a/demos/remote_attestation/app/ra_config.h +++ b/demos/remote_attestation/app/ra_config.h @@ -3,14 +3,9 @@ #include -#include "sofaenclave/common/error.h" -#include "sofaenclave/common/log.h" -#include "sofaenclave/ra_conf.h" - -constexpr char kConfValueEnable[] = "enable"; -constexpr char kConfValueDisable[] = "disable"; -constexpr char kConfValueTrue[] = "true"; -constexpr char kConfValueFalse[] = "false"; +#include "tee/common/error.h" +#include "tee/common/log.h" +#include "tee/ra_conf_api.h" constexpr char kRaConf[] = "ra_config.json"; @@ -20,8 +15,7 @@ constexpr char kConfIasKey[] = "ias_sp_key_file"; constexpr char kConfIasAccessKey[] = "ias_access_key"; constexpr char kConfSPID[] = "enclave_spid"; -#define RA_CONF_STR(name) SofaeConfGetStr(kRaConf, name) -#define RA_CONF_INT(name, value) SofaeConfGetInt(kRaConf, name, value) -#define RA_CONF_ARRARY(name, value) SofaeConfGetStrArray(kRaConf, name, value) +#define RA_CONF_STR(name) TeeConfGetStr(kRaConf, name) +#define RA_CONF_FILE(name) TeeConfGetStr(kRaConf, name) #endif // REMOTE_ATTESTATION_RA_CONFIG_H_ diff --git a/demos/remote_attestation/app/ra_main.cpp b/demos/remote_attestation/app/ra_main.cpp index 8e452f3d..105f2dea 100644 --- a/demos/remote_attestation/app/ra_main.cpp +++ b/demos/remote_attestation/app/ra_main.cpp @@ -1,67 +1,28 @@ -#include #include -#include "./ra_config.h" -#include "sofaenclave/ra_manager.h" - -static uint8_t Hex2Dec(const char hex) { - if (('0' <= hex) && (hex <= '9')) { - return hex - '0'; - } - else if (('a' <= hex) && (hex <= 'f')) { - return hex - 'a' + 10; - } - else if (('A' <= hex) && (hex <= 'F')) { - return hex - 'A' + 10; - } - else { - // Otherwise return zero for none HEX charactor - return 0; - } -} - -static std::vector HexStr2Bytes(const uint8_t* str) { - int len = strlen(RCAST(const char *, str)) / 2; - std::vector dst(len); - - for (int i = 0; i < len; i++) { - dst[i] = (Hex2Dec(str[i * 2] & 0xFF) << 4) + - (Hex2Dec(str[i * 2 + 1] & 0xFF)); - } - return dst; -} +#include "app/ra_config.h" +#include "tee/ra_quote.h" int main() { printf("Remote attestation testing ...\n"); - std::string endpoint = RA_CONF_STR(kConfIasServer); - std::string cert = RA_CONF_STR(kConfIasCert); - std::string key = RA_CONF_STR(kConfIasKey); - std::string access_key = RA_CONF_STR(kConfIasAccessKey); - std::string spid_str = RA_CONF_STR(kConfSPID); + // Don't need to set IAS key/cert when we used accesskey authentication + RaIasServerCfg ias_server; + ias_server.endpoint = RA_CONF_STR(kConfIasServer); + ias_server.accesskey = RA_CONF_STR(kConfIasAccessKey); + std::string spid = RA_CONF_STR(kConfSPID); - if (spid_str.empty()) { - printf("Please specify the right SPID in configuration file!\n"); - return -1; - } + // 64Byts report data for adding some project special things if necessary + sgx_report_data_t report_data = {0}; - SofaeServerCfg ias_server = {endpoint, cert, key, access_key}; - SofaeEnclaveQuote quote = {0}; - SofaeQuoteArgs quote_args = {0}; - quote_args.quote_type = SGX_LINKABLE_SIGNATURE; - quote_args.quote.as_buf = RCAST(uint8_t *, "e); - quote_args.quote_buf_len = sizeof(SofaeEnclaveQuote); - - std::vector spid_vec = HexStr2Bytes( - RCAST(const uint8_t *, spid_str.c_str())); - std::memcpy(RCAST(void *, "e_args.spid.id), - RCAST(const void *, spid_vec.data()), sizeof(quote_args.spid)); - sofaenclave::occlum::IasReport ias_report; - int ret = GetQuoteAndFetchIasReport(ias_server, "e_args, &ias_report); + ra::occlum::RaEnclaveQuote ra; + ra::occlum::RaIasReport ias_report; + int ret = ra.GetEnclaveIasReport(ias_server, spid, report_data, &ias_report); if (ret) { - printf("Fail to get quote or fetch report, erro code is %x!\n", ret); + printf("Fail to get quote or fetch report, error code is %x!\n", ret); } else { printf("Test getting quote and fetching report successfully!\n"); } + return ret; } diff --git a/demos/remote_attestation/download_and_build.sh b/demos/remote_attestation/download_and_build.sh index d3ff1f3f..e0fe415e 100755 --- a/demos/remote_attestation/download_and_build.sh +++ b/demos/remote_attestation/download_and_build.sh @@ -1,108 +1,144 @@ #!/usr/bin/env bash -export CC=occlum-gcc -export CXX=occlum-g++ - THISDIR="$(dirname $(readlink -f $0))" INSTALLDIR="/usr/local/occlum/x86_64-linux-musl" +OCCLUMCC="/usr/local/occlum/bin/occlum-gcc" +OCCLUMCXX="/usr/local/occlum/bin/occlum-g++" + +export CC=$OCCLUMCC +export CXX=$OCCLUMCXX +export PATH=$PATH:$INSTALLDIR/bin +export PKG_CONFIG_LIBDIR=$PKG_CONFIG_LIBDIR:$INSTALLDIR/lib + DEPSDIR="$THISDIR/deps" -BUILDMODE="Release" -[ "$1" == "--debug" ] && BUILDMODE="Debug" +ALL_COMPONENTS="openssl libcurl demo" +OPENSSLDIR=openssl +CURLDIR=curl +CPPCODECDIR=cppcodec +RAPIDJSONDIR=rapidjson -mkdir -p $DEPSDIR || exit 1 +SHOW_HELP() { + LOG_INFO "Usage: $0 [component-name]\n" + LOG_INFO "Build component in [$ALL_COMPONENTS] or all by default\n" + exit 0 +} -# Download OpenSSL 1.1.1 -OPENSSLDIR="${DEPSDIR}/openssl" -if [ ! -d "$OPENSSLDIR" ] ; then - echo "Downloading openssl ..." - cd "$DEPSDIR" && \ - wget https://github.com/openssl/openssl/archive/OpenSSL_1_1_1.tar.gz && \ - tar -xvf OpenSSL_1_1_1.tar.gz && \ - mv openssl-OpenSSL_1_1_1 openssl && \ - echo "Download openssl successfully" || exit 1 -else - echo "The openssl code is already existent" -fi +LOG_DEBUG() { + echo -e "\033[36m$@\033[0m" +} -# Download curl 7.29.0 -CURLDIR="${DEPSDIR}/curl" -if [ ! -d "$CURLDIR" ] ; then - echo "Downloading curl ..." - cd "$DEPSDIR" && \ - wget https://github.com/curl/curl/archive/curl-7_70_0.tar.gz && \ - tar -xvf curl-7_70_0.tar.gz && \ - mv curl-curl-7_70_0 curl && \ - echo "Download curl successfully" || exit 1 -else - echo "The curl code is already existent" -fi +LOG_INFO() { + echo -e "\033[32m$@\033[0m" +} -# Download other dependencies -CPPCODECDIR="${DEPSDIR}/cppcodec" -if [ ! -d "$CPPCODECDIR" ] ; then - echo "Downloading cppcodec ..." - cd "$DEPSDIR" && \ - wget -O cppcodec-v0.2.tar.gz \ - https://github.com/tplgy/cppcodec/archive/v0.2.tar.gz && \ - tar -xvf cppcodec-v0.2.tar.gz && \ - mv cppcodec-0.2 cppcodec && \ - echo "Download cppcodec successfully" || exit 1 -else - echo "The cppcodec code is already existent" -fi -RAPIDJSONDIR="${DEPSDIR}/rapidjson" -if [ ! -d "$RAPIDJSONDIR" ] ; then - echo "Downloading rapidjson ..." - cd "$DEPSDIR" && \ - wget -O rapidjson-v1.1.0.tar.gz \ - https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz && \ - tar -xvf rapidjson-v1.1.0.tar.gz && \ - mv rapidjson-1.1.0 rapidjson && \ - echo "Download cppcodec successfully" || exit 1 -else - echo "The cppcodec code is already existent" -fi +LOG_ERROR() { + echo -e "\033[31m$@\033[0m" +} +ERROR_EXIT() { + LOG_ERROR "$@" && exit 1 +} -# Build and install openssl -if [ ! -f "$INSTALLDIR/lib/libcrypto.so" ] ; then - echo "Building openssl ..." - cd "$OPENSSLDIR" && \ - CC=occlum-gcc ./config \ - --prefix=$INSTALLDIR \ +TRYGET() { + local dst=$1 + local url=$2 + local pkg=${3:-$(basename $url)} + local flag="./occlum_demo_source" + + # Download package tarball + if [ ! -e $pkg ] ; then + LOG_DEBUG "Downloading $pkg ..." + wget $url -O $pkg || ERROR_EXIT "Fail to download $pkg" + else + LOG_INFO "[READY] $pkg" + fi + + # Prepare the source code directory + if [ ! -f $dst/$flag ] ; then + LOG_DEBUG "Preparing source code: $dst ..." + mkdir -p $dst && \ + tar -xvf $pkg -C $dst --strip-components 1 >/dev/null || \ + ERROR_EXIT "Fail to extract archive file $pkg" + touch $dst/$flag && \ + LOG_DEBUG "Prepare $(basename $dst) source code successfully" + else + LOG_INFO "[READY] $dst" + fi +} + +openssl_check() { + [ -f "$INSTALLDIR/lib/libcrypto.so" ] || return 1 +} + +openssl_build() { + cd "$DEPSDIR/$OPENSSLDIR" && \ + CC=$OCCLUMCC CXX=$OCCLUMCXX \ + ./config --prefix=$INSTALLDIR \ --openssldir=/usr/local/occlum/ssl \ --with-rand-seed=rdcpu \ no-zlib no-async no-tests && \ - make -j${nproc} && \ - sudo make install && \ - echo "Build openssl successfully" || exit 1 -else - echo "The openssl library is aleady existent" -fi + make -j && make install +} -# Build and install libcurl -if [ ! -f "$INSTALLDIR/lib/libcurl.so" ] ; then - cd "$CURLDIR" +libcurl_check() { + [ -f "$INSTALLDIR/lib/libcurl.so" ] || return 1 +} + +libcurl_build() { + cd "$DEPSDIR/$CURLDIR" if [ ! -f ./configure ] ; then - echo "Building configure file ..." + LOG_DEBUG "Building configure file ..." ./buildconf || exit 1 fi - echo "Building curl ..." - CC=occlum-gcc CXX=occlum-g++ ./configure \ + CC=$OCCLUMCC CXX=$OCCLUMCXX \ + ./configure \ --prefix=$INSTALLDIR \ --with-ssl=$INSTALLDIR \ --without-zlib && \ - make -j${nproc} && \ - sudo make install && \ - echo "Build curl successfully" || exit 1 -else - echo "The curl library is aleady existent" + make -j && make install +} + +demo_check() { + return 1 # return false to always build it +} + +demo_build() { + cd "$THISDIR" + rm -rf build && mkdir build && cd build && \ + cmake ../ \ + -DCMAKE_NO_SYSTEM_FROM_IMPORTED=TRUE \ + -DCMAKE_CXX_COMPILER=$OCCLUMCXX \ + -DBUILD_MODE=${BUILDMODE} && \ + make -j $BUILDVERBOSE && \ + cp $THISDIR/build/libocclumra.a $INSTALLDIR/lib +} + +# Show help menu +[ "$1" == "-h" -o "$1" == "--help" ] && SHOW_HELP + +# Check the build mode +BUILDMODE="Release" +BUILDVERBOSE="" +if [ "$1" == "--debug" ] ; then + BUILDMODE="Debug" + BUILDVERBOSE="VERBOSE=1" + shift; fi -# Build the remote attestation library and demo application -echo "Build demo source code" -cd "$THISDIR" && rm -rf ./build && mkdir -p build -cd build && \ -cmake -DCMAKE_CXX_COMPILER=occlum-g++ -DBUILD_MODE=${BUILDMODE} ../ && \ -make -j$(nproc) +# Build specified component or all by default +BUILD_COMPONENTS="${1:-$ALL_COMPONENTS}" + +# Download all components once here together +mkdir -p $DEPSDIR && cd $DEPSDIR || exit 1 +TRYGET $OPENSSLDIR https://github.com/openssl/openssl/archive/OpenSSL_1_1_1.tar.gz +TRYGET $CURLDIR https://github.com/curl/curl/archive/curl-7_70_0.tar.gz +TRYGET $CPPCODECDIR https://github.com/tplgy/cppcodec/archive/v0.2.tar.gz cppcodec-0.2.tar.gz +TRYGET $RAPIDJSONDIR https://github.com/Tencent/rapidjson/archive/v1.1.0.tar.gz rapidjson-1.1.0.tar.gz + +for i in $BUILD_COMPONENTS ; do + ${i}_check && LOG_INFO "[READY] build check for $i" && continue + LOG_DEBUG "Building $i ..." && ${i}_build && \ + LOG_DEBUG "Build $i successfully" || ERROR_EXIT "Fail to build $i" +done + diff --git a/demos/remote_attestation/lib/include/sofaenclave/common/error.h b/demos/remote_attestation/lib/include/sofaenclave/common/error.h deleted file mode 100644 index d0a6cddb..00000000 --- a/demos/remote_attestation/lib/include/sofaenclave/common/error.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_ERROR_H_ -#define REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_ERROR_H_ - -/* We want to use SofaeErrorCode to include the error code from Intel SDK and - * also the SOFAEnclave code, so we use the same unsigned int type here.*/ -typedef int SofaeErrorCode; - -#define SOFAE_MK_ERROR(x) (0xFFFF0000&((x) << 16)) - -#define SOFAE_SUCCESS (0x00000000) - -#define SOFAE_ERROR_GENERIC SOFAE_MK_ERROR(0x0001) -#define SOFAE_ERROR_PARAMETERS SOFAE_MK_ERROR(0x0002) -#define SOFAE_ERROR_MALLOC SOFAE_MK_ERROR(0x0003) -#define SOFAE_ERROR_ENCLAVE_NOTINITIALIZED SOFAE_MK_ERROR(0x0004) -#define SOFAE_ERROR_REPORT_DATA_SIZE SOFAE_MK_ERROR(0x0005) -#define SOFAE_ERROR_PARSE_CONFIGURATIONS SOFAE_MK_ERROR(0x0006) -#define SOFAE_ERROR_PARSE_COMMANDLINE SOFAE_MK_ERROR(0x0007) - -#define SOFAE_ERROR_FILE_OPEN SOFAE_MK_ERROR(0x0101) -#define SOFAE_ERROR_FILE_READ SOFAE_MK_ERROR(0x0102) -#define SOFAE_ERROR_FILE_WRITE SOFAE_MK_ERROR(0x0103) - -#define SOFAE_ERROR_CONF_LOAD SOFAE_MK_ERROR(0x0201) -#define SOFAE_ERROR_CONF_NOTEXIST SOFAE_MK_ERROR(0x0202) - -#define SOFAE_ERROR_IAS_CLIENT_INIT SOFAE_MK_ERROR(0x0501) -#define SOFAE_ERROR_IAS_CLIENT_CONNECT SOFAE_MK_ERROR(0x0502) -#define SOFAE_ERROR_IAS_CLIENT_GETSIGRL SOFAE_MK_ERROR(0x0503) -#define SOFAE_ERROR_IAS_CLIENT_GETREPORT SOFAE_MK_ERROR(0x0504) -#define SOFAE_ERROR_IAS_CLIENT_UNESCAPE SOFAE_MK_ERROR(0x0505) -#define SOFAE_ERROR_IAS_LOAD_CACHED_REPORT SOFAE_MK_ERROR(0x0506) - -#define SOFAE_ERROR_SDK_UNEXPECTED SOFAE_MK_ERROR(0x0FFF) - -#define SOFAE_ERROR_CODE(rc) (rc) -#define SOFAE_ERROR_MERGE(ecallcode, retcode) ((ecallcode) | (retcode)) - -#endif // REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_ERROR_H_ diff --git a/demos/remote_attestation/lib/include/sofaenclave/common/log.h b/demos/remote_attestation/lib/include/sofaenclave/common/log.h deleted file mode 100644 index 728acf4c..00000000 --- a/demos/remote_attestation/lib/include/sofaenclave/common/log.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_LOG_H_ -#define REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_LOG_H_ - -#include - -extern "C" int printf(const char *fmt, ...); - -#ifdef DEBUG -#define SOFAE_LOG_DEBUG(fmt, ...) \ - printf("[DEBUG][%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) -#else -#define SOFAE_LOG_DEBUG(fmt, ...) -#endif - -#define SOFAE_LOG_INFO(fmt, ...) \ - printf("[INFO][%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) -#define SOFAE_LOG_WARN(fmt, ...) \ - printf("[WARN][%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) -#define SOFAE_LOG_ERROR(fmt, ...) \ - printf("[ERROR][%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) - -#endif // REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_LOG_H_ diff --git a/demos/remote_attestation/lib/include/sofaenclave/ra_conf.h b/demos/remote_attestation/lib/include/sofaenclave/ra_conf.h deleted file mode 100644 index 6cd12aa8..00000000 --- a/demos/remote_attestation/lib/include/sofaenclave/ra_conf.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_CONF_H_ -#define REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_CONF_H_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -std::string SofaeConfGetStr(const std::string& conf_file, const char* name, - const std::string& default_value = ""); -SofaeErrorCode SofaeConfGetStrArray(const std::string& conf_file, - const char* name, - std::vector* values); -SofaeErrorCode SofaeConfGetInt(const std::string& conf_file, const char* name, - int* value); - -#ifdef __cplusplus -} -#endif - -#endif // REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_CONF_H_ diff --git a/demos/remote_attestation/lib/include/sofaenclave/ra_device.h b/demos/remote_attestation/lib/include/sofaenclave/ra_device.h deleted file mode 100644 index a82013ae..00000000 --- a/demos/remote_attestation/lib/include/sofaenclave/ra_device.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_DEVICE_H_ -#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_DEVICE_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "sofaenclave/common/error.h" -#include "sofaenclave/common/type.h" - -namespace sofaenclave { -namespace occlum { - -SofaeErrorCode SgxDeviceGetGroupID(sgx_epid_group_id_t* gid); -SofaeErrorCode SgxDeviceGetQuote(SofaeQuoteArgs* quote_args); - -} // namespace occlum -} // namespace sofaenclave - -#endif // REMOTE_ATTESTATION_LIB_INCLUDE_RA_DEVICE_H_ diff --git a/demos/remote_attestation/lib/include/sofaenclave/ra_ias.h b/demos/remote_attestation/lib/include/sofaenclave/ra_ias.h deleted file mode 100644 index 5ccbfa72..00000000 --- a/demos/remote_attestation/lib/include/sofaenclave/ra_ias.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_IAS_H_ -#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_IAS_H_ - -#include -#include - -#include "./sgx_uae_epid.h" -#include "./sgx_urts.h" -#include "./sgx_utils.h" - -#include "curl/curl.h" - -#include "sofaenclave/common/error.h" -#include "sofaenclave/common/type.h" -#include "sofaenclave/ra_report.h" - -namespace sofaenclave { -namespace occlum { - -class RaIasClient { - public: - /// Connect to the HTTP IAS proxy server - explicit RaIasClient(const std::string& url); - - /// Connect to the HTTPS IAS - explicit RaIasClient(const SofaeServerCfg& ias_server); - - ~RaIasClient(); - - SofaeErrorCode GetSigRL(const sgx_epid_group_id_t& gid, std::string* sigrl); - SofaeErrorCode FetchReport(const std::string& quote, IasReport* ias_report); - - private: - void InitIasConnection(const std::string& url); - - CURL* curl_ = NULL; - curl_slist* headers_ = NULL; - std::string server_endpoint_; - - static std::mutex init_mutex_; -}; - -} // namespace occlum -} // namespace sofaenclave - -#endif // REMOTE_ATTESTATION_LIB_INCLUDE_RA_IAS_H_ diff --git a/demos/remote_attestation/lib/include/sofaenclave/ra_json.h b/demos/remote_attestation/lib/include/sofaenclave/ra_json.h deleted file mode 100644 index 31a79997..00000000 --- a/demos/remote_attestation/lib/include/sofaenclave/ra_json.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_JSON_H_ -#define REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_JSON_H_ - -#include -#include -#include -#include - -#include "rapidjson/document.h" - -#include "sofaenclave/common/error.h" -#include "sofaenclave/common/log.h" -#include "sofaenclave/common/type.h" - -namespace sofaenclave { -namespace occlum { - -typedef std::shared_ptr SofaeJsonDocPtr; -typedef std::map SofaeJsonConfMap; - -class JsonConfig { - public: - // Gets the singleton UnitTest object. - static JsonConfig* GetInstance(); - - // To support both rapidjson::Document and rapidjson::Value - template - static bool CheckString(const T& conf, const char* name); - template - static bool CheckArray(const T& conf, const char* name); - template - static bool CheckInt(const T& conf, const char* name); - template - static bool CheckObj(const T& conf, const char* name); - template - static std::string GetStr(const T& conf, const char* name, - const std::string& default_val = ""); - template - static SofaeErrorCode GetStrArray(const T& conf, const char* name, - std::vector* values); - template - static SofaeErrorCode GetInt(const T& conf, const char* name, int* value); - - // Load configuration files and then parse and get value(s) - std::string ConfGetStr(const std::string& conf_file, const char* name, - const std::string& default_val = ""); - SofaeErrorCode ConfGetStrArray(const std::string& conf_file, const char* name, - std::vector* values); - SofaeErrorCode ConfGetInt(const std::string& conf_file, const char* name, - int* value); - - private: - // Hide construction functions - JsonConfig() {} - JsonConfig(const JsonConfig&); - void operator=(JsonConfig const&); - - std::string GetConfigFilename(const std::string& filename); - SofaeErrorCode LoadConfiguration(const std::string& filename); - - SofaeJsonConfMap cfgs_; -}; - -} // namespace occlum -} // namespace sofaenclave - -#endif // REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_JSON_H_ diff --git a/demos/remote_attestation/lib/include/sofaenclave/ra_manager.h b/demos/remote_attestation/lib/include/sofaenclave/ra_manager.h deleted file mode 100644 index 498f9f07..00000000 --- a/demos/remote_attestation/lib/include/sofaenclave/ra_manager.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_MANAGER_H_ -#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_MANAGER_H_ - -#include - -#include "./sgx_quote.h" -#include "./sgx_report.h" -#include "./sgx_tseal.h" -#include "./sgx_urts.h" - -#include "sofaenclave/common/error.h" -#include "sofaenclave/common/type.h" - -#include "./ra_report.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initialization for getting enclave quote - * @param gid return GID for getting SigRL from attestation server - * @return Function run successfully or failed - * @retval 0 on success - * @retval Others when failed - */ -SofaeErrorCode InitializeQuote(sgx_epid_group_id_t* gid); - -/** - * @brief Get enclave quote for remote attestation - * @param quote_args All the input parameters required by get quote function. - * The output buffer is also in this structure. Please - * refer to the description of it in type.h header file. - * @return Function run successfully or failed - * @retval 0 on success - * @retval Others when failed - */ -SofaeErrorCode GetQuote(SofaeQuoteArgs* quote_args); - -/** - * @brief Fetch IAS report after ge. - * @param ias_server Specify the IAS server address, certificate and key. - * If HTTP proxy server is used, certificate and key are - * optional. - * @param gid input GID for getting SigRL from attestation server - * @param sigrl The string including the response from IAS - * @return Function run successfully or failed - * @retval 0 on success - * @retval Others when failed - */ -SofaeErrorCode FetchIasSigRL(const SofaeServerCfg& ias_server, - const sgx_epid_group_id_t& gid, - std::string* sigrl); - -/** - * @brief Fetch IAS report after get quote by GetQuote() function. - * @param ias_server Specify the IAS server address, certificate and key. - * If HTTP proxy server is used, certificate and key are - * optional. - * @param quote The input quote data returned by GetQuote() function - * @param ias_report The output IAS report strings wrapped by IasReport - * @return Function run successfully or failed - * @retval 0 on success - * @retval Others when failed - */ -SofaeErrorCode FetchIasReport(const SofaeServerCfg& ias_server, - sgx_quote_t* quote, - SofaeIasReport* ias_report); - -/** - * @brief All together to initialize quote, get quote and then fetch IAS report. - * @param ias_server Specify the IAS server address, certificate and key. - * If HTTP proxy server is used, certificate and key are - * optional. - * @param quote_args All the input parameters required by get quote function. - * The output buffer is also in this structure. Please - * refer to the description of it in type.h header file. - * @param ias_report The output IAS report strings wrapped by IasReport - * @return Function run successfully or failed - * @retval 0 on success - * @retval Others when failed - */ -SofaeErrorCode GetQuoteAndFetchIasReport(const SofaeServerCfg& ias_server, - SofaeQuoteArgs* quote_args, - SofaeIasReport* ias_report); - -#ifdef __cplusplus -} -#endif - -#endif // REMOTE_ATTESTATION_LIB_INCLUDE_RA_MANAGER_H_ diff --git a/demos/remote_attestation/lib/include/sofaenclave/ra_report.h b/demos/remote_attestation/lib/include/sofaenclave/ra_report.h deleted file mode 100644 index 4cc6fd3c..00000000 --- a/demos/remote_attestation/lib/include/sofaenclave/ra_report.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_REPORT_H_ -#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_REPORT_H_ - -#include - -namespace sofaenclave { -namespace occlum { - -#define DECLARE_IAS_REPORT_CLASS_MEMBER(x) \ - public: \ - std::string& x(); \ - const std::string& x() const; \ - void set_##x(const std::string& value); \ - void set_##x(const char* value); \ - void set_##x(const char* value, size_t size); \ - \ - private: \ - std::string x##_ - -class IasReport { - public: - IasReport() {} - ~IasReport() {} - - DECLARE_IAS_REPORT_CLASS_MEMBER(b64_signature); - DECLARE_IAS_REPORT_CLASS_MEMBER(signing_cert); - DECLARE_IAS_REPORT_CLASS_MEMBER(advisory_url); - DECLARE_IAS_REPORT_CLASS_MEMBER(advisory_ids); - DECLARE_IAS_REPORT_CLASS_MEMBER(response_body); - DECLARE_IAS_REPORT_CLASS_MEMBER(epid_pseudonym); - DECLARE_IAS_REPORT_CLASS_MEMBER(quote_status); - DECLARE_IAS_REPORT_CLASS_MEMBER(b16_platform_info_blob); - DECLARE_IAS_REPORT_CLASS_MEMBER(b64_quote_body); -}; - -} // namespace occlum -} // namespace sofaenclave - -// For coding convenience -using SofaeIasReport = sofaenclave::occlum::IasReport; - -#endif // REMOTE_ATTESTATION_LIB_INCLUDE_RA_REPORT_H_ diff --git a/demos/remote_attestation/lib/include/tee/common/error.h b/demos/remote_attestation/lib/include/tee/common/error.h new file mode 100644 index 00000000..3b49b46a --- /dev/null +++ b/demos/remote_attestation/lib/include/tee/common/error.h @@ -0,0 +1,43 @@ +#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_TEE_COMMON_ERROR_H_ +#define REMOTE_ATTESTATION_LIB_INCLUDE_TEE_COMMON_ERROR_H_ + +/* clang-format off */ + +/* Define TeeErrorCode to include the error code + * from both Intel SDK and ourself code */ +typedef int TeeErrorCode; + +#define TEE_MK_ERROR(x) (0xFFFF0000&((x) << 16)) + +#define TEE_SUCCESS (0x00000000) + +#define TEE_ERROR_GENERIC TEE_MK_ERROR(0x0001) +#define TEE_ERROR_PARAMETERS TEE_MK_ERROR(0x0002) +#define TEE_ERROR_MALLOC TEE_MK_ERROR(0x0003) +#define TEE_ERROR_ENCLAVE_NOTINITIALIZED TEE_MK_ERROR(0x0004) +#define TEE_ERROR_REPORT_DATA_SIZE TEE_MK_ERROR(0x0005) +#define TEE_ERROR_PARSE_CONFIGURATIONS TEE_MK_ERROR(0x0006) +#define TEE_ERROR_PARSE_COMMANDLINE TEE_MK_ERROR(0x0007) + +#define TEE_ERROR_FILE_OPEN TEE_MK_ERROR(0x0101) +#define TEE_ERROR_FILE_READ TEE_MK_ERROR(0x0102) +#define TEE_ERROR_FILE_WRITE TEE_MK_ERROR(0x0103) + +#define TEE_ERROR_CONF_LOAD TEE_MK_ERROR(0x0201) +#define TEE_ERROR_CONF_NOTEXIST TEE_MK_ERROR(0x0202) + +#define TEE_ERROR_IAS_CLIENT_INIT TEE_MK_ERROR(0x0501) +#define TEE_ERROR_IAS_CLIENT_CONNECT TEE_MK_ERROR(0x0502) +#define TEE_ERROR_IAS_CLIENT_GETSIGRL TEE_MK_ERROR(0x0503) +#define TEE_ERROR_IAS_CLIENT_GETREPORT TEE_MK_ERROR(0x0504) +#define TEE_ERROR_IAS_CLIENT_UNESCAPE TEE_MK_ERROR(0x0505) +#define TEE_ERROR_IAS_LOAD_CACHED_REPORT TEE_MK_ERROR(0x0506) + +#define TEE_ERROR_SDK_UNEXPECTED TEE_MK_ERROR(0x0FFF) + +#define TEE_ERROR_CODE(rc) (rc) +#define TEE_ERROR_MERGE(ecallcode, retcode) ((ecallcode) | (retcode)) + +/* clang-format on */ + +#endif // REMOTE_ATTESTATION_LIB_INCLUDE_TEE_COMMON_ERROR_H_ diff --git a/demos/remote_attestation/lib/include/tee/common/log.h b/demos/remote_attestation/lib/include/tee/common/log.h new file mode 100644 index 00000000..d9b3d52f --- /dev/null +++ b/demos/remote_attestation/lib/include/tee/common/log.h @@ -0,0 +1,46 @@ +#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_TEE_COMMON_LOG_H_ +#define REMOTE_ATTESTATION_LIB_INCLUDE_TEE_COMMON_LOG_H_ + +#include + +extern "C" int printf(const char* fmt, ...); + +#ifdef DEBUG +#define TEE_LOG_DEBUG(fmt, ...) \ + printf("[DEBUG][%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define TEE_LOG_BUFFER(name, ptr, size) \ + do { \ + const uint8_t* buffer = reinterpret_cast(ptr); \ + int len = static_cast((size)); \ + printf("Buffer %s[%p], length: %d(0x%x)\n", (name), buffer, len, len); \ + for (int i = 0; i < len; i++) { \ + if (i && (0 == i % 16)) printf("\n"); \ + printf("%02x ", buffer[i]); \ + } \ + printf("\n"); \ + } while (0) + +#else +#define TEE_LOG_DEBUG(fmt, ...) +#define TEE_LOG_BUFFER(name, ptr, size) +#endif + +#define TEE_LOG_INFO(fmt, ...) \ + printf("[INFO][%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define TEE_LOG_WARN(fmt, ...) \ + printf("[WARN][%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#define TEE_LOG_ERROR(fmt, ...) \ + printf("[ERROR][%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) + +#define TEE_LOG_ERROR_TRACE() TEE_LOG_ERROR("[Function] %s", __FUNCTION__) + +#define TEE_CHECK_RETURN(r) \ + do { \ + int ret = (r); \ + if (ret != 0) { \ + TEE_LOG_ERROR_TRACE(); \ + return ret; \ + } \ + } while (0) + +#endif // REMOTE_ATTESTATION_LIB_INCLUDE_TEE_COMMON_LOG_H_ diff --git a/demos/remote_attestation/lib/include/sofaenclave/common/type.h b/demos/remote_attestation/lib/include/tee/common/type.h similarity index 66% rename from demos/remote_attestation/lib/include/sofaenclave/common/type.h rename to demos/remote_attestation/lib/include/tee/common/type.h index 7ea94363..ac18aae8 100644 --- a/demos/remote_attestation/lib/include/sofaenclave/common/type.h +++ b/demos/remote_attestation/lib/include/tee/common/type.h @@ -1,5 +1,5 @@ -#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_TYPE_H_ -#define REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_TYPE_H_ +#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_TEE_COMMON_TYPE_H_ +#define REMOTE_ATTESTATION_LIB_INCLUDE_TEE_COMMON_TYPE_H_ #include @@ -10,10 +10,12 @@ #define RCAST(t, v) reinterpret_cast((v)) #define SCAST(t, v) static_cast((v)) #define CCAST(t, v) const_cast((v)) +#define RCCAST(t, v) reinterpret_cast(const_cast((v))) -#define SOFAE_UNREFERENCED_PARAMETER(p) static_cast((p)) - -typedef uint8_t SofaeEnclaveQuote[4096]; +#define TEE_UNREFERENCED_PARAMETER(p) \ + do { \ + static_cast((p)); \ + } while (0) /** * report_data Input report data which will be included in quote data. @@ -40,20 +42,20 @@ typedef struct { uint8_t* as_buf; sgx_quote_t* as_quote; } quote; // output -} SofaeQuoteArgs; +} EnclaveQuoteArgs; /** - * endpoint http://xxx.xxx.xxx.xxx: for HTTP IAS proxy server - * or https://xxx.xxx.xxx.xxx: for IAS server. Key and - * certificate must be provoided for HTTPS IAS server. - * cert Service provider certificate file path - * key Service provider private key file path + * endpoint https://xxx.xxx.xxx.xxx: for Intel Attestation Service. + * cert Service provider certificate file path. + * key Service provider private key file path. + * accesskey Service provider access key, see also here: + * https://api.portal.trustedservices.intel.com/EPID-attestation */ typedef struct { std::string endpoint; std::string cert; std::string key; std::string accesskey; -} SofaeServerCfg; +} RaIasServerCfg; -#endif // REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_TYPE_H_ +#endif // REMOTE_ATTESTATION_LIB_INCLUDE_TEE_COMMON_TYPE_H_ diff --git a/demos/remote_attestation/lib/include/tee/ra_conf_api.h b/demos/remote_attestation/lib/include/tee/ra_conf_api.h new file mode 100644 index 00000000..379c557c --- /dev/null +++ b/demos/remote_attestation/lib/include/tee/ra_conf_api.h @@ -0,0 +1,32 @@ +#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_TEE_RA_CONF_API_H_ +#define REMOTE_ATTESTATION_LIB_INCLUDE_TEE_RA_CONF_API_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// Get the string type option in configuration file +std::string TeeConfGetStr(const std::string& conf_file, const char* name, + const std::string& default_value = ""); + +/// If the value of option is filename in the configuration file, +/// use the function to read the file content and return it as string. +std::string TeeConfGetFileStr(const std::string& conf_file, const char* name, + const std::string& default_value = ""); + +/// Get the array type option in configuration file +TeeErrorCode TeeConfGetStrArray(const std::string& conf_file, const char* name, + std::vector* values); + +/// Get the integer type option in configuration file +TeeErrorCode TeeConfGetInt(const std::string& conf_file, const char* name, + int* value); + +#ifdef __cplusplus +} +#endif + +#endif // REMOTE_ATTESTATION_LIB_INCLUDE_TEE_RA_CONF_API_H_ diff --git a/demos/remote_attestation/lib/include/tee/ra_ias.h b/demos/remote_attestation/lib/include/tee/ra_ias.h new file mode 100644 index 00000000..bef5dc71 --- /dev/null +++ b/demos/remote_attestation/lib/include/tee/ra_ias.h @@ -0,0 +1,88 @@ +#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_IAS_H_ +#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_IAS_H_ + +#include +#include + +#include "./sgx_uae_epid.h" +#include "./sgx_urts.h" +#include "./sgx_utils.h" + +#include "curl/curl.h" + +#include "tee/common/error.h" +#include "tee/common/type.h" + +#define IAS_REPORT_CLASS_MEMBER(x) \ + public: \ + std::string& x() { \ + return x##_; \ + } \ + const std::string& x() const { \ + return x##_; \ + } \ + std::string* mutable_##x() { \ + return &x##_; \ + } \ + void set_##x(const std::string& value) { \ + x##_ = value; \ + } \ + void set_##x(const char* value) { \ + x##_ = value; \ + } \ + void set_##x(const char* value, size_t size) { \ + x##_ = value; \ + } \ + \ + private: \ + std::string x##_ + +namespace ra { +namespace occlum { + +/// Data structure to hold the IAS sigrl API response +typedef struct { + std::string b64_sigrl; +} RaIasSigrl; + +/// Data structure to hold the IAS sigrl API response +/// Use this class to simulate the protobuf class +/// don't need to introduce the protobuf dependency +class RaIasReport { + IAS_REPORT_CLASS_MEMBER(b64_signature); + IAS_REPORT_CLASS_MEMBER(signing_cert); + IAS_REPORT_CLASS_MEMBER(advisory_url); + IAS_REPORT_CLASS_MEMBER(advisory_ids); + IAS_REPORT_CLASS_MEMBER(response_body); + IAS_REPORT_CLASS_MEMBER(epid_pseudonym); + IAS_REPORT_CLASS_MEMBER(quote_status); + IAS_REPORT_CLASS_MEMBER(b16_platform_info_blob); + IAS_REPORT_CLASS_MEMBER(b64_quote_body); +}; + +/// HTTPS client for connecting to IAS +class RaIasClient { + public: + explicit RaIasClient(const RaIasServerCfg& ias_server); + ~RaIasClient(); + + /// api: /sigrl/ + TeeErrorCode GetSigRL(const sgx_epid_group_id_t& gid, std::string* sigrl); + + /// api: /report + TeeErrorCode FetchReport(const std::string& quote, RaIasReport* ias_report); + + private: + void InitIasConnection(const std::string& url); + + CURL* curl_ = NULL; + curl_slist* headers_ = NULL; + std::string server_endpoint_; + + static std::mutex init_mutex_; +}; + +} // namespace occlum +} // namespace ra + +#endif // REMOTE_ATTESTATION_LIB_INCLUDE_RA_IAS_H_ diff --git a/demos/remote_attestation/lib/include/tee/ra_json.h b/demos/remote_attestation/lib/include/tee/ra_json.h new file mode 100644 index 00000000..2a162542 --- /dev/null +++ b/demos/remote_attestation/lib/include/tee/ra_json.h @@ -0,0 +1,72 @@ +#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_TEE_RA_JSON_H_ +#define REMOTE_ATTESTATION_LIB_INCLUDE_TEE_RA_JSON_H_ + +#include +#include +#include +#include + +#include "rapidjson/document.h" + +#include "tee/common/error.h" +#include "tee/common/log.h" +#include "tee/common/type.h" + +namespace ra { +namespace occlum { + +typedef std::shared_ptr TeeJsonDocPtr; +typedef std::map TeeJsonConfMap; + +class JsonConfig { + public: + // Gets the singleton Unit Test object. + static JsonConfig* GetInstance(); + + // To support both rapidjson::Document and rapidjson::Value + template + static bool CheckString(const T& conf, const char* name); + template + static bool CheckArray(const T& conf, const char* name); + template + static bool CheckInt(const T& conf, const char* name); + template + static bool CheckObj(const T& conf, const char* name); + template + static std::string GetStr(const T& conf, const char* name, + const std::string& default_val = ""); + template + static TeeErrorCode GetStrArray(const T& conf, const char* name, + std::vector* values); + template + static TeeErrorCode GetInt(const T& conf, const char* name, int* value); + + // Load configuration files and then parse and get value(s) + std::string ConfGetStr(const std::string& conf_file, const char* name, + const std::string& default_val = ""); + std::string ConfGetFileStr(const std::string& conf_file, const char* name, + const std::string& default_val = ""); + TeeErrorCode ConfGetStrArray(const std::string& conf_file, const char* name, + std::vector* values); + TeeErrorCode ConfGetInt(const std::string& conf_file, const char* name, + int* value); + + private: + // Hide construction functions + JsonConfig() {} + JsonConfig(const JsonConfig&); + void operator=(JsonConfig const&); + + std::string ReadStringFile(const std::string& filename); + bool ConfigFileExists(const std::string& filename); + + std::string GetConfigFilename(const std::string& filename); + TeeErrorCode LoadConfiguration(const std::string& filename); + + TeeJsonConfMap cfgs_; +}; + +} // namespace occlum +} // namespace ra + +#endif // REMOTE_ATTESTATION_LIB_INCLUDE_TEE_RA_JSON_H_ diff --git a/demos/remote_attestation/lib/include/tee/ra_quote.h b/demos/remote_attestation/lib/include/tee/ra_quote.h new file mode 100644 index 00000000..ad4eebad --- /dev/null +++ b/demos/remote_attestation/lib/include/tee/ra_quote.h @@ -0,0 +1,51 @@ +#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_QUOTE_H_ +#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_QUOTE_H_ + +#include +#include + +#include "./sgx_quote.h" +#include "./sgx_report.h" +#include "./sgx_tseal.h" +#include "./sgx_urts.h" + +#include "tee/common/error.h" +#include "tee/common/type.h" + +#include "tee/ra_ias.h" + +namespace ra { +namespace occlum { + +class RaEnclaveQuote { + public: + // The methods that warp the ioctl device interfaces + static TeeErrorCode SgxDeviceInitQuote(sgx_epid_group_id_t* gid); + static TeeErrorCode SgxDeviceGetQuote(EnclaveQuoteArgs* quote_args); + + // The methods which are higher wrapper of quote and IasClient together. + TeeErrorCode GetEnclaveQuoteB64(const RaIasServerCfg& ias_server, + const std::string& spid, + const sgx_report_data_t& report_data, + std::string* quote_b64); + TeeErrorCode GetEnclaveIasReport(const RaIasServerCfg& ias_server, + const std::string& spid, + const sgx_report_data_t& report_data, + RaIasReport* ias_report); + + private: + uint8_t Hex2Dec(const char hex); + TeeErrorCode GetSpidFromHexStr(const std::string& spid_str); + TeeErrorCode GetIasSigRL(const RaIasServerCfg& ias_server); + TeeErrorCode GetEnclaveQuote(const RaIasServerCfg& ias_server, + const std::string& spid, + const sgx_report_data_t& report_data); + + std::vector quote_buf_; + EnclaveQuoteArgs quote_args_; +}; + +} // namespace occlum +} // namespace ra + +#endif // REMOTE_ATTESTATION_LIB_INCLUDE_RA_QUOTE_H_ diff --git a/demos/remote_attestation/lib/include/tee/ra_quote_api.h b/demos/remote_attestation/lib/include/tee/ra_quote_api.h new file mode 100644 index 00000000..c16b4403 --- /dev/null +++ b/demos/remote_attestation/lib/include/tee/ra_quote_api.h @@ -0,0 +1,44 @@ +/** + * @brief This header file provides the C APIs to use /dev/sgx device directly. + * + * As a C++ language developer, you can also use the C++ classes declared + * in ra_quote.h file. The C++ classes provide more convenient metheds. + */ + +#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_QUOTE_API_H_ +#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_QUOTE_API_H_ + +#include + +#include "tee/common/error.h" +#include "tee/common/type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialization for getting enclave quote + * @param gid return GID for getting SigRL from attestation server + * @return Function run successfully or failed + * @retval 0 on success + * @retval Others when failed + */ +TeeErrorCode InitializeQuote(sgx_epid_group_id_t* gid); + +/** + * @brief Get enclave quote for remote attestation + * @param quote_args All the input parameters required by get quote function. + * The output buffer is also in this structure. Please + * refer to the description of it in type.h header file. + * @return Function run successfully or failed + * @retval 0 on success + * @retval Others when failed + */ +TeeErrorCode GetQuote(EnclaveQuoteArgs* quote_args); + +#ifdef __cplusplus +} +#endif + +#endif // REMOTE_ATTESTATION_LIB_INCLUDE_RA_MANAGER_API_H_ diff --git a/demos/remote_attestation/lib/src/ra_device.cpp b/demos/remote_attestation/lib/src/ra_device.cpp deleted file mode 100644 index 9804d651..00000000 --- a/demos/remote_attestation/lib/src/ra_device.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include - -#include "sofaenclave/common/error.h" -#include "sofaenclave/common/log.h" -#include "sofaenclave/ra_device.h" - -namespace sofaenclave { -namespace occlum { - -#define SGXIOC_GET_EPID_GROUP_ID _IOR('s', 1, sgx_epid_group_id_t) -#define SGXIOC_GEN_QUOTE _IOWR('s', 2, SofaeQuoteArgs) - -constexpr char kSgxDeviceName[] = "/dev/sgx"; - -SofaeErrorCode SgxDeviceGetGroupID(sgx_epid_group_id_t* gid) { - int sgx_fd; - if ((sgx_fd = open(kSgxDeviceName, O_RDONLY)) < 0) { - SOFAE_LOG_ERROR("Fail to open %s", kSgxDeviceName); - return SOFAE_ERROR_FILE_OPEN; - } - - SofaeErrorCode ret = SOFAE_SUCCESS; - if (ioctl(sgx_fd, SGXIOC_GET_EPID_GROUP_ID, gid) < 0) { - SOFAE_LOG_ERROR("Fail to get group id from %s", kSgxDeviceName); - ret = SOFAE_ERROR_SDK_UNEXPECTED; - } - - close(sgx_fd); - return ret; -} - -SofaeErrorCode SgxDeviceGetQuote(SofaeQuoteArgs* quote_args) { - int sgx_fd; - if ((sgx_fd = open(kSgxDeviceName, O_RDONLY)) < 0) { - SOFAE_LOG_ERROR("Fail to open %s", kSgxDeviceName); - return SOFAE_ERROR_FILE_OPEN; - } - - SofaeErrorCode ret = SOFAE_SUCCESS; - int count = 3; - while (count--) { - if (ioctl(sgx_fd, SGXIOC_GEN_QUOTE, quote_args) == 0) { - uint32_t signature_len = quote_args->quote.as_quote->signature_len; - SOFAE_LOG_DEBUG("SgxDeviceGetQuote length=%ld", signature_len); - if (signature_len == 0) { - SOFAE_LOG_ERROR("Invalid quote from %s", kSgxDeviceName); - ret = SOFAE_ERROR_SDK_UNEXPECTED; - } - break; - } - else if (errno != EAGAIN) { - SOFAE_LOG_ERROR("Fail to get quote from %s", kSgxDeviceName); - ret = SOFAE_ERROR_SDK_UNEXPECTED; - break; - } - else { - SOFAE_LOG_WARN("/dev/sgx is temporarily busy. Try again after 1s."); - sleep(1); - } - } - - close(sgx_fd); - return ret; -} - -} // namespace occlum -} // namespace sofaenclave diff --git a/demos/remote_attestation/lib/src/ra_ias.cpp b/demos/remote_attestation/lib/src/ra_ias.cpp index f97068c2..3808a0a7 100644 --- a/demos/remote_attestation/lib/src/ra_ias.cpp +++ b/demos/remote_attestation/lib/src/ra_ias.cpp @@ -2,17 +2,18 @@ #include #include -#include "sofaenclave/common/error.h" -#include "sofaenclave/common/log.h" -#include "sofaenclave/common/type.h" -#include "sofaenclave/ra_json.h" -#include "sofaenclave/ra_ias.h" +#include "tee/common/error.h" +#include "tee/common/log.h" +#include "tee/common/type.h" + +#include "tee/ra_ias.h" +#include "tee/ra_json.h" // use cppcodec/base64 #include "cppcodec/base64_rfc4648.hpp" using base64 = cppcodec::base64_rfc4648; -namespace sofaenclave { +namespace ra { namespace occlum { constexpr char kStrEpidPseudonym[] = "epidPseudonym"; @@ -26,11 +27,7 @@ constexpr char kStrHeaderCaAk[] = "X-IASReport-Signing-Certificate:"; constexpr char kStrHeaderAdvisoryUrl[] = "advisory-url:"; constexpr char kStrHeaderAdvisoryIDs[] = "advisory-ids:"; -typedef struct { - std::string b64_sigrl; -} SofaeIasSigrl; - -static std::string GetHeaderValue(const char *header, const char *name) { +static std::string GetHeaderValue(const char* header, const char* name) { std::string header_str = header; std::string ending("\n\r"); @@ -47,14 +44,14 @@ static std::string GetHeaderValue(const char *header, const char *name) { static size_t ParseSigrlResponseBody(const void* contents, size_t size, size_t nmemb, void* response) { size_t content_length = size * nmemb; - SofaeIasSigrl *sigrl = RCAST(SofaeIasSigrl *, response); + RaIasSigrl* sigrl = RCAST(RaIasSigrl*, response); if (content_length == 0) { sigrl->b64_sigrl.clear(); - SOFAE_LOG_DEBUG("GetSigRL: Empty"); + TEE_LOG_DEBUG("GetSigRL: Empty"); } else { - sigrl->b64_sigrl.assign(RCAST(const char *, contents), content_length); - SOFAE_LOG_DEBUG("GetSigRL: %s", sigrl->b64_sigrl.c_str()); + sigrl->b64_sigrl.assign(RCAST(const char*, contents), content_length); + TEE_LOG_DEBUG("GetSigRL: %s", sigrl->b64_sigrl.c_str()); } return content_length; } @@ -62,28 +59,29 @@ static size_t ParseSigrlResponseBody(const void* contents, size_t size, static size_t ParseSigrlResponseHeader(const void* contents, size_t size, size_t nmemb, void* response) { size_t len = size * nmemb; - const char *header = RCAST(const char *, contents); + const char* header = RCAST(const char*, contents); - SOFAE_LOG_DEBUG("IAS Get SigRL %s", header); + TEE_LOG_DEBUG("IAS Get SigRL %s", header); return len; } static size_t ParseReportResponseBody(const void* contents, size_t size, size_t nmemb, void* response) { - const char *body = RCAST(const char *, contents); + const char* body = RCAST(const char*, contents); size_t content_length = size * nmemb; - IasReport *report = RCAST(IasReport *, response); + RaIasReport* report = RCAST(RaIasReport*, response); - report->set_response_body(body, content_length); + // The json response body maybe will be splited into two times + report->mutable_response_body()->append(body, content_length); rapidjson::Document doc; - if (doc.Parse(body).HasParseError()) { - SOFAE_LOG_ERROR("Fail to parse report response body"); - } else { + if (!doc.Parse(report->response_body().data()).HasParseError()) { report->set_epid_pseudonym(JsonConfig::GetStr(doc, kStrEpidPseudonym)); report->set_quote_status(JsonConfig::GetStr(doc, kStrQuoteStatus)); report->set_b16_platform_info_blob(JsonConfig::GetStr(doc, kStrPlatform)); report->set_b64_quote_body(JsonConfig::GetStr(doc, kStrQuoteBody)); + } else if (body[content_length - 1] == '}') { + TEE_LOG_ERROR("Fail to parse report response body"); } return content_length; @@ -92,8 +90,8 @@ static size_t ParseReportResponseBody(const void* contents, size_t size, static size_t ParseReportResponseHeader(const void* contents, size_t size, size_t nmemb, void* response) { size_t len = size * nmemb; - const char *header = RCAST(const char *, contents); - IasReport *report = RCAST(IasReport *, response); + const char* header = RCAST(const char*, contents); + RaIasReport* report = RCAST(RaIasReport*, response); if (strncmp(header, kStrHeaderSig, strlen(kStrHeaderSig)) == 0) { report->set_b64_signature(GetHeaderValue(header, kStrHeaderSig)); @@ -156,11 +154,7 @@ void RaIasClient::InitIasConnection(const std::string& endpoint) { server_endpoint_ = endpoint; } -RaIasClient::RaIasClient(const std::string& endpoint) { - InitIasConnection(endpoint); -} - -RaIasClient::RaIasClient(const SofaeServerCfg& ias_server) { +RaIasClient::RaIasClient(const RaIasServerCfg& ias_server) { // Configure the other normal settings firstly. InitIasConnection(ias_server.endpoint); @@ -172,11 +166,11 @@ RaIasClient::RaIasClient(const SofaeServerCfg& ias_server) { headers_ = curl_slist_append(headers_, header_access_key.c_str()); } - if (curl_ && (ias_server.endpoint.find("https://") != std::string::npos) && \ + if (curl_ && (ias_server.endpoint.find("https://") != std::string::npos) && (ias_server.accesskey.empty())) { - const char *ias_cert_key_type = "PEM"; - SOFAE_LOG_DEBUG("IAS cert: %s", ias_server.cert.c_str()); - SOFAE_LOG_DEBUG("IAS key: %s", ias_server.key.c_str()); + const char* ias_cert_key_type = "PEM"; + TEE_LOG_DEBUG("IAS cert: %s", ias_server.cert.c_str()); + TEE_LOG_DEBUG("IAS key: %s", ias_server.key.c_str()); curl_easy_setopt(curl_, CURLOPT_SSLCERT, ias_server.cert.c_str()); curl_easy_setopt(curl_, CURLOPT_SSLKEY, ias_server.key.c_str()); @@ -200,11 +194,11 @@ RaIasClient::~RaIasClient() { } } -SofaeErrorCode RaIasClient::GetSigRL(const sgx_epid_group_id_t& gid, - std::string *sigrl) { +TeeErrorCode RaIasClient::GetSigRL(const sgx_epid_group_id_t& gid, + std::string* sigrl) { if (!curl_) { - SOFAE_LOG_ERROR("IAS client is not initialized"); - return SOFAE_ERROR_IAS_CLIENT_INIT; + TEE_LOG_ERROR("IAS client is not initialized"); + return TEE_ERROR_IAS_CLIENT_INIT; } /* Set the URL */ @@ -213,20 +207,20 @@ SofaeErrorCode RaIasClient::GetSigRL(const sgx_epid_group_id_t& gid, snprintf(tmp_gid_vec.data(), tmp_gid_vec.size(), "%02X%02X%02X%02X", gid[3], gid[2], gid[1], gid[0]); url += std::string(tmp_gid_vec.data()); - SOFAE_LOG_DEBUG("URL: %s", url.c_str()); + TEE_LOG_DEBUG("URL: %s", url.c_str()); curl_easy_setopt(curl_, CURLOPT_URL, url.c_str()); /* Set the sigrl request header and body handler function and data */ - SofaeIasSigrl ias_sigrl; + RaIasSigrl ias_sigrl; curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, ParseSigrlResponseBody); curl_easy_setopt(curl_, CURLOPT_HEADERFUNCTION, ParseSigrlResponseHeader); - curl_easy_setopt(curl_, CURLOPT_WRITEDATA, RCAST(void *, &ias_sigrl)); - curl_easy_setopt(curl_, CURLOPT_WRITEHEADER, RCAST(void *, &ias_sigrl)); + curl_easy_setopt(curl_, CURLOPT_WRITEDATA, RCAST(void*, &ias_sigrl)); + curl_easy_setopt(curl_, CURLOPT_WRITEHEADER, RCAST(void*, &ias_sigrl)); CURLcode rc = curl_easy_perform(curl_); if (rc != CURLE_OK) { - SOFAE_LOG_ERROR("Fail to connect server: %s\n", curl_easy_strerror(rc)); - return SOFAE_ERROR_IAS_CLIENT_CONNECT; + TEE_LOG_ERROR("Fail to connect server: %s\n", curl_easy_strerror(rc)); + return TEE_ERROR_IAS_CLIENT_CONNECT; } if (!ias_sigrl.b64_sigrl.empty()) { @@ -234,37 +228,37 @@ SofaeErrorCode RaIasClient::GetSigRL(const sgx_epid_group_id_t& gid, try { sigrl_vec = base64::decode(ias_sigrl.b64_sigrl); } catch (std::exception& e) { - SOFAE_LOG_ERROR("Cannot decode base64 sigrl: %s", e.what()); - return SOFAE_ERROR_IAS_CLIENT_GETSIGRL; + TEE_LOG_ERROR("Cannot decode base64 sigrl: %s", e.what()); + return TEE_ERROR_IAS_CLIENT_GETSIGRL; } - sigrl->assign(RCAST(const char *, sigrl_vec.data()), sigrl_vec.size()); + sigrl->assign(RCAST(const char*, sigrl_vec.data()), sigrl_vec.size()); } - return SOFAE_SUCCESS; + return TEE_SUCCESS; } -SofaeErrorCode RaIasClient::FetchReport(const std::string& quote, - IasReport *ias_report) { +TeeErrorCode RaIasClient::FetchReport(const std::string& quote, + RaIasReport* ias_report) { /* should not be empty is not to use cache */ if (quote.empty()) { - SOFAE_LOG_ERROR("Invalid base64 quote value"); - return SOFAE_ERROR_PARAMETERS; + TEE_LOG_ERROR("Invalid base64 quote value"); + return TEE_ERROR_PARAMETERS; } if (!curl_) { - SOFAE_LOG_ERROR("IAS client is not initialized!"); - return SOFAE_ERROR_IAS_CLIENT_INIT; + TEE_LOG_ERROR("IAS client is not initialized!"); + return TEE_ERROR_IAS_CLIENT_INIT; } /* Set the report url */ std::string url = server_endpoint_ + "/report"; - SOFAE_LOG_DEBUG("URL: %s", url.c_str()); + TEE_LOG_DEBUG("URL: %s", url.c_str()); curl_easy_setopt(curl_, CURLOPT_URL, url.c_str()); /* Set the post data */ - SOFAE_LOG_DEBUG("Quote length: %ld", quote.length()); - std::string b64_quote = base64::encode(RCAST(const char *, quote.c_str()), + TEE_LOG_DEBUG("Quote length: %ld", quote.length()); + std::string b64_quote = base64::encode(RCAST(const char*, quote.c_str()), SCAST(size_t, quote.length())); - SOFAE_LOG_DEBUG("QUTEO[%lu]: %s", b64_quote.length(), b64_quote.c_str()); + TEE_LOG_DEBUG("QUTEO[%lu]: %s", b64_quote.length(), b64_quote.c_str()); std::string post_data = "{\"isvEnclaveQuote\": \""; post_data += b64_quote; post_data += "\"}"; @@ -273,35 +267,35 @@ SofaeErrorCode RaIasClient::FetchReport(const std::string& quote, /* Set the report request header and body handler function and data */ curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, ParseReportResponseBody); curl_easy_setopt(curl_, CURLOPT_HEADERFUNCTION, ParseReportResponseHeader); - curl_easy_setopt(curl_, CURLOPT_WRITEDATA, RCAST(void *, ias_report)); - curl_easy_setopt(curl_, CURLOPT_WRITEHEADER, RCAST(void *, ias_report)); + curl_easy_setopt(curl_, CURLOPT_WRITEDATA, RCAST(void*, ias_report)); + curl_easy_setopt(curl_, CURLOPT_WRITEHEADER, RCAST(void*, ias_report)); CURLcode rc = curl_easy_perform(curl_); if (rc != CURLE_OK) { - SOFAE_LOG_ERROR("Fail to connect server: %s\n", curl_easy_strerror(rc)); - return SOFAE_ERROR_IAS_CLIENT_CONNECT; + TEE_LOG_ERROR("Fail to connect server: %s\n", curl_easy_strerror(rc)); + return TEE_ERROR_IAS_CLIENT_CONNECT; } /* deal with the escaped certificates */ std::string signing_cert = ias_report->signing_cert(); if (!signing_cert.empty()) { int unescape_len = 0; - char *p_unescape = curl_easy_unescape(curl_, signing_cert.data(), + char* p_unescape = curl_easy_unescape(curl_, signing_cert.data(), signing_cert.length(), &unescape_len); if (p_unescape && unescape_len) { ias_report->set_signing_cert(p_unescape, unescape_len); curl_free(p_unescape); } else { - SOFAE_LOG_ERROR("Fail to convert the escaped certificate in response."); - return SOFAE_ERROR_IAS_CLIENT_UNESCAPE; + TEE_LOG_ERROR("Fail to convert the escaped certificate in response."); + return TEE_ERROR_IAS_CLIENT_UNESCAPE; } } else { - SOFAE_LOG_ERROR("Fail to get quote report from IAS"); - return SOFAE_ERROR_IAS_CLIENT_GETREPORT; + TEE_LOG_ERROR("Fail to get quote report from IAS"); + return TEE_ERROR_IAS_CLIENT_GETREPORT; } - return SOFAE_SUCCESS; + return TEE_SUCCESS; } } // namespace occlum -} // namespace sofaenclave +} // namespace ra diff --git a/demos/remote_attestation/lib/src/ra_json.cpp b/demos/remote_attestation/lib/src/ra_json.cpp index 74e4a9a6..16da4dad 100644 --- a/demos/remote_attestation/lib/src/ra_json.cpp +++ b/demos/remote_attestation/lib/src/ra_json.cpp @@ -3,19 +3,20 @@ #include #include -#include "sofaenclave/common/error.h" -#include "sofaenclave/common/log.h" -#include "sofaenclave/ra_json.h" +#include "tee/common/error.h" +#include "tee/common/log.h" +#include "tee/ra_json.h" -namespace sofaenclave { +namespace ra { namespace occlum { -static SofaeErrorCode FsReadString(const std::string& filename, - std::string* str) { +std::string JsonConfig::ReadStringFile(const std::string& filename) { + std::string str; + std::ifstream ifs(filename, std::ios::binary | std::ios::in); if (!ifs) { - SOFAE_LOG_ERROR("Fail to open file \"%s\"\n", filename.c_str()); - return SOFAE_ERROR_FILE_OPEN; + TEE_LOG_ERROR("Fail to open file \"%s\"\n", filename.c_str()); + return str; } ifs.seekg(0, std::ios::end); @@ -25,15 +26,15 @@ static SofaeErrorCode FsReadString(const std::string& filename, std::vector buf(length); ifs.read(buf.data(), length); if (ifs.fail()) { - SOFAE_LOG_ERROR("Fail to read file \"%s\"\n", filename.c_str()); - return SOFAE_ERROR_FILE_READ; + TEE_LOG_ERROR("Fail to read file \"%s\"\n", filename.c_str()); + return str; } - str->assign(buf.data(), length); - return SOFAE_SUCCESS; + str.assign(buf.data(), length); + return str; } -static bool FsFileExists(const std::string& filename) { +bool JsonConfig::ConfigFileExists(const std::string& filename) { std::ifstream ifs(filename, std::ios::binary | std::ios::in); return ifs.good(); } @@ -46,7 +47,7 @@ JsonConfig* JsonConfig::GetInstance() { template bool JsonConfig::CheckString(const T& conf, const char* name) { if (!conf.HasMember(name) || !conf[name].IsString()) { - SOFAE_LOG_DEBUG("%s is missed or not string in config file", name); + TEE_LOG_DEBUG("%s is missed or not string in config file", name); return false; } return true; @@ -55,7 +56,7 @@ bool JsonConfig::CheckString(const T& conf, const char* name) { template bool JsonConfig::CheckArray(const T& conf, const char* name) { if (!conf.HasMember(name) || !conf[name].IsArray()) { - SOFAE_LOG_DEBUG("%s is missed or not array in config file", name); + TEE_LOG_DEBUG("%s is missed or not array in config file", name); return false; } return true; @@ -64,7 +65,7 @@ bool JsonConfig::CheckArray(const T& conf, const char* name) { template bool JsonConfig::CheckInt(const T& conf, const char* name) { if (!conf.HasMember(name) || !conf[name].IsInt()) { - SOFAE_LOG_DEBUG("%s is missed or not integer in config file", name); + TEE_LOG_DEBUG("%s is missed or not integer in config file", name); return false; } return true; @@ -73,7 +74,7 @@ bool JsonConfig::CheckInt(const T& conf, const char* name) { template bool JsonConfig::CheckObj(const T& conf, const char* name) { if (!conf.HasMember(name) || !conf[name].IsObject()) { - SOFAE_LOG_DEBUG("%s is missed or not object in config file", name); + TEE_LOG_DEBUG("%s is missed or not object in config file", name); return false; } return true; @@ -84,106 +85,106 @@ std::string JsonConfig::GetStr(const T& conf, const char* name, const std::string& default_val) { if (CheckString(conf, name)) { std::string value = conf[name].GetString(); - SOFAE_LOG_DEBUG("%s=%s", name, value.c_str()); + TEE_LOG_DEBUG("%s=%s", name, value.c_str()); return value; } else { - SOFAE_LOG_DEBUG("Not string type, %s=%s[default]", name, default_val); + TEE_LOG_DEBUG("Not string type, %s=%s[default]", name, default_val); return default_val; } } template -SofaeErrorCode JsonConfig::GetStrArray(const T& conf, const char* name, - std::vector* values) { +TeeErrorCode JsonConfig::GetStrArray(const T& conf, const char* name, + std::vector* values) { if (CheckArray(conf, name)) { const rapidjson::Value& val_array = conf[name]; size_t count = val_array.Size(); for (size_t i = 0; i < count; i++) { if (val_array[i].IsString()) { std::string val_str = val_array[i].GetString(); - SOFAE_LOG_DEBUG("%s[%ld]=%s", name, i, val_str.c_str()); + TEE_LOG_DEBUG("%s[%ld]=%s", name, i, val_str.c_str()); values->push_back(val_str); } else { - SOFAE_LOG_ERROR("Invalid string type in Array"); - return SOFAE_ERROR_PARSE_CONFIGURATIONS; + TEE_LOG_ERROR("Invalid string type in Array"); + return TEE_ERROR_PARSE_CONFIGURATIONS; } } } else { - SOFAE_LOG_DEBUG("Invalid Array type"); - return SOFAE_ERROR_PARSE_CONFIGURATIONS; + TEE_LOG_DEBUG("Invalid Array type"); + return TEE_ERROR_PARSE_CONFIGURATIONS; } - return SOFAE_SUCCESS; + return TEE_SUCCESS; } template -SofaeErrorCode JsonConfig::GetInt(const T& conf, const char* name, int* value) { +TeeErrorCode JsonConfig::GetInt(const T& conf, const char* name, int* value) { if (!CheckInt(conf, name)) { - SOFAE_LOG_ERROR("Not integer type: %s", name); - return SOFAE_ERROR_PARSE_CONFIGURATIONS; + TEE_LOG_ERROR("Not integer type: %s", name); + return TEE_ERROR_PARSE_CONFIGURATIONS; } *value = conf[name].GetInt(); - SOFAE_LOG_DEBUG("%s=%d", name, *value); - return SOFAE_SUCCESS; + TEE_LOG_DEBUG("%s=%d", name, *value); + return TEE_SUCCESS; } std::string JsonConfig::GetConfigFilename(const std::string& filename) { // First priority, the absolute path filename or file in current directory - if (FsFileExists(filename)) { - SOFAE_LOG_DEBUG("Configuration file: %s", filename.c_str()); + if (ConfigFileExists(filename)) { + TEE_LOG_DEBUG("Configuration file: %s", filename.c_str()); return filename; } // Finally, try to find configuration file in /etc directory std::string etcpath = "/etc/"; etcpath += filename; - if (FsFileExists(etcpath)) { - SOFAE_LOG_DEBUG("Configuration file: %s", etcpath.c_str()); + if (ConfigFileExists(etcpath)) { + TEE_LOG_DEBUG("Configuration file: %s", etcpath.c_str()); return etcpath; } // If cannot find configuration file, return empty string - SOFAE_LOG_ERROR("Cannot find configuration file: %s", filename.c_str()); + TEE_LOG_ERROR("Cannot find configuration file: %s", filename.c_str()); return ""; } -SofaeErrorCode JsonConfig::LoadConfiguration(const std::string& filename) { +TeeErrorCode JsonConfig::LoadConfiguration(const std::string& filename) { if (filename.empty()) { - SOFAE_LOG_ERROR("Empty configuration file name"); - return SOFAE_ERROR_CONF_NOTEXIST; + TEE_LOG_ERROR("Empty configuration file name"); + return TEE_ERROR_CONF_NOTEXIST; } std::string config_file = GetConfigFilename(filename); if (config_file.empty()) { - SOFAE_LOG_ERROR("Fail to find configuration file"); - return SOFAE_ERROR_CONF_NOTEXIST; + TEE_LOG_ERROR("Fail to find configuration file"); + return TEE_ERROR_CONF_NOTEXIST; } - std::string config_str; - if (FsReadString(config_file, &config_str) != SOFAE_SUCCESS) { - SOFAE_LOG_ERROR("Fail to read configuration file"); - return SOFAE_ERROR_PARSE_CONFIGURATIONS; + std::string config_str = ReadStringFile(config_file); + if (config_str.empty()) { + TEE_LOG_ERROR("Fail to read configuration file"); + return TEE_ERROR_PARSE_CONFIGURATIONS; } - SofaeJsonDocPtr doc(new rapidjson::Document); + TeeJsonDocPtr doc(new rapidjson::Document); if (doc.get()->Parse(config_str.data()).HasParseError()) { - SOFAE_LOG_ERROR("Fail to parse json configration file"); - return SOFAE_ERROR_PARSE_CONFIGURATIONS; + TEE_LOG_ERROR("Fail to parse json configration file"); + return TEE_ERROR_PARSE_CONFIGURATIONS; } cfgs_.emplace(filename, doc); - SOFAE_LOG_DEBUG("Load configuration file %s successfully", filename.c_str()); - return SOFAE_SUCCESS; + TEE_LOG_DEBUG("Load configuration file %s successfully", filename.c_str()); + return TEE_SUCCESS; } std::string JsonConfig::ConfGetStr(const std::string& conf_file, const char* name, const std::string& default_val) { - SOFAE_LOG_DEBUG("Get %s from %s", name, conf_file.c_str()); + TEE_LOG_DEBUG("Get %s from %s", name, conf_file.c_str()); if (cfgs_.find(conf_file) == cfgs_.end()) { - if (LoadConfiguration(conf_file) != SOFAE_SUCCESS) { - SOFAE_LOG_DEBUG("Load config failed, %s=%s[default]", name, default_val); + if (LoadConfiguration(conf_file) != TEE_SUCCESS) { + TEE_LOG_DEBUG("Load config failed, %s=%s[default]", name, default_val); return default_val; } } @@ -191,29 +192,37 @@ std::string JsonConfig::ConfGetStr(const std::string& conf_file, return GetStr(*cfgs_[conf_file].get(), name, default_val); } -SofaeErrorCode JsonConfig::ConfGetStrArray(const std::string& conf_file, - const char* name, - std::vector* values) { - SOFAE_LOG_DEBUG("Get %s from %s", name, conf_file.c_str()); +std::string JsonConfig::ConfGetFileStr(const std::string& conf_file, + const char* name, + const std::string& default_val) { + TEE_LOG_DEBUG("Get string from %s", name); + std::string filename = ConfGetStr(conf_file, name, default_val); + return ReadStringFile(filename); +} + +TeeErrorCode JsonConfig::ConfGetStrArray(const std::string& conf_file, + const char* name, + std::vector* values) { + TEE_LOG_DEBUG("Get %s from %s", name, conf_file.c_str()); if (cfgs_.find(conf_file) == cfgs_.end()) { - if (LoadConfiguration(conf_file) != SOFAE_SUCCESS) { - SOFAE_LOG_DEBUG("Fail to load configuration file"); - return SOFAE_ERROR_PARSE_CONFIGURATIONS; + if (LoadConfiguration(conf_file) != TEE_SUCCESS) { + TEE_LOG_DEBUG("Fail to load configuration file"); + return TEE_ERROR_PARSE_CONFIGURATIONS; } } return GetStrArray(*cfgs_[conf_file].get(), name, values); } -SofaeErrorCode JsonConfig::ConfGetInt(const std::string& conf_file, - const char* name, int* value) { - SOFAE_LOG_DEBUG("Get %s from %s", name, conf_file.c_str()); +TeeErrorCode JsonConfig::ConfGetInt(const std::string& conf_file, + const char* name, int* value) { + TEE_LOG_DEBUG("Get %s from %s", name, conf_file.c_str()); if (cfgs_.find(conf_file) == cfgs_.end()) { - if (LoadConfiguration(conf_file) != SOFAE_SUCCESS) { - SOFAE_LOG_ERROR("Fail to load configuration file"); - return SOFAE_ERROR_PARSE_CONFIGURATIONS; + if (LoadConfiguration(conf_file) != TEE_SUCCESS) { + TEE_LOG_ERROR("Fail to load configuration file"); + return TEE_ERROR_PARSE_CONFIGURATIONS; } } @@ -221,29 +230,34 @@ SofaeErrorCode JsonConfig::ConfGetInt(const std::string& conf_file, } } // namespace occlum -} // namespace sofaenclave +} // namespace ra #ifdef __cplusplus extern "C" { #endif -std::string SofaeConfGetStr(const std::string& conf_file, const char* name, - const std::string& default_val) { - return sofaenclave::occlum::JsonConfig::GetInstance()->ConfGetStr( - conf_file, name, default_val); +std::string TeeConfGetStr(const std::string& conf_file, const char* name, + const std::string& default_val) { + return ra::occlum::JsonConfig::GetInstance()->ConfGetStr(conf_file, name, + default_val); } -SofaeErrorCode SofaeConfGetStrArray(const std::string& conf_file, - const char* name, - std::vector* values) { - return sofaenclave::occlum::JsonConfig::GetInstance()->ConfGetStrArray( - conf_file, name, values); +std::string TeeConfGetFileStr(const std::string& conf_file, const char* name, + const std::string& default_val) { + return ra::occlum::JsonConfig::GetInstance()->ConfGetFileStr(conf_file, name, + default_val); } -SofaeErrorCode SofaeConfGetInt(const std::string& conf_file, const char* name, - int* value) { - return sofaenclave::occlum::JsonConfig::GetInstance()->ConfGetInt( - conf_file, name, value); +TeeErrorCode TeeConfGetStrArray(const std::string& conf_file, const char* name, + std::vector* values) { + return ra::occlum::JsonConfig::GetInstance()->ConfGetStrArray(conf_file, name, + values); +} + +TeeErrorCode TeeConfGetInt(const std::string& conf_file, const char* name, + int* value) { + return ra::occlum::JsonConfig::GetInstance()->ConfGetInt(conf_file, name, + value); } #ifdef __cplusplus diff --git a/demos/remote_attestation/lib/src/ra_manager.cpp b/demos/remote_attestation/lib/src/ra_manager.cpp deleted file mode 100644 index b414be6c..00000000 --- a/demos/remote_attestation/lib/src/ra_manager.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include -#include - -#include "./sgx_quote.h" -#include "./sgx_tseal.h" - -#include "sofaenclave/common/error.h" -#include "sofaenclave/common/log.h" -#include "sofaenclave/common/type.h" -#include "sofaenclave/ra_device.h" -#include "sofaenclave/ra_ias.h" -#include "sofaenclave/ra_manager.h" - -// use cppcodec/base64 -#include "cppcodec/base64_rfc4648.hpp" -using base64 = cppcodec::base64_rfc4648; - -#ifdef __cplusplus -extern "C" { -#endif - -SofaeErrorCode InitializeQuote(sgx_epid_group_id_t* gid) { - return sofaenclave::occlum::SgxDeviceGetGroupID(gid); -} - -SofaeErrorCode GetQuote(SofaeQuoteArgs* quote_args) { - if (!quote_args->quote.as_buf || (quote_args->quote_buf_len == 0)) { - SOFAE_LOG_ERROR("Invalid quote buffer or len"); - return SOFAE_ERROR_PARAMETERS; - } - - return sofaenclave::occlum::SgxDeviceGetQuote(quote_args); -} - -SofaeErrorCode FetchIasSigRL(const SofaeServerCfg& ias_server, - const sgx_epid_group_id_t& gid, - std::string* sigrl) { - sofaenclave::occlum::RaIasClient ias_client(ias_server); - return ias_client.GetSigRL(gid, sigrl); -} - -SofaeErrorCode FetchIasReport(const SofaeServerCfg& ias_server, - sgx_quote_t* quote, - SofaeIasReport* ias_report) { - sofaenclave::occlum::RaIasClient ias_client(ias_server); - std::string quote_str(RCAST(char*, quote), - sizeof(sgx_quote_t) + quote->signature_len); - return ias_client.FetchReport(quote_str, ias_report); -} - -SofaeErrorCode GetQuoteAndFetchIasReport(const SofaeServerCfg& ias_server, - SofaeQuoteArgs* quote_args, - SofaeIasReport* ias_report) { - // Initialize the quote firstly - sgx_epid_group_id_t gid = {0}; - SofaeErrorCode ret = InitializeQuote(&gid); - if (ret != SOFAE_SUCCESS) { - return ret; - } - - // If there is no SigRL, try to fetch it. - if (!quote_args->sigrl_ptr || (quote_args->sigrl_len == 0)) { - std::string sigrl_str; - ret = FetchIasSigRL(ias_server, gid, &sigrl_str); - if (ret != SOFAE_SUCCESS) { - return ret; - } - if (!sigrl_str.empty()) { - quote_args->sigrl_ptr = RCAST(const uint8_t *, sigrl_str.data()); - quote_args->sigrl_len = sigrl_str.length(); - } - } - - // Get the quote, assuming quote buffer is allocated out of this function - ret = GetQuote(quote_args); - if (ret != SOFAE_SUCCESS) { - return ret; - } - - // Fetch the IAS report based on the quote output buffer - return FetchIasReport(ias_server, quote_args->quote.as_quote, ias_report); -} - -#ifdef __cplusplus -} -#endif diff --git a/demos/remote_attestation/lib/src/ra_quote.cpp b/demos/remote_attestation/lib/src/ra_quote.cpp new file mode 100644 index 00000000..58ba1d99 --- /dev/null +++ b/demos/remote_attestation/lib/src/ra_quote.cpp @@ -0,0 +1,209 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tee/common/log.h" + +#include "tee/ra_ias.h" +#include "tee/ra_quote.h" + +#include "cppcodec/base64_rfc4648.hpp" +#include "openssl/rand.h" +using base64 = cppcodec::base64_rfc4648; + +#define SGXIOC_GET_EPID_GROUP_ID _IOR('s', 1, sgx_epid_group_id_t) +#define SGXIOC_GEN_QUOTE _IOWR('s', 2, EnclaveQuoteArgs) + +constexpr char kSgxDeviceName[] = "/dev/sgx"; + +namespace ra { +namespace occlum { + +TeeErrorCode RaEnclaveQuote::SgxDeviceInitQuote(sgx_epid_group_id_t* gid) { + int sgx_fd; + if ((sgx_fd = open(kSgxDeviceName, O_RDONLY)) < 0) { + TEE_LOG_ERROR("Fail to open %s", kSgxDeviceName); + return TEE_ERROR_FILE_OPEN; + } + + TeeErrorCode ret = TEE_SUCCESS; + if (ioctl(sgx_fd, SGXIOC_GET_EPID_GROUP_ID, gid) < 0) { + TEE_LOG_ERROR("Fail to get group id from %s", kSgxDeviceName); + ret = TEE_ERROR_SDK_UNEXPECTED; + } + + close(sgx_fd); + return ret; +} + +TeeErrorCode RaEnclaveQuote::SgxDeviceGetQuote(EnclaveQuoteArgs* quote_args) { + if (!quote_args->quote.as_buf || (quote_args->quote_buf_len == 0)) { + TEE_LOG_ERROR("Invalid quote buffer or len"); + return TEE_ERROR_PARAMETERS; + } + + int sgx_fd; + if ((sgx_fd = open(kSgxDeviceName, O_RDONLY)) < 0) { + TEE_LOG_ERROR("Fail to open %s", kSgxDeviceName); + return TEE_ERROR_FILE_OPEN; + } + + TeeErrorCode ret = TEE_SUCCESS; + int count = 3; + while (count--) { + if (ioctl(sgx_fd, SGXIOC_GEN_QUOTE, quote_args) == 0) { + uint32_t signature_len = quote_args->quote.as_quote->signature_len; + TEE_LOG_DEBUG("SgxDeviceGetQuote length=%ld", signature_len); + if (signature_len == 0) { + TEE_LOG_ERROR("Invalid quote from %s", kSgxDeviceName); + ret = TEE_ERROR_SDK_UNEXPECTED; + } + break; + } else if (errno != EAGAIN) { + TEE_LOG_ERROR("Fail to get quote from %s", kSgxDeviceName); + ret = TEE_ERROR_SDK_UNEXPECTED; + break; + } else { + TEE_LOG_WARN("/dev/sgx is temporarily busy. Try again after 1s."); + sleep(1); + } + } + + close(sgx_fd); + return ret; +} + +uint8_t RaEnclaveQuote::Hex2Dec(const char hex) { + if (('0' <= hex) && (hex <= '9')) { + return hex - '0'; + } else if (('a' <= hex) && (hex <= 'f')) { + return hex - 'a' + 10; + } else if (('A' <= hex) && (hex <= 'F')) { + return hex - 'A' + 10; + } else { + // Otherwise return zero for none HEX charactor + return 0; + } +} + +TeeErrorCode RaEnclaveQuote::GetSpidFromHexStr(const std::string& spid_str) { + const char* src = spid_str.data(); + const int len = sizeof(sgx_spid_t); + uint8_t* dst = RCAST(uint8_t*, quote_args_.spid.id); + + if ((spid_str.empty()) || ((len * 2) != spid_str.length())) { + TEE_LOG_ERROR("Empty SPID or Invalid SPID hexstring length!\n"); + return TEE_ERROR_PARAMETERS; + } + + for (int i = 0; i < len; i++) { + dst[i] = + (Hex2Dec(src[i * 2] & 0xFF) << 4) + (Hex2Dec(src[i * 2 + 1] & 0xFF)); + } + return TEE_SUCCESS; +} + +TeeErrorCode RaEnclaveQuote::GetIasSigRL(const RaIasServerCfg& ias_server) { + // Initialize the quote firstly + sgx_epid_group_id_t gid = {0}; + TEE_CHECK_RETURN(SgxDeviceInitQuote(&gid)); + + // Try to Get the IAS SigRL, do nothing if failed + RaIasClient ias_client(ias_server); + std::string sigrl_str; + TEE_CHECK_RETURN(ias_client.GetSigRL(gid, &sigrl_str)); + + // If there is valid SigRL + if (!sigrl_str.empty()) { + TEE_LOG_DEBUG("Set the SigRL, length=%ld", sigrl_str.size()); + quote_args_.sigrl_ptr = RCAST(const uint8_t*, sigrl_str.data()); + quote_args_.sigrl_len = sigrl_str.size(); + } + return TEE_SUCCESS; +} + +TeeErrorCode RaEnclaveQuote::GetEnclaveQuote( + const RaIasServerCfg& ias_server, const std::string& spid, + const sgx_report_data_t& report_data) { + // Firstly, eset all the data + constexpr int kMaxQuoteLen = 4096; + quote_buf_.resize(kMaxQuoteLen, 0); + memset(RCAST(void*, "e_args_), 0, sizeof(EnclaveQuoteArgs)); + + // Initialize the arguments + quote_args_.quote.as_buf = quote_buf_.data(); + quote_args_.quote_buf_len = quote_buf_.size(); + quote_args_.quote_type = SGX_LINKABLE_SIGNATURE; + std::memcpy(RCAST(void*, quote_args_.report_data.d), + RCAST(const void*, report_data.d), sizeof(sgx_report_data_t)); + RAND_bytes(quote_args_.nonce.rand, sizeof(sgx_quote_nonce_t)); + TEE_CHECK_RETURN(GetSpidFromHexStr(spid)); + TEE_CHECK_RETURN(GetIasSigRL(ias_server)); + + // Finally, get quote via ioctl device + TEE_CHECK_RETURN(SgxDeviceGetQuote("e_args_)); + + return TEE_SUCCESS; +} + +TeeErrorCode RaEnclaveQuote::GetEnclaveQuoteB64( + const RaIasServerCfg& ias_server, const std::string& spid, + const sgx_report_data_t& report_data, std::string* quote_b64) { + // Get the enclave quote + TEE_CHECK_RETURN(GetEnclaveQuote(ias_server, spid, report_data)); + + // Convert the quote data to base64 format + char* quote_ptr = RCAST(char*, quote_args_.quote.as_quote); + size_t quote_len = + sizeof(sgx_quote_t) + quote_args_.quote.as_quote->signature_len; + std::string tmp_quote_b64 = base64::encode(quote_ptr, quote_len); + quote_b64->assign(tmp_quote_b64); + TEE_LOG_DEBUG("QuoteB64[%lu]: %s", quote_b64->length(), quote_b64->c_str()); + + return TEE_SUCCESS; +} + +TeeErrorCode RaEnclaveQuote::GetEnclaveIasReport( + const RaIasServerCfg& ias_server, const std::string& spid, + const sgx_report_data_t& report_data, RaIasReport* ias_report) { + // Get the enclave quote + TEE_CHECK_RETURN(GetEnclaveQuote(ias_server, spid, report_data)); + + // Convert the quote data to a new string for calling IAS client method + ra::occlum::RaIasClient ias_client(ias_server); + size_t quote_len = + sizeof(sgx_quote_t) + quote_args_.quote.as_quote->signature_len; + std::string quote_str(RCAST(char*, quote_args_.quote.as_quote), quote_len); + TEE_CHECK_RETURN(ias_client.FetchReport(quote_str, ias_report)); + + return TEE_SUCCESS; +} + +} // namespace occlum +} // namespace ra + +#ifdef __cplusplus +extern "C" { +#endif + +TeeErrorCode InitializeQuote(sgx_epid_group_id_t* gid) { + return ra::occlum::RaEnclaveQuote::SgxDeviceInitQuote(gid); +} + +TeeErrorCode GetQuote(EnclaveQuoteArgs* quote_args) { + return ra::occlum::RaEnclaveQuote::SgxDeviceGetQuote(quote_args); +} + +#ifdef __cplusplus +} +#endif diff --git a/demos/remote_attestation/lib/src/ra_report.cpp b/demos/remote_attestation/lib/src/ra_report.cpp deleted file mode 100644 index 62f67b51..00000000 --- a/demos/remote_attestation/lib/src/ra_report.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include - -#include "sofaenclave/ra_report.h" - -namespace sofaenclave { -namespace occlum { - -#define IMPLEMENT_IAS_REPORT_CLASS_MEMBER(x); \ - std::string& IasReport::x() { return x##_; } \ - const std::string& IasReport::x() const { return x##_; } \ - void IasReport::set_##x(const std::string& value) { x##_ = value; } \ - void IasReport::set_##x(const char* value) { x##_ = value; } \ - void IasReport::set_##x(const char* value, size_t size) { x##_ = value; } - -IMPLEMENT_IAS_REPORT_CLASS_MEMBER(b64_signature); -IMPLEMENT_IAS_REPORT_CLASS_MEMBER(signing_cert); -IMPLEMENT_IAS_REPORT_CLASS_MEMBER(advisory_url); -IMPLEMENT_IAS_REPORT_CLASS_MEMBER(advisory_ids); -IMPLEMENT_IAS_REPORT_CLASS_MEMBER(response_body); -IMPLEMENT_IAS_REPORT_CLASS_MEMBER(epid_pseudonym); -IMPLEMENT_IAS_REPORT_CLASS_MEMBER(quote_status); -IMPLEMENT_IAS_REPORT_CLASS_MEMBER(b16_platform_info_blob); -IMPLEMENT_IAS_REPORT_CLASS_MEMBER(b64_quote_body); - -} // namespace occlum -} // namespace sofaenclave diff --git a/demos/remote_attestation/run_on_occlum.sh b/demos/remote_attestation/run_on_occlum.sh index 793db5d8..f9d071c8 100755 --- a/demos/remote_attestation/run_on_occlum.sh +++ b/demos/remote_attestation/run_on_occlum.sh @@ -22,4 +22,5 @@ cp /usr/local/occlum/x86_64-linux-musl/lib/libcurl.so.4 image/lib occlum build # 3. Run application -occlum run /bin/$DEMPOAPP +LOG_LEVEL=${1:-off} +OCCLUM_LOG_LEVEL=$LEVEL occlum run /bin/$DEMPOAPP