Add SGX remote attestaion demo
This demo consists of 1. An user-friendly library for getting Intel Attestation Service (IAS) report. 2. A application that uses this library to get IAS report. This demo requires obtaining service provider certificate/ID from Intel.
This commit is contained in:
parent
b9fa937504
commit
2052447950
@ -2,10 +2,23 @@
|
||||
|
||||
This directory contains sample projects that demonstrate how Occlum can be used to build and run user applications.
|
||||
|
||||
## Toolchain demos
|
||||
|
||||
This set of demos shows how the Occlum toolchain can be used with different build tools.
|
||||
|
||||
* `hello_c/`: A sample C project built with Makefile/CMake.
|
||||
* `hello_cc/`: A sample C++ project built with Makefile/CMake.
|
||||
* `hello_bazel/`: A sample C++ project built with [Bazel](https://bazel.build).
|
||||
|
||||
## Application demos
|
||||
|
||||
This set of demos shows how real-world apps can be easily run inside SGX enclaves with Occlum.
|
||||
|
||||
* `https_server/`: A HTTPS file server based on [Mongoose Embedded Web Server Library](https://github.com/cesanta/mongoose).
|
||||
* `openvino/` A benchmark of [OpenVINO Inference Engine](https://docs.openvinotoolkit.org/2019_R3/_docs_IE_DG_inference_engine_intro.html).
|
||||
* `tensorflow_lite/`: A demo and benchmark of [Tensorflow Lite](https://www.tensorflow.org/lite) inference engine.
|
||||
* `xgboost/`: A demo of [XGBoost](https://xgboost.readthedocs.io/en/latest/).
|
||||
|
||||
## SGX capability demos
|
||||
|
||||
* `remote_attestation/`: This project demonstrates how an app running upon Occlum can perform SGX remote attestation.
|
||||
|
3
demos/remote_attestation/.gitignore
vendored
Normal file
3
demos/remote_attestation/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
build
|
||||
deps
|
||||
occlum_workspace
|
42
demos/remote_attestation/CMakeLists.txt
Normal file
42
demos/remote_attestation/CMakeLists.txt
Normal file
@ -0,0 +1,42 @@
|
||||
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 "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)
|
||||
|
||||
FILE(GLOB LIB_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/lib/src/*.cpp)
|
||||
|
||||
SET(RALIB occlumra)
|
||||
ADD_LIBRARY(${RALIB} ${LIB_SRCS})
|
||||
TARGET_INCLUDE_DIRECTORIES(
|
||||
${RALIB} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lib/include
|
||||
${SGXSDK_INSTALL_DIR}/include
|
||||
${OCCLUM_INSTALL_DIR}/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/deps/cppcodec
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/deps/rapidjson/include
|
||||
)
|
||||
TARGET_LINK_LIBRARIES(${RALIB}
|
||||
-L${OCCLUM_INSTALL_DIR}/lib -lcurl
|
||||
)
|
||||
|
||||
SET(DEMOAPP remote_attestation_demo)
|
||||
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}/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
|
||||
-Wl,-rpath=${CMAKE_CURRENT_BINARY_DIR}:${OCCLUM_INSTALL_DIR}/lib
|
||||
)
|
||||
ADD_DEPENDENCIES(${DEMOAPP} ${RALIB})
|
18
demos/remote_attestation/README.md
Normal file
18
demos/remote_attestation/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
# SGX Remote Attestation Demo
|
||||
|
||||
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.
|
||||
|
||||
**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`.
|
||||
|
||||
**Step 1.** Build this demo
|
||||
```
|
||||
download_and_build.sh
|
||||
```
|
||||
|
||||
**Step 2.** Run this demo on Occlum
|
||||
```
|
||||
run_on_occlum.sh
|
||||
```
|
||||
|
26
demos/remote_attestation/app/ra_config.h
Normal file
26
demos/remote_attestation/app/ra_config.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef REMOTE_ATTESTATION_RA_CONFIG_H_
|
||||
#define REMOTE_ATTESTATION_RA_CONFIG_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#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";
|
||||
|
||||
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 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)
|
||||
|
||||
#endif // REMOTE_ATTESTATION_RA_CONFIG_H_
|
66
demos/remote_attestation/app/ra_main.cpp
Normal file
66
demos/remote_attestation/app/ra_main.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#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<uint8_t> HexStr2Bytes(const uint8_t* str) {
|
||||
int len = strlen(RCAST(const char *, str)) / 2;
|
||||
std::vector<uint8_t> 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;
|
||||
}
|
||||
|
||||
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 spid_str = RA_CONF_STR(kConfSPID);
|
||||
|
||||
if (spid_str.empty()) {
|
||||
printf("Please specify the right SPID in configuration file!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
SofaeServerCfg ias_server = {endpoint, cert, 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<uint8_t> 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);
|
||||
if (ret) {
|
||||
printf("Fail to get quote or fetch report, erro code is %x!\n", ret);
|
||||
} else {
|
||||
printf("Test getting quote and fetching report successfully!\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
6
demos/remote_attestation/conf/ra_config.example.json
Normal file
6
demos/remote_attestation/conf/ra_config.example.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"ias_url": "",
|
||||
"ias_sp_cert_file": "/etc/certs/sp_client.crt",
|
||||
"ias_sp_key_file": "/etc/certs/sp_client.key",
|
||||
"enclave_spid": ""
|
||||
}
|
104
demos/remote_attestation/download_and_build.sh
Executable file
104
demos/remote_attestation/download_and_build.sh
Executable file
@ -0,0 +1,104 @@
|
||||
#!/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"
|
||||
DEPSDIR="$THISDIR/deps"
|
||||
|
||||
mkdir -p $DEPSDIR || exit 1
|
||||
|
||||
# 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
|
||||
|
||||
# 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_29_0.tar.gz && \
|
||||
tar -xvf curl-7_29_0.tar.gz && \
|
||||
mv curl-curl-7_29_0 curl && \
|
||||
echo "Download curl successfully" || exit 1
|
||||
else
|
||||
echo "The openssl code is already existent"
|
||||
fi
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
# Build and install openssl
|
||||
if [ ! -f "$INSTALLDIR/lib/libcrypto.so" ] ; then
|
||||
echo "Building openssl ..."
|
||||
cd "$OPENSSLDIR" && \
|
||||
CC=occlum-gcc ./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
|
||||
|
||||
# Build and install libcurl
|
||||
if [ ! -f "$INSTALLDIR/lib/libcurl.so" ] ; then
|
||||
cd "$CURLDIR"
|
||||
if [ ! -f ./configure ] ; then
|
||||
echo "Building configure file ..."
|
||||
./buildconf || exit 1
|
||||
fi
|
||||
echo "Building curl ..."
|
||||
CC=occlum-gcc CXX=occlum-g++ ./configure \
|
||||
--prefix=$INSTALLDIR \
|
||||
--with-ssl=$INSTALLDIR && \
|
||||
make -j${nproc} && \
|
||||
sudo make install && \
|
||||
echo "Build curl successfully" || exit 1
|
||||
else
|
||||
echo "The curl library is aleady existent"
|
||||
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++ ../ && \
|
||||
make -j$(nproc)
|
@ -0,0 +1,39 @@
|
||||
#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_
|
@ -0,0 +1,22 @@
|
||||
#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_LOG_H_
|
||||
#define REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_LOG_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
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_
|
@ -0,0 +1,58 @@
|
||||
#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_TYPE_H_
|
||||
#define REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_TYPE_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "./sgx_quote.h"
|
||||
#include "./sgx_report.h"
|
||||
#include "./sgx_tseal.h"
|
||||
|
||||
#define RCAST(t, v) reinterpret_cast<t>((v))
|
||||
#define SCAST(t, v) static_cast<t>((v))
|
||||
#define CCAST(t, v) const_cast<t>((v))
|
||||
|
||||
#define SOFAE_UNREFERENCED_PARAMETER(p) static_cast<void>((p))
|
||||
|
||||
typedef uint8_t SofaeEnclaveQuote[4096];
|
||||
|
||||
/**
|
||||
* report_data Input report data which will be included in quote data.
|
||||
* The first 32 bytes should be the SHA256 hash value of
|
||||
* the public key which is used in the RA work flow.
|
||||
* nonce Nonce value to avoid replay attack. All zero to ignore it.
|
||||
* spid The service provider ID, please use you real SPID,
|
||||
* otherwise, IAS will return bad request when quote report.
|
||||
* quote_type Maybe SGX_UNLINKABLE_SIGNATURE or SGX_LINKABLE_SIGNATURE
|
||||
* quote type.
|
||||
* sigrl_ptr The SigRL data buffer
|
||||
* sigrl_len The total length of SigRL data
|
||||
* quote Output quote structure data in binary format.
|
||||
*/
|
||||
typedef struct {
|
||||
sgx_report_data_t report_data; // input
|
||||
sgx_quote_sign_type_t quote_type; // input
|
||||
sgx_spid_t spid; // input
|
||||
sgx_quote_nonce_t nonce; // input
|
||||
const uint8_t* sigrl_ptr; // input (optional)
|
||||
uint32_t sigrl_len; // input (optional)
|
||||
uint32_t quote_buf_len; // input
|
||||
union {
|
||||
uint8_t* as_buf;
|
||||
sgx_quote_t* as_quote;
|
||||
} quote; // output
|
||||
} SofaeQuoteArgs;
|
||||
|
||||
/**
|
||||
* endpoint http://xxx.xxx.xxx.xxx:<port> for HTTP IAS proxy server
|
||||
* or https://xxx.xxx.xxx.xxx:<port> 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
|
||||
*/
|
||||
typedef struct {
|
||||
std::string endpoint;
|
||||
std::string cert;
|
||||
std::string key;
|
||||
} SofaeServerCfg;
|
||||
|
||||
#endif // REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_COMMON_TYPE_H_
|
23
demos/remote_attestation/lib/include/sofaenclave/ra_conf.h
Normal file
23
demos/remote_attestation/lib/include/sofaenclave/ra_conf.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_CONF_H_
|
||||
#define REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_CONF_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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<std::string>* 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_
|
27
demos/remote_attestation/lib/include/sofaenclave/ra_device.h
Normal file
27
demos/remote_attestation/lib/include/sofaenclave/ra_device.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_DEVICE_H_
|
||||
#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_DEVICE_H_
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#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_
|
46
demos/remote_attestation/lib/include/sofaenclave/ra_ias.h
Normal file
46
demos/remote_attestation/lib/include/sofaenclave/ra_ias.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_IAS_H_
|
||||
#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_IAS_H_
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
#include "./sgx_uae_service.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_
|
67
demos/remote_attestation/lib/include/sofaenclave/ra_json.h
Normal file
67
demos/remote_attestation/lib/include/sofaenclave/ra_json.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_JSON_H_
|
||||
#define REMOTE_ATTESTATION_LIB_INCLUDE_SOFAENCLAVE_RA_JSON_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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<rapidjson::Document> SofaeJsonDocPtr;
|
||||
typedef std::map<std::string, SofaeJsonDocPtr> SofaeJsonConfMap;
|
||||
|
||||
class JsonConfig {
|
||||
public:
|
||||
// Gets the singleton UnitTest object.
|
||||
static JsonConfig* GetInstance();
|
||||
|
||||
// To support both rapidjson::Document and rapidjson::Value
|
||||
template <typename T>
|
||||
static bool CheckString(const T& conf, const char* name);
|
||||
template <typename T>
|
||||
static bool CheckArray(const T& conf, const char* name);
|
||||
template <typename T>
|
||||
static bool CheckInt(const T& conf, const char* name);
|
||||
template <typename T>
|
||||
static bool CheckObj(const T& conf, const char* name);
|
||||
template <typename T>
|
||||
static std::string GetStr(const T& conf, const char* name,
|
||||
const std::string& default_val = "");
|
||||
template <typename T>
|
||||
static SofaeErrorCode GetStrArray(const T& conf, const char* name,
|
||||
std::vector<std::string>* values);
|
||||
template <typename T>
|
||||
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<std::string>* 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_
|
@ -0,0 +1,91 @@
|
||||
#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_MANAGER_H_
|
||||
#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_MANAGER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#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,
|
||||
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_
|
42
demos/remote_attestation/lib/include/sofaenclave/ra_report.h
Normal file
42
demos/remote_attestation/lib/include/sofaenclave/ra_report.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef REMOTE_ATTESTATION_LIB_INCLUDE_RA_REPORT_H_
|
||||
#define REMOTE_ATTESTATION_LIB_INCLUDE_RA_REPORT_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
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_
|
67
demos/remote_attestation/lib/src/ra_device.cpp
Normal file
67
demos/remote_attestation/lib/src/ra_device.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include <string>
|
||||
|
||||
#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
|
293
demos/remote_attestation/lib/src/ra_ias.cpp
Normal file
293
demos/remote_attestation/lib/src/ra_ias.cpp
Normal file
@ -0,0 +1,293 @@
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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"
|
||||
|
||||
// use cppcodec/base64
|
||||
#include "cppcodec/base64_rfc4648.hpp"
|
||||
using base64 = cppcodec::base64_rfc4648;
|
||||
|
||||
namespace sofaenclave {
|
||||
namespace occlum {
|
||||
|
||||
constexpr char kStrEpidPseudonym[] = "epidPseudonym";
|
||||
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 kStrHeaderAdvisoryIDs[] = "advisory-ids:";
|
||||
|
||||
typedef struct {
|
||||
std::string b64_sigrl;
|
||||
} SofaeIasSigrl;
|
||||
|
||||
static std::string GetHeaderValue(const char *header, const char *name) {
|
||||
std::string header_str = header;
|
||||
std::string ending("\n\r");
|
||||
|
||||
// Name: value\r\n
|
||||
std::size_t pos_start = header_str.find_first_of(" ");
|
||||
std::size_t pos_end = header_str.find_first_of("\r\n");
|
||||
if ((pos_start != std::string::npos) && (pos_end != std::string::npos)) {
|
||||
return header_str.substr(pos_start + 1, pos_end - pos_start - 1);
|
||||
} else {
|
||||
return std::string("");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (content_length == 0) {
|
||||
sigrl->b64_sigrl.clear();
|
||||
SOFAE_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());
|
||||
}
|
||||
return content_length;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
SOFAE_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);
|
||||
size_t content_length = size * nmemb;
|
||||
IasReport *report = RCAST(IasReport *, response);
|
||||
|
||||
report->set_response_body(body, content_length);
|
||||
|
||||
rapidjson::Document doc;
|
||||
if (doc.Parse(body).HasParseError()) {
|
||||
SOFAE_LOG_ERROR("Fail to parse report response body");
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
|
||||
return content_length;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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, kStrHeaderAdvisoryIDs,
|
||||
strlen(kStrHeaderAdvisoryIDs)) == 0) {
|
||||
report->set_advisory_ids(GetHeaderValue(header, kStrHeaderAdvisoryIDs));
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
std::mutex RaIasClient::init_mutex_;
|
||||
|
||||
void RaIasClient::InitIasConnection(const std::string& endpoint) {
|
||||
if (endpoint.empty()) {
|
||||
curl_ = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// curl_global_init is not multithreads safe function. It's suggested to
|
||||
// call it in main thread. Here we just add lock to make sure safety, but
|
||||
// don't consider the performance, as multithreads is not common usecase.
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(init_mutex_);
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
}
|
||||
|
||||
curl_ = curl_easy_init();
|
||||
if (!curl_) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
/* set libcurl verbose */
|
||||
curl_easy_setopt(curl_, CURLOPT_VERBOSE, 1L);
|
||||
#endif
|
||||
|
||||
/* set the common header */
|
||||
headers_ = curl_slist_append(NULL, "Accept: application/json");
|
||||
headers_ = curl_slist_append(headers_, "Content-Type: application/json");
|
||||
curl_easy_setopt(curl_, CURLOPT_HTTPHEADER, headers_);
|
||||
curl_easy_setopt(curl_, CURLOPT_USERAGENT, "sgx-sp/1.0");
|
||||
|
||||
/* set commom option */
|
||||
curl_easy_setopt(curl_, CURLOPT_FORBID_REUSE, 1L);
|
||||
curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(curl_, CURLOPT_TIMEOUT, 60L);
|
||||
curl_easy_setopt(curl_, CURLOPT_CONNECTTIMEOUT, 10L);
|
||||
|
||||
server_endpoint_ = endpoint;
|
||||
}
|
||||
|
||||
RaIasClient::RaIasClient(const std::string& endpoint) {
|
||||
InitIasConnection(endpoint);
|
||||
}
|
||||
|
||||
RaIasClient::RaIasClient(const SofaeServerCfg& ias_server) {
|
||||
// Configure the other normal settings firstly.
|
||||
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)) {
|
||||
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);
|
||||
curl_easy_setopt(curl_, CURLOPT_SSLKEYTYPE, ias_cert_key_type);
|
||||
}
|
||||
}
|
||||
|
||||
RaIasClient::~RaIasClient() {
|
||||
if (headers_) {
|
||||
curl_slist_free_all(headers_);
|
||||
}
|
||||
if (curl_) {
|
||||
curl_easy_cleanup(curl_);
|
||||
}
|
||||
|
||||
// add lock for multi-threads safety
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(init_mutex_);
|
||||
curl_global_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
SofaeErrorCode 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;
|
||||
}
|
||||
|
||||
/* Set the URL */
|
||||
std::string url = server_endpoint_ + "/attestation/sgx/v3/sigrl/";
|
||||
std::vector<char> tmp_gid_vec(sizeof(sgx_epid_group_id_t) * 2, 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());
|
||||
SOFAE_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;
|
||||
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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!ias_sigrl.b64_sigrl.empty()) {
|
||||
std::vector<uint8_t> sigrl_vec;
|
||||
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;
|
||||
}
|
||||
sigrl->assign(RCAST(const char *, sigrl_vec.data()), sigrl_vec.size());
|
||||
}
|
||||
return SOFAE_SUCCESS;
|
||||
}
|
||||
|
||||
SofaeErrorCode RaIasClient::FetchReport(const std::string& quote,
|
||||
IasReport *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;
|
||||
}
|
||||
|
||||
if (!curl_) {
|
||||
SOFAE_LOG_ERROR("IAS client is not initialized!");
|
||||
return SOFAE_ERROR_IAS_CLIENT_INIT;
|
||||
}
|
||||
|
||||
/* Set the report url */
|
||||
std::string url = server_endpoint_ + "/attestation/sgx/v3/report";
|
||||
SOFAE_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()),
|
||||
SCAST(size_t, quote.length()));
|
||||
SOFAE_LOG_DEBUG("QUTEO[%lu]: %s", b64_quote.length(), b64_quote.c_str());
|
||||
std::string post_data = "{\"isvEnclaveQuote\": \"";
|
||||
post_data += b64_quote;
|
||||
post_data += "\"}";
|
||||
curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, post_data.c_str());
|
||||
|
||||
/* 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));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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(),
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
SOFAE_LOG_ERROR("Fail to get quote report from IAS");
|
||||
return SOFAE_ERROR_IAS_CLIENT_GETREPORT;
|
||||
}
|
||||
|
||||
return SOFAE_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace occlum
|
||||
} // namespace sofaenclave
|
251
demos/remote_attestation/lib/src/ra_json.cpp
Normal file
251
demos/remote_attestation/lib/src/ra_json.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "sofaenclave/common/error.h"
|
||||
#include "sofaenclave/common/log.h"
|
||||
#include "sofaenclave/ra_json.h"
|
||||
|
||||
namespace sofaenclave {
|
||||
namespace occlum {
|
||||
|
||||
static SofaeErrorCode FsReadString(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;
|
||||
}
|
||||
|
||||
ifs.seekg(0, std::ios::end);
|
||||
int length = ifs.tellg();
|
||||
ifs.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<char> 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;
|
||||
}
|
||||
|
||||
str->assign(buf.data(), length);
|
||||
return SOFAE_SUCCESS;
|
||||
}
|
||||
|
||||
static bool FsFileExists(const std::string& filename) {
|
||||
std::ifstream ifs(filename, std::ios::binary | std::ios::in);
|
||||
return ifs.good();
|
||||
}
|
||||
|
||||
JsonConfig* JsonConfig::GetInstance() {
|
||||
static JsonConfig instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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());
|
||||
return value;
|
||||
} else {
|
||||
SOFAE_LOG_DEBUG("Not string type, %s=%s[default]", name, default_val);
|
||||
return default_val;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SofaeErrorCode JsonConfig::GetStrArray(const T& conf, const char* name,
|
||||
std::vector<std::string>* 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());
|
||||
values->push_back(val_str);
|
||||
} else {
|
||||
SOFAE_LOG_ERROR("Invalid string type in Array");
|
||||
return SOFAE_ERROR_PARSE_CONFIGURATIONS;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SOFAE_LOG_DEBUG("Invalid Array type");
|
||||
return SOFAE_ERROR_PARSE_CONFIGURATIONS;
|
||||
}
|
||||
return SOFAE_SUCCESS;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SofaeErrorCode 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;
|
||||
}
|
||||
|
||||
*value = conf[name].GetInt();
|
||||
SOFAE_LOG_DEBUG("%s=%d", name, *value);
|
||||
return SOFAE_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());
|
||||
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());
|
||||
return etcpath;
|
||||
}
|
||||
|
||||
// If cannot find configuration file, return empty string
|
||||
SOFAE_LOG_ERROR("Cannot find configuration file: %s", filename.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
SofaeErrorCode JsonConfig::LoadConfiguration(const std::string& filename) {
|
||||
if (filename.empty()) {
|
||||
SOFAE_LOG_ERROR("Empty configuration file name");
|
||||
return SOFAE_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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
SofaeJsonDocPtr 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;
|
||||
}
|
||||
|
||||
cfgs_.emplace(filename, doc);
|
||||
SOFAE_LOG_DEBUG("Load configuration file %s successfully", filename.c_str());
|
||||
return SOFAE_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());
|
||||
|
||||
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);
|
||||
return default_val;
|
||||
}
|
||||
}
|
||||
|
||||
return GetStr(*cfgs_[conf_file].get(), name, default_val);
|
||||
}
|
||||
|
||||
SofaeErrorCode JsonConfig::ConfGetStrArray(const std::string& conf_file,
|
||||
const char* name,
|
||||
std::vector<std::string>* values) {
|
||||
SOFAE_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;
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return GetInt(*cfgs_[conf_file].get(), name, value);
|
||||
}
|
||||
|
||||
} // namespace occlum
|
||||
} // namespace sofaenclave
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
SofaeErrorCode SofaeConfGetStrArray(const std::string& conf_file,
|
||||
const char* name,
|
||||
std::vector<std::string>* values) {
|
||||
return sofaenclave::occlum::JsonConfig::GetInstance()->ConfGetStrArray(
|
||||
conf_file, name, values);
|
||||
}
|
||||
|
||||
SofaeErrorCode SofaeConfGetInt(const std::string& conf_file, const char* name,
|
||||
int* value) {
|
||||
return sofaenclave::occlum::JsonConfig::GetInstance()->ConfGetInt(
|
||||
conf_file, name, value);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
88
demos/remote_attestation/lib/src/ra_manager.cpp
Normal file
88
demos/remote_attestation/lib/src/ra_manager.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#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,
|
||||
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
|
26
demos/remote_attestation/lib/src/ra_report.cpp
Normal file
26
demos/remote_attestation/lib/src/ra_report.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <string>
|
||||
|
||||
#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
|
26
demos/remote_attestation/run_on_occlum.sh
Executable file
26
demos/remote_attestation/run_on_occlum.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
THISDIR="$(dirname $(readlink -f $0))"
|
||||
DEMPOAPP="remote_attestation_demo"
|
||||
|
||||
# 1. Init Occlum Workspace
|
||||
rm -rf $THISDIR/occlum_workspace && \
|
||||
mkdir -p $THISDIR/occlum_workspace && \
|
||||
cd occlum_workspace &&
|
||||
occlum init || exit 1
|
||||
|
||||
# 2. Copy files into Occlum Workspace and Build
|
||||
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/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
|
||||
cp /usr/local/occlum/x86_64-linux-musl/lib/libcurl.so.4 image/lib
|
||||
occlum build
|
||||
|
||||
# 3. Run application
|
||||
occlum run /bin/$DEMPOAPP
|
Loading…
Reference in New Issue
Block a user