diff --git a/demos/remote_attestation/CMakeLists.txt b/demos/remote_attestation/CMakeLists.txt index 7da155ae..3cb53a83 100644 --- a/demos/remote_attestation/CMakeLists.txt +++ b/demos/remote_attestation/CMakeLists.txt @@ -8,6 +8,10 @@ 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) diff --git a/demos/remote_attestation/README.md b/demos/remote_attestation/README.md index 97d46a81..ea7b90cf 100644 --- a/demos/remote_attestation/README.md +++ b/demos/remote_attestation/README.md @@ -2,17 +2,35 @@ This project demonstrates how to do remote attestation on Occlum. -In a nutshell, Occlum provides SGX capabilities to user apps through ioctls on a special device (`/dev/sgx`). To hide the low-level details of ioctls from user apps, a user-friendly, remote attestation library is provided in this demo. +In a nutshell, Occlum provides SGX capabilities to user apps through ioctls on a special device (`/dev/sgx`). +To hide the low-level details of ioctls from user apps, a user-friendly, remote attestation library is provided in this demo. -**Prerequisites.** This demo needs to access Intel Attestation Service (IAS). To do this, a developer needs to contact Intel to obtain a Service Provider ID (SPID) and the associated Service Provider certificate. The certificate and key files should be put into `conf/certs`, and configure the SPID and paths of the certificate and key files in `conf/ra_config.example.json`. +**Prerequisites.** This demo needs to access Intel Attestation Service (IAS). To do this, +a developer needs to contact Intel to obtain a Service Provider ID (SPID) and the associated +Access Key from [here](https://api.portal.trustedservices.intel.com/EPID-attestation). +After obtaining the SPID and Access Key, fill them in the config file `conf/ra_config.json` as shown below: + +``` +{ + "ias_url": "https://api.trustedservices.intel.com/sgx/dev/attestation/v4", + "ias_access_key": "", + "enclave_spid": "" +} +``` + +**NOTE:** The URL, SPID and Access Key above vary depending whether it is for development or production **Step 1.** Build this demo + +Build the code in debug mode with "--debug", otherwise it's in Relese mode by default. ``` -download_and_build.sh +./download_and_build.sh [--debug] ``` **Step 2.** Run this demo on Occlum + +Build the occlum image and run the RA test application. ``` -run_on_occlum.sh +./run_on_occlum.sh ``` diff --git a/demos/remote_attestation/app/ra_config.h b/demos/remote_attestation/app/ra_config.h index 504cc72f..5a2e3fb5 100644 --- a/demos/remote_attestation/app/ra_config.h +++ b/demos/remote_attestation/app/ra_config.h @@ -17,6 +17,7 @@ constexpr char kRaConf[] = "ra_config.json"; constexpr char kConfIasServer[] = "ias_url"; constexpr char kConfIasCert[] = "ias_sp_cert_file"; 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) diff --git a/demos/remote_attestation/app/ra_main.cpp b/demos/remote_attestation/app/ra_main.cpp index ae4e89b2..8e452f3d 100644 --- a/demos/remote_attestation/app/ra_main.cpp +++ b/demos/remote_attestation/app/ra_main.cpp @@ -37,6 +37,7 @@ int main() { 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); if (spid_str.empty()) { @@ -44,7 +45,7 @@ int main() { return -1; } - SofaeServerCfg ias_server = {endpoint, cert, key}; + SofaeServerCfg ias_server = {endpoint, cert, key, access_key}; SofaeEnclaveQuote quote = {0}; SofaeQuoteArgs quote_args = {0}; quote_args.quote_type = SGX_LINKABLE_SIGNATURE; diff --git a/demos/remote_attestation/conf/ra_config.example.json b/demos/remote_attestation/conf/ra_config.example.json deleted file mode 100644 index 44dee9fb..00000000 --- a/demos/remote_attestation/conf/ra_config.example.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ias_url": "", - "ias_sp_cert_file": "/etc/certs/sp_client.crt", - "ias_sp_key_file": "/etc/certs/sp_client.key", - "enclave_spid": "" -} diff --git a/demos/remote_attestation/conf/ra_config.json b/demos/remote_attestation/conf/ra_config.json new file mode 100644 index 00000000..636d3072 --- /dev/null +++ b/demos/remote_attestation/conf/ra_config.json @@ -0,0 +1,5 @@ +{ + "ias_url": "https://api.trustedservices.intel.com/sgx/dev/attestation/v4", + "ias_access_key": "", + "enclave_spid": "" +} diff --git a/demos/remote_attestation/download_and_build.sh b/demos/remote_attestation/download_and_build.sh index 5d6612d3..d3ff1f3f 100755 --- a/demos/remote_attestation/download_and_build.sh +++ b/demos/remote_attestation/download_and_build.sh @@ -7,6 +7,9 @@ THISDIR="$(dirname $(readlink -f $0))" INSTALLDIR="/usr/local/occlum/x86_64-linux-musl" DEPSDIR="$THISDIR/deps" +BUILDMODE="Release" +[ "$1" == "--debug" ] && BUILDMODE="Debug" + mkdir -p $DEPSDIR || exit 1 # Download OpenSSL 1.1.1 @@ -27,9 +30,9 @@ CURLDIR="${DEPSDIR}/curl" if [ ! -d "$CURLDIR" ] ; then echo "Downloading curl ..." cd "$DEPSDIR" && \ - wget https://github.com/curl/curl/archive/curl-7_29_0.tar.gz && \ - tar -xvf curl-7_29_0.tar.gz && \ - mv curl-curl-7_29_0 curl && \ + 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" @@ -101,5 +104,5 @@ fi echo "Build demo source code" cd "$THISDIR" && rm -rf ./build && mkdir -p build cd build && \ -cmake -DCMAKE_CXX_COMPILER=occlum-g++ ../ && \ +cmake -DCMAKE_CXX_COMPILER=occlum-g++ -DBUILD_MODE=${BUILDMODE} ../ && \ make -j$(nproc) diff --git a/demos/remote_attestation/lib/include/sofaenclave/common/type.h b/demos/remote_attestation/lib/include/sofaenclave/common/type.h index df54e0c4..7ea94363 100644 --- a/demos/remote_attestation/lib/include/sofaenclave/common/type.h +++ b/demos/remote_attestation/lib/include/sofaenclave/common/type.h @@ -53,6 +53,7 @@ typedef struct { std::string endpoint; std::string cert; std::string key; + std::string accesskey; } SofaeServerCfg; #endif // REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_TYPE_H_ diff --git a/demos/remote_attestation/lib/include/sofaenclave/ra_ias.h b/demos/remote_attestation/lib/include/sofaenclave/ra_ias.h index 7cc60cc9..5ccbfa72 100644 --- a/demos/remote_attestation/lib/include/sofaenclave/ra_ias.h +++ b/demos/remote_attestation/lib/include/sofaenclave/ra_ias.h @@ -4,7 +4,7 @@ #include #include -#include "./sgx_uae_service.h" +#include "./sgx_uae_epid.h" #include "./sgx_urts.h" #include "./sgx_utils.h" @@ -27,7 +27,7 @@ class RaIasClient { ~RaIasClient(); - SofaeErrorCode GetSigRL(const sgx_epid_group_id_t* gid, std::string* sigrl); + SofaeErrorCode GetSigRL(const sgx_epid_group_id_t& gid, std::string* sigrl); SofaeErrorCode FetchReport(const std::string& quote, IasReport* ias_report); private: diff --git a/demos/remote_attestation/lib/include/sofaenclave/ra_manager.h b/demos/remote_attestation/lib/include/sofaenclave/ra_manager.h index f1d8c7c4..498f9f07 100644 --- a/demos/remote_attestation/lib/include/sofaenclave/ra_manager.h +++ b/demos/remote_attestation/lib/include/sofaenclave/ra_manager.h @@ -49,7 +49,7 @@ SofaeErrorCode GetQuote(SofaeQuoteArgs* quote_args); * @retval Others when failed */ SofaeErrorCode FetchIasSigRL(const SofaeServerCfg& ias_server, - sgx_epid_group_id_t* gid, + const sgx_epid_group_id_t& gid, std::string* sigrl); /** diff --git a/demos/remote_attestation/lib/src/ra_ias.cpp b/demos/remote_attestation/lib/src/ra_ias.cpp index 284c7bd5..f97068c2 100644 --- a/demos/remote_attestation/lib/src/ra_ias.cpp +++ b/demos/remote_attestation/lib/src/ra_ias.cpp @@ -20,8 +20,10 @@ constexpr char kStrQuoteStatus[] = "isvEnclaveQuoteStatus"; constexpr char kStrPlatform[] = "platformInfoBlob"; constexpr char kStrQuoteBody[] = "isvEnclaveQuoteBody"; constexpr char kStrHeaderSig[] = "x-iasreport-signature:"; -constexpr char kStrHeaderCA[] = "x-iasreport-signing-certificate:"; -constexpr char kStrHeaderAdvisoryURL[] = "advisory-url:"; +constexpr char kStrHeaderSigAk[] = "X-IASReport-Signature:"; +constexpr char kStrHeaderCa[] = "x-iasreport-signing-certificate:"; +constexpr char kStrHeaderCaAk[] = "X-IASReport-Signing-Certificate:"; +constexpr char kStrHeaderAdvisoryUrl[] = "advisory-url:"; constexpr char kStrHeaderAdvisoryIDs[] = "advisory-ids:"; typedef struct { @@ -95,11 +97,15 @@ static size_t ParseReportResponseHeader(const void* contents, size_t size, if (strncmp(header, kStrHeaderSig, strlen(kStrHeaderSig)) == 0) { report->set_b64_signature(GetHeaderValue(header, kStrHeaderSig)); - } else if (strncmp(header, kStrHeaderCA, strlen(kStrHeaderCA)) == 0) { - report->set_signing_cert(GetHeaderValue(header, kStrHeaderCA)); - } else if (strncmp(header, kStrHeaderAdvisoryURL, - strlen(kStrHeaderAdvisoryURL)) == 0) { - report->set_advisory_url(GetHeaderValue(header, kStrHeaderAdvisoryURL)); + } else if (strncmp(header, kStrHeaderSigAk, strlen(kStrHeaderSigAk)) == 0) { + report->set_b64_signature(GetHeaderValue(header, kStrHeaderSigAk)); + } else if (strncmp(header, kStrHeaderCa, strlen(kStrHeaderCa)) == 0) { + report->set_signing_cert(GetHeaderValue(header, kStrHeaderCa)); + } else if (strncmp(header, kStrHeaderCaAk, strlen(kStrHeaderCaAk)) == 0) { + report->set_signing_cert(GetHeaderValue(header, kStrHeaderCaAk)); + } else if (strncmp(header, kStrHeaderAdvisoryUrl, + strlen(kStrHeaderAdvisoryUrl)) == 0) { + report->set_advisory_url(GetHeaderValue(header, kStrHeaderAdvisoryUrl)); } else if (strncmp(header, kStrHeaderAdvisoryIDs, strlen(kStrHeaderAdvisoryIDs)) == 0) { report->set_advisory_ids(GetHeaderValue(header, kStrHeaderAdvisoryIDs)); @@ -144,6 +150,8 @@ void RaIasClient::InitIasConnection(const std::string& endpoint) { curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1L); curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 60L); curl_easy_setopt(curl_, CURLOPT_CONNECTTIMEOUT, 10L); + curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L); server_endpoint_ = endpoint; } @@ -157,13 +165,19 @@ RaIasClient::RaIasClient(const SofaeServerCfg& ias_server) { InitIasConnection(ias_server.endpoint); // Check the HTTPS server addr and set the cert/key settings - if (curl_ && (ias_server.endpoint.find("https://") != std::string::npos)) { + // Or use the Access key authentication + std::string header_access_key = "Ocp-Apim-Subscription-Key: "; + if (!ias_server.accesskey.empty()) { + header_access_key += ias_server.accesskey; + headers_ = curl_slist_append(headers_, header_access_key.c_str()); + } + + 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()); - curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(curl_, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl_, CURLOPT_SSLCERT, ias_server.cert.c_str()); curl_easy_setopt(curl_, CURLOPT_SSLKEY, ias_server.key.c_str()); curl_easy_setopt(curl_, CURLOPT_SSLCERTTYPE, ias_cert_key_type); @@ -186,7 +200,7 @@ RaIasClient::~RaIasClient() { } } -SofaeErrorCode RaIasClient::GetSigRL(const sgx_epid_group_id_t *gid, +SofaeErrorCode RaIasClient::GetSigRL(const sgx_epid_group_id_t& gid, std::string *sigrl) { if (!curl_) { SOFAE_LOG_ERROR("IAS client is not initialized"); @@ -194,8 +208,8 @@ SofaeErrorCode RaIasClient::GetSigRL(const sgx_epid_group_id_t *gid, } /* Set the URL */ - std::string url = server_endpoint_ + "/attestation/sgx/v3/sigrl/"; - std::vector tmp_gid_vec(sizeof(sgx_epid_group_id_t) * 2, 0); + std::string url = server_endpoint_ + "/sigrl/"; + std::vector tmp_gid_vec(sizeof(sgx_epid_group_id_t) * 2 + 1, 0); 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()); @@ -242,7 +256,7 @@ SofaeErrorCode RaIasClient::FetchReport(const std::string& quote, } /* Set the report url */ - std::string url = server_endpoint_ + "/attestation/sgx/v3/report"; + std::string url = server_endpoint_ + "/report"; SOFAE_LOG_DEBUG("URL: %s", url.c_str()); curl_easy_setopt(curl_, CURLOPT_URL, url.c_str()); diff --git a/demos/remote_attestation/lib/src/ra_json.cpp b/demos/remote_attestation/lib/src/ra_json.cpp index bdfabee2..74e4a9a6 100644 --- a/demos/remote_attestation/lib/src/ra_json.cpp +++ b/demos/remote_attestation/lib/src/ra_json.cpp @@ -46,7 +46,7 @@ JsonConfig* JsonConfig::GetInstance() { template bool JsonConfig::CheckString(const T& conf, const char* name) { if (!conf.HasMember(name) || !conf[name].IsString()) { - SOFAE_LOG_ERROR("%s is missed or not string in config file", name); + SOFAE_LOG_DEBUG("%s is missed or not string in config file", name); return false; } return true; @@ -55,7 +55,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_ERROR("%s is missed or not array in config file", name); + SOFAE_LOG_DEBUG("%s is missed or not array in config file", name); return false; } return true; @@ -64,7 +64,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_ERROR("%s is missed or not integer in config file", name); + SOFAE_LOG_DEBUG("%s is missed or not integer in config file", name); return false; } return true; @@ -73,7 +73,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_ERROR("%s is missed or not object in config file", name); + SOFAE_LOG_DEBUG("%s is missed or not object in config file", name); return false; } return true; diff --git a/demos/remote_attestation/lib/src/ra_manager.cpp b/demos/remote_attestation/lib/src/ra_manager.cpp index 500d91b1..b414be6c 100644 --- a/demos/remote_attestation/lib/src/ra_manager.cpp +++ b/demos/remote_attestation/lib/src/ra_manager.cpp @@ -35,7 +35,7 @@ SofaeErrorCode GetQuote(SofaeQuoteArgs* quote_args) { } SofaeErrorCode FetchIasSigRL(const SofaeServerCfg& ias_server, - sgx_epid_group_id_t* gid, + const sgx_epid_group_id_t& gid, std::string* sigrl) { sofaenclave::occlum::RaIasClient ias_client(ias_server); return ias_client.GetSigRL(gid, sigrl); @@ -63,7 +63,7 @@ SofaeErrorCode GetQuoteAndFetchIasReport(const SofaeServerCfg& ias_server, // 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); + ret = FetchIasSigRL(ias_server, gid, &sigrl_str); if (ret != SOFAE_SUCCESS) { return ret; } diff --git a/demos/remote_attestation/run_on_occlum.sh b/demos/remote_attestation/run_on_occlum.sh index d247cb51..793db5d8 100755 --- a/demos/remote_attestation/run_on_occlum.sh +++ b/demos/remote_attestation/run_on_occlum.sh @@ -14,8 +14,7 @@ mkdir -p image/etc mkdir -p image/etc/certs cp /etc/resolv.conf image/etc cp /etc/hosts image/etc -cp $THISDIR/conf/ra_config.example.json image/etc/ra_config.json -cp $THISDIR/conf/certs/* image/etc/certs +cp $THISDIR/conf/ra_config.json image/etc/ cp $THISDIR/build/$DEMPOAPP image/bin cp /usr/local/occlum/x86_64-linux-musl/lib/libssl.so.1.1 image/lib cp /usr/local/occlum/x86_64-linux-musl/lib/libcrypto.so.1.1 image/lib