Add support for DCAP

1. Five new ioctl commands of /dev/sgx are added for occlum
applications to securely get and verify DCAP quote;
2. Not all the functions of the intel DCAP package are open to
developers to simplify the DCAP usage;
3. The test may only run on the platform with DCAP driver installed;
4. A macro OCCLUM_DISABLE_DCAP is used to separate the DCAP code from
the other code.
5. Skip DCAP test when DCAP driver is not detected or in simulation mode
This commit is contained in:
He Sun 2020-12-14 05:04:52 +00:00 committed by Tate, Hongliang Tian
parent dc7599c87c
commit f1e5f574ca
19 changed files with 742 additions and 57 deletions

@ -60,7 +60,7 @@ test-glibc:
@$(MAKE) --no-print-directory -C test test-glibc
OCCLUM_PREFIX ?= /opt/occlum
install: $(OCCLUM_PREFIX)/sgxsdk-tools/lib64/libsgx_uae_service_sim.so
install: minimal_sgx_libs
@# Install both libraries for HW mode and SIM mode
@$(MAKE) SGX_MODE=HW --no-print-directory -C src
@$(MAKE) SGX_MODE=SIM --no-print-directory -C src
@ -88,16 +88,18 @@ install: $(OCCLUM_PREFIX)/sgxsdk-tools/lib64/libsgx_uae_service_sim.so
@echo "Installation is done."
SGX_SDK=/opt/intel/sgxsdk
# Install minimum sgx-sdk set to support Occlum cmd execution in non-customized sgx-sdk environment
$(OCCLUM_PREFIX)/sgxsdk-tools/lib64/libsgx_uae_service_sim.so: /opt/intel/sgxsdk/lib64/libsgx_uae_service_sim.so
minimal_sgx_libs: $(SGX_SDK)/lib64/libsgx_uae_service_sim.so $(SGX_SDK)/lib64/libsgx_quote_ex_sim.so
@echo "Install needed sgx-sdk tools ..."
@mkdir -p $(OCCLUM_PREFIX)/sgxsdk-tools/lib64
@cp /opt/intel/sgxsdk/lib64/{libsgx_ptrace.so,libsgx_uae_service_sim.so} $(OCCLUM_PREFIX)/sgxsdk-tools/lib64
@cp $(SGX_SDK)/lib64/{libsgx_ptrace.so,libsgx_uae_service_sim.so,libsgx_quote_ex_sim.so} $(OCCLUM_PREFIX)/sgxsdk-tools/lib64
@mkdir -p $(OCCLUM_PREFIX)/sgxsdk-tools/lib64/gdb-sgx-plugin
@cd /opt/intel/sgxsdk/lib64/gdb-sgx-plugin/ && cp $$(ls -A | grep -v __pycache__) $(OCCLUM_PREFIX)/sgxsdk-tools/lib64/gdb-sgx-plugin
@cd /opt/intel/sgxsdk && cp -a --parents {bin/sgx-gdb,bin/x64/sgx_sign} $(OCCLUM_PREFIX)/sgxsdk-tools/
@cd $(SGX_SDK)/lib64/gdb-sgx-plugin/ && cp $$(ls -A | grep -v __pycache__) $(OCCLUM_PREFIX)/sgxsdk-tools/lib64/gdb-sgx-plugin
@cd $(SGX_SDK) && cp -a --parents {bin/sgx-gdb,bin/x64/sgx_sign} $(OCCLUM_PREFIX)/sgxsdk-tools/
@mkdir -p $(OCCLUM_PREFIX)/sgxsdk-tools/sdk_libs && cd $(OCCLUM_PREFIX)/sgxsdk-tools/sdk_libs && \
ln -sf ../lib64/libsgx_uae_service_sim.so libsgx_uae_service_sim.so
ln -sf ../lib64/libsgx_uae_service_sim.so libsgx_uae_service_sim.so && \
ln -sf ../lib64/libsgx_quote_ex_sim.so libsgx_quote_ex_sim.so
@# Delete SGX_LIBRARY_PATH env in sgx-gdb which are defined in etc/environment
@sed -i '/^SGX_LIBRARY_PATH=/d' $(OCCLUM_PREFIX)/sgxsdk-tools/bin/sgx-gdb
@cp etc/environment $(OCCLUM_PREFIX)/sgxsdk-tools/

@ -10,6 +10,28 @@ enclave {
include "sgx_quote.h"
include "occlum_edl_types.h"
include "sgx_ql_quote.h"
include "sgx_qve_header.h"
// for deep copy of the inside contents
struct sgx_ql_qve_collateral {
uint32_t version;
[size=pck_crl_issuer_chain_size] char *pck_crl_issuer_chain;
uint32_t pck_crl_issuer_chain_size;
[size=root_ca_crl_size] char *root_ca_crl;
uint32_t root_ca_crl_size;
[size=pck_crl_size] char *pck_crl;
uint32_t pck_crl_size;
[size=tcb_info_issuer_chain_size] char *tcb_info_issuer_chain;
uint32_t tcb_info_issuer_chain_size;
[size=tcb_info_size] char *tcb_info;
uint32_t tcb_info_size;
[size=qe_identity_issuer_chain_size] char *qe_identity_issuer_chain;
uint32_t qe_identity_issuer_chain_size;
[size=qe_identity_size] char *qe_identity;
uint32_t qe_identity_size;
};
trusted {
/*
* Initialize the LibOS according to the specified attributes.
@ -151,7 +173,7 @@ enclave {
sgx_status_t occlum_ocall_sgx_init_quote(
[out] sgx_target_info_t* target_info,
[out] sgx_epid_group_id_t* epid_group_id);
sgx_status_t occlum_ocall_sgx_get_quote(
sgx_status_t occlum_ocall_sgx_get_epid_quote(
[in, size=sigrl_len] uint8_t* sigrl,
uint32_t sigrl_len,
[in] sgx_report_t* report,
@ -162,6 +184,29 @@ enclave {
[out, size=quote_buf_len] sgx_quote_t* quote_buf,
uint32_t quote_buf_len);
int occlum_ocall_detect_dcap_driver() propagate_errno;
quote3_error_t occlum_ocall_init_dcap_quote_generator(
[out] sgx_target_info_t* qe_target_info,
[out] uint32_t* quote_size
) propagate_errno;
quote3_error_t occlum_ocall_generate_dcap_quote(
[in] sgx_report_t* app_report,
uint32_t quote_size,
[out, size=quote_size] uint8_t* quote_buf
) propagate_errno;
uint32_t occlum_ocall_get_supplement_size() propagate_errno;
quote3_error_t occlum_ocall_verify_dcap_quote(
[in, size=quote_size] uint8_t* quote_buf,
uint32_t quote_size,
[in] struct sgx_ql_qve_collateral* quote_collateral,
time_t expiration_check_date,
[out] uint32_t* collateral_expiration_status,
[out] sgx_ql_qv_result_t* quote_verification_result,
[in, out] sgx_ql_qe_report_info_t* qve_report_info,
uint32_t supplemental_data_size,
[out, size=supplemental_data_size] uint8_t* supplemental_data
) propagate_errno;
int64_t occlum_ocall_sendmsg(
int sockfd,
[in, size=msg_namelen] const void* msg_name,

@ -34,6 +34,7 @@ syscall_timing = [] # Timing for each syscall. But it has cost from more oca
integrity_only_opt = [] # Clear bss only. It should be disabled if checking memory reads.
sgx_file_cache = [] # Cache SgxFile objects. Invalidation is unimplemented.
sgx1_exception_sim = [] # Simulate #PF and #GP exceptions on SGX 1
dcap = [] # DCAP support. The compilation relies on DCAP package.
[target.'cfg(not(target_env = "sgx"))'.dependencies]
xmas-elf = { path = "../../deps/xmas-elf" }

@ -86,6 +86,9 @@ CXX_FLAGS := $(SGX_CXXFLAGS_T) $(C_COMMON_FLAGS)
_Other_Link_Flags := -L$(RUST_SGX_SDK_DIR)/compiler-rt/ -L$(BUILD_DIR)/lib -L$(RUST_OUT_DIR)
_Other_Enclave_Libs := -l$(LIBOS_CORE_LIB_NAME) -lsgx_tprotected_fs
ifndef OCCLUM_DISABLE_DCAP
_Other_Enclave_Libs += -lsgx_dcap_tvl
endif
LINK_FLAGS := $(SGX_LFLAGS_T)
.PHONY: all clean format format-c format-rust format-check format-check-c format-check-rust
@ -112,13 +115,19 @@ else
RUSTC_WRAPPER :=
endif
LIBOS_FEATURES :=
ifndef OCCLUM_DISABLE_DCAP
LIBOS_FEATURES += dcap
endif
ifeq ($(OCCLUM_RELEASE_BUILD), 1)
$(LIBOS_CORE_RS_A): $(RUST_SRCS)
@RUSTC_BOOTSTRAP=1 RUSTC_WRAPPER=$(RUSTC_WRAPPER) cargo build --release --target-dir=$(RUST_TARGET_DIR) -Z unstable-options --out-dir=$(RUST_OUT_DIR)
@RUSTC_BOOTSTRAP=1 RUSTC_WRAPPER=$(RUSTC_WRAPPER) cargo build --release --target-dir=$(RUST_TARGET_DIR) -Z unstable-options --out-dir=$(RUST_OUT_DIR) --features "$(LIBOS_FEATURES)"
@echo "CARGO (release) => $@"
else
$(LIBOS_CORE_RS_A): $(RUST_SRCS)
@RUSTC_BOOTSTRAP=1 RUSTC_WRAPPER=$(RUSTC_WRAPPER) cargo build --target-dir=$(RUST_TARGET_DIR) -Z unstable-options --out-dir=$(RUST_OUT_DIR)
@RUSTC_BOOTSTRAP=1 RUSTC_WRAPPER=$(RUSTC_WRAPPER) cargo build --target-dir=$(RUST_TARGET_DIR) -Z unstable-options --out-dir=$(RUST_OUT_DIR) --features "$(LIBOS_FEATURES)"
@echo "CARGO (debug) => $@"
endif

@ -3,6 +3,7 @@ use super::*;
/// Ioctl to check if EDMM (Enclave Dynamic Memory Management) is supported
pub const SGX_CMD_NUM_IS_EDMM_SUPPORTED: u32 =
StructuredIoctlNum::new::<i32>(0, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output).as_u32();
/// Ioctl to get the EPID group ID
pub const SGX_CMD_NUM_GET_EPID_GROUP_ID: u32 = StructuredIoctlNum::new::<sgx_epid_group_id_t>(
1,
@ -10,17 +11,20 @@ pub const SGX_CMD_NUM_GET_EPID_GROUP_ID: u32 = StructuredIoctlNum::new::<sgx_epi
StructuredIoctlArgType::Output,
)
.as_u32();
/// Ioctl to get quote
pub const SGX_CMD_NUM_GEN_QUOTE: u32 = StructuredIoctlNum::new::<IoctlGenQuoteArg>(
/// Ioctl to get EPID quote
pub const SGX_CMD_NUM_GEN_EPID_QUOTE: u32 = StructuredIoctlNum::new::<IoctlGenEPIDQuoteArg>(
2,
SGX_MAGIC_CHAR,
StructuredIoctlArgType::InputOutput,
)
.as_u32();
/// Ioctl to get the target info of the current enclave
pub const SGX_CMD_NUM_SELF_TARGET: u32 =
StructuredIoctlNum::new::<sgx_target_info_t>(3, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output)
.as_u32();
/// Ioctl to create a report
pub const SGX_CMD_NUM_CREATE_REPORT: u32 = StructuredIoctlNum::new::<IoctlCreateReportArg>(
4,
@ -28,10 +32,43 @@ pub const SGX_CMD_NUM_CREATE_REPORT: u32 = StructuredIoctlNum::new::<IoctlCreate
StructuredIoctlArgType::InputOutput,
)
.as_u32();
/// Ioctl to verify a report
pub const SGX_CMD_NUM_VERIFY_REPORT: u32 =
StructuredIoctlNum::new::<sgx_report_t>(5, SGX_MAGIC_CHAR, StructuredIoctlArgType::Input)
.as_u32();
/// Ioctl to check if DCAP driver is installed on host
pub const SGX_CMD_NUM_DETECT_DCAP_DRIVER: u32 =
StructuredIoctlNum::new::<i32>(6, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output).as_u32();
#[cfg(feature = "dcap")]
/// Ioctl to get DCAP quote size
pub const SGX_CMD_NUM_GET_DCAP_QUOTE_SIZE: u32 =
StructuredIoctlNum::new::<i32>(7, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output).as_u32();
#[cfg(feature = "dcap")]
/// Ioctl to get DCAP quote
pub const SGX_CMD_NUM_GEN_DCAP_QUOTE: u32 = StructuredIoctlNum::new::<IoctlGenDCAPQuoteArg>(
8,
SGX_MAGIC_CHAR,
StructuredIoctlArgType::InputOutput,
)
.as_u32();
#[cfg(feature = "dcap")]
/// Ioctl to get the verfication supplemental data size
pub const SGX_CMD_NUM_GET_DCAP_SUPPLEMENTAL_SIZE: u32 =
StructuredIoctlNum::new::<i32>(9, SGX_MAGIC_CHAR, StructuredIoctlArgType::Output).as_u32();
#[cfg(feature = "dcap")]
/// Ioctl to verify DCAP quote
pub const SGX_CMD_NUM_VER_DCAP_QUOTE: u32 = StructuredIoctlNum::new::<IoctlVerDCAPQuoteArg>(
10,
SGX_MAGIC_CHAR,
StructuredIoctlArgType::InputOutput,
)
.as_u32();
/// A magical number that distinguishes SGX ioctls for other ioctls
const SGX_MAGIC_CHAR: u8 = 's' as u8;

@ -5,8 +5,13 @@ use super::*;
mod consts;
use self::consts::*;
use util::mem_util::from_user::*;
use util::sgx::*;
extern "C" {
static EDMM_supported: i32;
}
#[derive(Debug)]
pub struct DevSgx;
@ -20,15 +25,15 @@ impl File for DevSgx {
match cmd_num {
SGX_CMD_NUM_IS_EDMM_SUPPORTED => {
let arg = nonbuiltin_cmd.arg_mut::<i32>()?;
*arg = 0; // no support for now
*arg = unsafe { EDMM_supported };
}
SGX_CMD_NUM_GET_EPID_GROUP_ID => {
let arg = nonbuiltin_cmd.arg_mut::<sgx_epid_group_id_t>()?;
*arg = SGX_ATTEST_AGENT.lock().unwrap().get_epid_group_id()?;
*arg = SGX_EPID_ATTEST_AGENT.lock().unwrap().get_epid_group_id()?;
}
SGX_CMD_NUM_GEN_QUOTE => {
SGX_CMD_NUM_GEN_EPID_QUOTE => {
// Prepare the arguments
let arg = nonbuiltin_cmd.arg_mut::<IoctlGenQuoteArg>()?;
let arg = nonbuiltin_cmd.arg_mut::<IoctlGenEPIDQuoteArg>()?;
let sigrl = {
let sigrl_ptr = arg.sigrl_ptr;
let sigrl_len = arg.sigrl_len as usize;
@ -50,7 +55,7 @@ impl File for DevSgx {
};
// Generate the quote
let quote = SGX_ATTEST_AGENT.lock().unwrap().generate_quote(
let quote = SGX_EPID_ATTEST_AGENT.lock().unwrap().generate_quote(
sigrl,
&arg.report_data,
arg.quote_type,
@ -88,6 +93,87 @@ impl File for DevSgx {
let arg = nonbuiltin_cmd.arg::<sgx_report_t>()?;
verify_report(arg)?;
}
SGX_CMD_NUM_DETECT_DCAP_DRIVER => {
let arg = nonbuiltin_cmd.arg_mut::<i32>()?;
unsafe {
let sgx_status = occlum_ocall_detect_dcap_driver(arg);
assert_eq!(sgx_status, sgx_status_t::SGX_SUCCESS);
}
extern "C" {
fn occlum_ocall_detect_dcap_driver(driver_installed: *mut i32) -> sgx_status_t;
}
}
#[cfg(feature = "dcap")]
SGX_CMD_NUM_GET_DCAP_QUOTE_SIZE => {
let arg = nonbuiltin_cmd.arg_mut::<u32>()?;
let quote_size = SGX_DCAP_QUOTE_GENERATOR.get_quote_size();
unsafe {
*arg = quote_size;
}
}
#[cfg(feature = "dcap")]
SGX_CMD_NUM_GEN_DCAP_QUOTE => {
let arg = nonbuiltin_cmd.arg_mut::<IoctlGenDCAPQuoteArg>()?;
check_ptr(arg.quote_size)?;
let input_len = unsafe { *arg.quote_size };
check_mut_array(arg.quote_buf, input_len as usize)?;
let quote_size = SGX_DCAP_QUOTE_GENERATOR.get_quote_size();
if input_len < quote_size {
return_errno!(EINVAL, "provided quote is too small");
}
let quote =
SGX_DCAP_QUOTE_GENERATOR.generate_quote(unsafe { &*arg.report_data })?;
let mut input_quote_buf =
unsafe { std::slice::from_raw_parts_mut(arg.quote_buf, quote_size as usize) };
input_quote_buf.copy_from_slice(&quote);
}
#[cfg(feature = "dcap")]
SGX_CMD_NUM_GET_DCAP_SUPPLEMENTAL_SIZE => {
let arg = nonbuiltin_cmd.arg_mut::<u32>()?;
let supplemental_size = SGX_DCAP_QUOTE_VERIFIER.get_supplemental_data_size();
unsafe {
*arg = supplemental_size;
}
}
#[cfg(feature = "dcap")]
SGX_CMD_NUM_VER_DCAP_QUOTE => {
let arg = nonbuiltin_cmd.arg_mut::<IoctlVerDCAPQuoteArg>()?;
let quote_size = arg.quote_size as usize;
let supplemental_size = SGX_DCAP_QUOTE_VERIFIER.get_supplemental_data_size();
check_array(arg.quote_buf, quote_size)?;
let supplemental_slice = if !arg.supplemental_data.is_null() {
check_array(arg.supplemental_data, arg.supplemental_data_size as usize)?;
if arg.supplemental_data_size < supplemental_size {
return_errno!(EINVAL, "provided supplemental buffer is too short");
}
Some(unsafe {
std::slice::from_raw_parts_mut(
arg.supplemental_data,
supplemental_size as usize,
)
})
} else {
None
};
let input_quote_buf =
unsafe { std::slice::from_raw_parts(arg.quote_buf, quote_size) };
let (collateral_expiration_status, quote_verification_result, supplemental_data) =
SGX_DCAP_QUOTE_VERIFIER.verify_quote(input_quote_buf)?;
unsafe {
*arg.collateral_expiration_status = collateral_expiration_status;
*arg.quote_verification_result = quote_verification_result;
}
if let Some(slice) = supplemental_slice {
slice.copy_from_slice(&supplemental_data);
}
}
_ => {
return_errno!(ENOSYS, "unknown ioctl cmd for /dev/sgx");
}
@ -105,14 +191,19 @@ impl File for DevSgx {
}
lazy_static! {
/// The root of file system
pub static ref SGX_ATTEST_AGENT: SgxMutex<SgxAttestationAgent> = {
SgxMutex::new(SgxAttestationAgent::new())
};
pub static ref SGX_EPID_ATTEST_AGENT: SgxMutex<SgxEPIDAttestationAgent> =
{ SgxMutex::new(SgxEPIDAttestationAgent::new()) };
}
#[cfg(feature = "dcap")]
lazy_static! {
pub static ref SGX_DCAP_QUOTE_GENERATOR: SgxDCAPQuoteGenerator =
{ SgxDCAPQuoteGenerator::new() };
pub static ref SGX_DCAP_QUOTE_VERIFIER: SgxDCAPQuoteVerifier = { SgxDCAPQuoteVerifier::new() };
}
#[repr(C)]
struct IoctlGenQuoteArg {
struct IoctlGenEPIDQuoteArg {
report_data: sgx_report_data_t, // Input
quote_type: sgx_quote_sign_type_t, // Input
spid: sgx_spid_t, // Input
@ -129,3 +220,22 @@ struct IoctlCreateReportArg {
report_data: *const sgx_report_data_t, // Input (optional)
report: *mut sgx_report_t, // Output
}
#[cfg(feature = "dcap")]
#[repr(C)]
struct IoctlGenDCAPQuoteArg {
report_data: *const sgx_report_data_t, // Input
quote_size: *mut u32, // Input/output
quote_buf: *mut u8, // Output
}
#[cfg(feature = "dcap")]
#[repr(C)]
struct IoctlVerDCAPQuoteArg {
quote_buf: *const u8, // Input
quote_size: u32, // Input
collateral_expiration_status: *mut u32, // Output
quote_verification_result: *mut sgx_ql_qv_result_t, // Output
supplemental_data_size: u32, // Input (optional)
supplemental_data: *mut u8, // Output (optional)
}

@ -0,0 +1,7 @@
use super::*;
mod quote_generator;
mod quote_verifier;
pub use quote_generator::QuoteGenerator;
pub use quote_verifier::QuoteVerifier;

@ -0,0 +1,76 @@
use super::*;
pub use sgx_types::{sgx_ql_qv_result_t, sgx_quote3_error_t, sgx_report_data_t, sgx_target_info_t};
pub struct QuoteGenerator {
qe_target_info: sgx_target_info_t,
quote_size: u32,
}
impl QuoteGenerator {
pub fn new() -> Self {
let mut qe_target_info = sgx_target_info_t::default();
let mut quote_size: u32 = 0;
unsafe {
let mut qe3_ret = sgx_quote3_error_t::SGX_QL_SUCCESS;
let sgx_status = occlum_ocall_init_dcap_quote_generator(
&mut qe3_ret,
&mut qe_target_info,
&mut quote_size,
);
assert_eq!(sgx_status_t::SGX_SUCCESS, sgx_status);
assert_eq!(
sgx_quote3_error_t::SGX_QL_SUCCESS,
qe3_ret,
"fail to launch QE"
);
}
Self {
qe_target_info,
quote_size,
}
}
pub fn get_quote_size(&self) -> u32 {
self.quote_size
}
pub fn generate_quote(&self, report_data: &sgx_report_data_t) -> Result<Vec<u8>> {
let mut quote = vec![0; self.quote_size as usize];
let mut qe3_ret = sgx_quote3_error_t::SGX_QL_SUCCESS;
let app_report = create_report(Some(&self.qe_target_info), Some(report_data))?;
unsafe {
let sgx_status = occlum_ocall_generate_dcap_quote(
&mut qe3_ret,
&app_report,
self.quote_size,
quote.as_mut_ptr(),
);
assert_eq!(sgx_status_t::SGX_SUCCESS, sgx_status);
}
match qe3_ret {
sgx_quote3_error_t::SGX_QL_SUCCESS => Ok(quote),
sgx_quote3_error_t::SGX_QL_ERROR_BUSY => {
return_errno!(EBUSY, "occlum_ocall_sgx_gen_dcap_quote is temporarily busy");
}
_ => return_errno!(EINVAL, "occlum_ocall_sgx_gen_dcap_quote failed"),
}
}
}
extern "C" {
fn occlum_ocall_init_dcap_quote_generator(
ret: *mut sgx_quote3_error_t,
qe_target_info: *mut sgx_target_info_t,
quote_size: *mut uint32_t,
) -> sgx_status_t;
fn occlum_ocall_generate_dcap_quote(
ret: *mut sgx_quote3_error_t,
app_report: *const sgx_report_t,
quote_size: uint32_t,
quote_buf: *mut uint8_t,
) -> sgx_status_t;
}

@ -0,0 +1,116 @@
use super::*;
pub struct QuoteVerifier {
supplemental_data_size: u32,
}
// The latest QvE ISVSVN from Intel PCS.
// It should be updated when a newer QvE is released.
const QVE_ISVSVN_THRESHOLD: sgx_isv_svn_t = 3;
impl QuoteVerifier {
pub fn new() -> Self {
let mut supplemental_data_size = 0;
unsafe {
let sgx_status = occlum_ocall_get_supplement_size(&mut supplemental_data_size);
assert_eq!(sgx_status_t::SGX_SUCCESS, sgx_status);
assert_ne!(supplemental_data_size, 0);
}
Self {
supplemental_data_size,
}
}
pub fn get_supplemental_data_size(&self) -> u32 {
self.supplemental_data_size
}
pub fn verify_quote(&self, quote: &[u8]) -> Result<(u32, sgx_ql_qv_result_t, Vec<u8>)> {
let mut qe3_ret = sgx_quote3_error_t::SGX_QL_SUCCESS;
// FIXME: a trusted time should be provided here in production mode
let current_time = time::do_gettimeofday().as_duration().as_secs() as time_t;
let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK;
let mut collateral_expiration_status = 1;
let mut supplemental_data = vec![0; self.supplemental_data_size as usize];
let mut qve_report_info = sgx_ql_qe_report_info_t::default();
unsafe {
let sgx_status = sgx_read_rand(
qve_report_info.nonce.rand.as_mut_ptr(),
qve_report_info.nonce.rand.len(),
);
if sgx_status != sgx_status_t::SGX_SUCCESS {
return_errno!(EAGAIN, "failed to get random number from sgx");
}
}
qve_report_info.app_enclave_target_info = get_self_target()?;
unsafe {
let sgx_status = occlum_ocall_verify_dcap_quote(
&mut qe3_ret,
quote.as_ptr(),
quote.len() as u32,
std::ptr::null(),
current_time,
&mut collateral_expiration_status,
&mut quote_verification_result,
&mut qve_report_info,
supplemental_data.len() as u32,
supplemental_data.as_mut_ptr(),
);
assert_eq!(sgx_status_t::SGX_SUCCESS, sgx_status);
}
match qe3_ret {
sgx_quote3_error_t::SGX_QL_SUCCESS => {
let qe3_ret = unsafe {
sgx_tvl_verify_qve_report_and_identity(
quote.as_ptr(),
quote.len() as u32,
&qve_report_info,
current_time,
collateral_expiration_status,
quote_verification_result,
supplemental_data.as_ptr(),
supplemental_data.len() as u32,
QVE_ISVSVN_THRESHOLD,
)
};
if qe3_ret == sgx_quote3_error_t::SGX_QL_SUCCESS {
Ok((
collateral_expiration_status,
quote_verification_result,
supplemental_data,
))
} else {
debug!("returned qe3 error is {}", qe3_ret);
return_errno!(EINVAL, "failed to verify quote");
}
}
sgx_quote3_error_t::SGX_QL_ERROR_BUSY => {
return_errno!(EBUSY, "occlum_ocall_sgx_ver_dcap_quote is temporarily busy");
}
_ => return_errno!(EINVAL, "occlum_ocall_sgx_ver_dcap_quote failed"),
}
}
}
extern "C" {
fn occlum_ocall_get_supplement_size(size: *mut u32) -> sgx_status_t;
// sgx_ql_qve_collateral_t uses char that is not FFI-safe. It will raise improper_ctypes
// warning. As only char pointer is used, we allow the use here.
#[allow(improper_ctypes)]
fn occlum_ocall_verify_dcap_quote(
ret: *mut sgx_quote3_error_t,
quote_buf: *const uint8_t,
quote_size: uint32_t,
quote_collateral: *const sgx_ql_qve_collateral_t,
expiration_check_date: time_t,
collateral_expiration_status: *mut uint32_t,
quote_verification_result: *mut sgx_ql_qv_result_t,
qve_report_info: *mut sgx_ql_qe_report_info_t,
supplemental_data_size: uint32_t,
supplemental_data: *mut uint8_t,
) -> sgx_status_t;
}

@ -2,12 +2,12 @@
use super::*;
pub struct SgxAttestationAgent {
pub struct AttestationAgent {
inner: Option<InnerAgent>,
}
impl SgxAttestationAgent {
pub fn new() -> SgxAttestationAgent {
impl AttestationAgent {
pub fn new() -> Self {
Self { inner: None }
}
@ -23,7 +23,7 @@ impl SgxAttestationAgent {
quote_type: sgx_quote_sign_type_t,
spid: &sgx_spid_t,
nonce: &sgx_quote_nonce_t,
) -> Result<SgxQuote> {
) -> Result<Quote> {
self.init_inner()?;
self.inner
.as_mut()
@ -98,9 +98,9 @@ impl InnerAgent {
quote_type: sgx_quote_sign_type_t,
spid: &sgx_spid_t,
nonce: &sgx_quote_nonce_t,
) -> Result<SgxQuote> {
) -> Result<Quote> {
extern "C" {
pub fn occlum_ocall_sgx_get_quote(
pub fn occlum_ocall_sgx_get_epid_quote(
retval: *mut sgx_status_t, // Output
sigrl: *const u8, // Input (optional)
sigrl_len: u32, // Input (optional)
@ -158,7 +158,7 @@ impl InnerAgent {
// Do OCall
unsafe {
let mut retval = Default::default();
let status = occlum_ocall_sgx_get_quote(
let status = occlum_ocall_sgx_get_epid_quote(
&mut retval as *mut sgx_status_t,
sigrl_ptr,
sigrl_size,
@ -175,9 +175,9 @@ impl InnerAgent {
if retval != sgx_status_t::SGX_SUCCESS {
match retval {
sgx_status_t::SGX_ERROR_BUSY => {
return_errno!(EBUSY, "occlum_ocall_sgx_get_quote is temporarily busy")
return_errno!(EBUSY, "occlum_ocall_sgx_get_epid_quote is temporarily busy")
}
_ => return_errno!(EINVAL, "occlum_ocall_sgx_get_quote failed"),
_ => return_errno!(EINVAL, "occlum_ocall_sgx_get_epid_quote failed"),
}
}
}
@ -186,7 +186,7 @@ impl InnerAgent {
SgxQeReportValidator::new(&self.target_info, nonce).validate(&qe_report)?;
// Construct the resulting quote
let quote = SgxQuote::new(&quote_buf, &nonce, &qe_report)?;
let quote = Quote::new(&quote_buf, &nonce, &qe_report)?;
Ok(quote)
}

@ -0,0 +1,7 @@
use super::*;
mod attestation_agent;
mod quote;
pub use self::attestation_agent::AttestationAgent;
pub use self::quote::Quote;

@ -1,21 +1,21 @@
//! SGX Quote in a memory safe representation and with hash validation.
//! SGX EPID Quote in a memory safe representation and with hash validation.
use super::*;
#[derive(Debug, Default)]
pub struct SgxQuote {
pub struct Quote {
quote_buf: Vec<u8>,
}
impl SgxQuote {
impl Quote {
pub fn new(
quote_raw_buf: &[u8],
quote_nonce: &sgx_quote_nonce_t,
qe_report: &sgx_report_t,
) -> Result<SgxQuote> {
) -> Result<Self> {
let quote_buf = Self::new_buf(quote_raw_buf)?;
Self::validate_quote_buf(&quote_buf, quote_nonce, qe_report)?;
Ok(SgxQuote { quote_buf })
Ok(Self { quote_buf })
}
fn new_buf(quote_raw_buf: &[u8]) -> Result<Vec<u8>> {

@ -5,8 +5,9 @@ use super::*;
use sgx_tse::*;
use sgx_types::*;
mod sgx_attestation_agent;
mod sgx_quote;
#[cfg(feature = "dcap")]
mod dcap;
mod epid;
mod sgx_report;
pub use sgx_types::{
@ -14,8 +15,11 @@ pub use sgx_types::{
sgx_report_data_t, sgx_self_target, sgx_spid_t, sgx_target_info_t, sgx_verify_report,
};
pub use self::sgx_attestation_agent::SgxAttestationAgent;
pub use self::sgx_quote::SgxQuote;
#[cfg(feature = "dcap")]
pub use self::dcap::{
QuoteGenerator as SgxDCAPQuoteGenerator, QuoteVerifier as SgxDCAPQuoteVerifier,
};
pub use self::epid::AttestationAgent as SgxEPIDAttestationAgent;
pub use self::sgx_report::{create_report, get_self_target, verify_report};
pub fn allow_debug() -> bool {

@ -28,10 +28,21 @@ endif
HEADER_FILES := $(sort $(wildcard src/*.h include/*.h include/*/*.h))
C_COMMON_FLAGS := -I$(OBJ_DIR)/pal/$(SRC_OBJ) -Iinclude -Iinclude/edl
ifdef OCCLUM_DISABLE_DCAP
C_COMMON_FLAGS += -DOCCLUM_DISABLE_DCAP
endif
C_FLAGS := $(C_COMMON_FLAGS) $(SGX_CFLAGS_U)
CXX_FLAGS := $(C_COMMON_FLAGS) $(SGX_CXXFLAGS_U)
LINK_FLAGS := $(SGX_LFLAGS_U) -shared -L$(RUST_SGX_SDK_DIR)/sgx_ustdc/ -lsgx_ustdc -lsgx_uprotected_fs -ldl
LINK_FLAGS += -Wl,--version-script=pal.lds
ifndef OCCLUM_DISABLE_DCAP
LINK_FLAGS += -lsgx_dcap_ql -lsgx_dcap_quoteverify
ifneq ($(SGX_MODE), HW)
LINK_FLAGS += -lsgx_quote_ex_sim
else
LINK_FLAGS += -lsgx_quote_ex
endif
endif
ALL_BUILD_SUBDIRS := $(sort $(patsubst %/,%,$(dir $(LIBOCCLUM_PAL_SO_REAL) $(EDL_C_OBJS) $(C_OBJS) $(CXX_OBJS))))

@ -1,3 +1,10 @@
#ifndef OCCLUM_DISABLE_DCAP
#include <sgx_dcap_ql_wrapper.h>
#include <sgx_dcap_quoteverify.h>
#include <sgx_pce.h>
#include <sgx_ql_quote.h>
#include <sgx_quote_3.h>
#endif
#include <sgx_uae_service.h>
#include "ocalls.h"
@ -10,7 +17,7 @@ sgx_status_t occlum_ocall_sgx_init_quote(
return sgx_init_quote(target_info, epid_group_id);
}
sgx_status_t occlum_ocall_sgx_get_quote(
sgx_status_t occlum_ocall_sgx_get_epid_quote(
uint8_t *sigrl,
uint32_t sigrl_len,
sgx_report_t *report,
@ -52,3 +59,95 @@ sgx_status_t occlum_ocall_sgx_calc_quote_size (
uint32_t *p_quote_size) {
return sgx_calc_quote_size(p_sig_rl, sig_rl_size, p_quote_size);
}
int occlum_ocall_detect_dcap_driver() {
return access("/dev/sgx/enclave", F_OK) == 0 &&
access("/dev/sgx/provision", F_OK) == 0;
}
#define MAX_RETRY 5
quote3_error_t occlum_ocall_init_dcap_quote_generator(
sgx_target_info_t *qe_target_info,
uint32_t *quote_size
) {
#ifndef OCCLUM_DISABLE_DCAP
quote3_error_t qe3_ret = SGX_QL_SUCCESS;
int count = 0;
while ((qe3_ret = sgx_qe_get_target_info(qe_target_info)) == SGX_QL_ERROR_BUSY &&
count < MAX_RETRY) {
count += 1;
sleep(1);
}
if (SGX_QL_SUCCESS != qe3_ret) {
return qe3_ret;
}
count = 0;
while ((qe3_ret = sgx_qe_get_quote_size(quote_size)) == SGX_QL_ERROR_BUSY &&
count < MAX_RETRY) {
count += 1;
sleep(1);
}
return qe3_ret;
#else
return SGX_QL_ERROR_UNEXPECTED;
#endif
}
quote3_error_t occlum_ocall_generate_dcap_quote(
sgx_report_t *app_report,
uint32_t quote_size,
uint8_t *quote_buf
) {
#ifndef OCCLUM_DISABLE_DCAP
return sgx_qe_get_quote(app_report,
quote_size,
quote_buf);
#else
return SGX_QL_ERROR_UNEXPECTED;
#endif
}
uint32_t occlum_ocall_get_supplement_size() {
#ifndef OCCLUM_DISABLE_DCAP
uint32_t supplemental_data_size = 0;
quote3_error_t dcap_ret = sgx_qv_get_quote_supplemental_data_size(
&supplemental_data_size);
if (dcap_ret == SGX_QL_SUCCESS) {
return supplemental_data_size;
} else {
return 0;
}
#else
return 0;
#endif
}
quote3_error_t occlum_ocall_verify_dcap_quote(
uint8_t *quote_buf,
uint32_t quote_size,
struct sgx_ql_qve_collateral *quote_collateral,
time_t expiration_check_date,
uint32_t *collateral_expiration_status,
sgx_ql_qv_result_t *quote_verification_result,
sgx_ql_qe_report_info_t *qve_report_info,
uint32_t supplemental_data_size,
uint8_t *supplemental_data
) {
#ifndef OCCLUM_DISABLE_DCAP
return sgx_qv_verify_quote(
quote_buf, quote_size,
(sgx_ql_qve_collateral_t *)quote_collateral,
expiration_check_date,
collateral_expiration_status,
quote_verification_result,
qve_report_info,
supplemental_data_size,
supplemental_data);
#else
return SGX_QL_ERROR_UNEXPECTED;
#endif
}

@ -3,5 +3,17 @@ include ../test_common.mk
SGX_SDK ?= /opt/intel/sgxsdk
EXTRA_C_FLAGS := -I$(SGX_SDK)/include
ifdef OCCLUM_DISABLE_DCAP
EXTRA_C_FLAGS += -DOCCLUM_DISABLE_DCAP
endif
## TODO: support DCAP test in SIM mode
ifeq ($(SGX_MODE), SIM)
EXTRA_C_FLAGS += -DOCCLUM_DISABLE_DCAP
else ifeq ($(SGX_MODE), SW)
EXTRA_C_FLAGS += -DOCCLUM_DISABLE_DCAP
endif
EXTRA_LINK_FLAGS :=
BIN_ARGS :=

@ -12,6 +12,10 @@
#include <unistd.h>
#include <sgx_report.h>
#include <sgx_quote.h>
#ifndef OCCLUM_DISABLE_DCAP
#include <sgx_ql_quote.h>
#include <sgx_qve_header.h>
#endif
#include "test.h"
// ============================================================================
@ -48,7 +52,7 @@ typedef struct {
uint8_t *as_buf;
sgx_quote_t *as_quote;
} quote; // output
} sgxioc_gen_quote_arg_t;
} sgxioc_gen_epid_quote_arg_t;
typedef struct {
const sgx_target_info_t *target_info; // input (optinal)
@ -56,12 +60,37 @@ typedef struct {
sgx_report_t *report; // output
} sgxioc_create_report_arg_t;
#define SGXIOC_IS_EDMM_SUPPORTED _IOR('s', 0, int)
#define SGXIOC_GET_EPID_GROUP_ID _IOR('s', 1, sgx_epid_group_id_t)
#define SGXIOC_GEN_QUOTE _IOWR('s', 2, sgxioc_gen_quote_arg_t)
#define SGXIOC_SELF_TARGET _IOR('s', 3, sgx_target_info_t)
#define SGXIOC_CREATE_REPORT _IOWR('s', 4, sgxioc_create_report_arg_t)
#define SGXIOC_VERIFY_REPORT _IOW('s', 5, sgx_report_t)
#ifndef OCCLUM_DISABLE_DCAP
typedef struct {
sgx_report_data_t *report_data; // input
uint32_t *quote_len; // input/output
uint8_t *quote_buf; // output
} sgxioc_gen_dcap_quote_arg_t;
typedef struct {
const uint8_t *quote_buf; // input
uint32_t quote_size; // input
uint32_t *collateral_expiration_status; // output
sgx_ql_qv_result_t *quote_verification_result; // output
uint32_t supplemental_data_size; // input
uint8_t *supplemental_data; // output
} sgxioc_ver_dcap_quote_arg_t;
#endif
#define SGXIOC_IS_EDMM_SUPPORTED _IOR('s', 0, int)
#define SGXIOC_GET_EPID_GROUP_ID _IOR('s', 1, sgx_epid_group_id_t)
#define SGXIOC_GEN_EPID_QUOTE _IOWR('s', 2, sgxioc_gen_epid_quote_arg_t)
#define SGXIOC_SELF_TARGET _IOR('s', 3, sgx_target_info_t)
#define SGXIOC_CREATE_REPORT _IOWR('s', 4, sgxioc_create_report_arg_t)
#define SGXIOC_VERIFY_REPORT _IOW('s', 5, sgx_report_t)
#define SGXIOC_DETECT_DCAP_DRIVER _IOR('s', 6, int)
#ifndef OCCLUM_DISABLE_DCAP
#define SGXIOC_GET_DCAP_QUOTE_SIZE _IOR('s', 7, uint32_t)
#define SGXIOC_GEN_DCAP_QUOTE _IOWR('s', 8, sgxioc_gen_dcap_quote_arg_t)
#define SGXIOC_GET_DCAP_SUPPLEMENTAL_SIZE _IOR('s', 9, uint32_t)
#define SGXIOC_VER_DCAP_QUOTE _IOWR('s', 10, sgxioc_ver_dcap_quote_arg_t)
#endif
// The max number of retries if ioctl returns EBUSY
#define IOCTL_MAX_RETRIES 20
@ -73,9 +102,8 @@ static int do_SGXIOC_IS_EDMM_SUPPORTED(int sgx_fd) {
if (ioctl(sgx_fd, SGXIOC_IS_EDMM_SUPPORTED, &is_edmm_supported) < 0) {
THROW_ERROR("failed to ioctl /dev/sgx");
}
if (is_edmm_supported != 0) {
THROW_ERROR("SGX EDMM supported are not expected to be enabled");
}
printf(" SGX EDMM support: %d\n", is_edmm_supported);
return 0;
}
@ -102,7 +130,7 @@ static int do_SGXIOC_GET_EPID_GROUP_ID(int sgx_fd) {
static int do_SGXIOC_GEN_QUOTE(int sgx_fd) {
uint8_t quote_buf[2048] = { 0 };
sgxioc_gen_quote_arg_t gen_quote_arg = {
sgxioc_gen_epid_quote_arg_t gen_quote_arg = {
.report_data = { { 0 } }, // input (empty is ok)
.quote_type = SGX_LINKABLE_SIGNATURE, // input
.spid = { { 0 } }, // input (empty is ok)
@ -114,7 +142,7 @@ static int do_SGXIOC_GEN_QUOTE(int sgx_fd) {
};
int nretries = 0;
while (nretries < IOCTL_MAX_RETRIES) {
int ret = ioctl(sgx_fd, SGXIOC_GEN_QUOTE, &gen_quote_arg);
int ret = ioctl(sgx_fd, SGXIOC_GEN_EPID_QUOTE, &gen_quote_arg);
if (ret == 0) {
break;
} else if (errno != EBUSY) {
@ -199,6 +227,124 @@ static int do_SGXIOC_CREATE_AND_VERIFY_REPORT(int sgx_fd) {
return 0;
}
#ifndef OCCLUM_DISABLE_DCAP
#define REPORT_BODY_OFFSET 48
static int generate_and_verify_dcap_quote(int sgx_fd) {
// get quote size
uint32_t quote_size = 0;
if (ioctl(sgx_fd, SGXIOC_GET_DCAP_QUOTE_SIZE, &quote_size) < 0) {
THROW_ERROR("failed to get quote size");
}
// get quote
uint8_t *quote_buffer = (uint8_t *)malloc(quote_size);
if (NULL == quote_buffer) {
THROW_ERROR("Couldn't allocate quote_buffer");
}
memset(quote_buffer, 0, quote_size);
sgx_report_data_t report_data = { 0 };
char *data = "ioctl DCAP report data example";
memcpy(report_data.d, data, strlen(data));
sgxioc_gen_dcap_quote_arg_t gen_quote_arg = {
.report_data = &report_data,
.quote_len = &quote_size,
.quote_buf = quote_buffer
};
if (ioctl(sgx_fd, SGXIOC_GEN_DCAP_QUOTE, &gen_quote_arg) < 0) {
THROW_ERROR("failed to get quote");
}
if (memcmp((void *) & ((sgx_report_body_t *)(quote_buffer +
REPORT_BODY_OFFSET))->report_data,
(void *)&report_data, sizeof(sgx_report_data_t)) != 0) {
THROW_ERROR("mismathced report data");
}
uint32_t collateral_expiration_status = 1;
sgx_ql_qv_result_t quote_verification_result = SGX_QL_QV_RESULT_UNSPECIFIED;
uint32_t supplemental_size = 0;
if (ioctl(sgx_fd, SGXIOC_GET_DCAP_SUPPLEMENTAL_SIZE, &supplemental_size) < 0) {
THROW_ERROR("failed to get supplemental data size");
}
uint8_t *supplemental_buffer = (uint8_t *)malloc(supplemental_size);
if (NULL == supplemental_buffer) {
THROW_ERROR("Couldn't allocate quote_buffer");
}
memset(supplemental_buffer, 0, supplemental_size);
sgxioc_ver_dcap_quote_arg_t ver_quote_arg = {
.quote_buf = quote_buffer,
.quote_size = quote_size,
.collateral_expiration_status = &collateral_expiration_status,
.quote_verification_result = &quote_verification_result,
.supplemental_data_size = supplemental_size,
.supplemental_data = supplemental_buffer
};
if (ioctl(sgx_fd, SGXIOC_VER_DCAP_QUOTE, &ver_quote_arg) < 0) {
THROW_ERROR("failed to verify quote");
}
switch (quote_verification_result) {
case SGX_QL_QV_RESULT_OK:
return 0;
case SGX_QL_QV_RESULT_CONFIG_NEEDED:
case SGX_QL_QV_RESULT_OUT_OF_DATE:
case SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED:
case SGX_QL_QV_RESULT_SW_HARDENING_NEEDED:
case SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED:
printf("WARN: App: Verification completed with Non-terminal result: %x\n",
quote_verification_result);
return 0;
case SGX_QL_QV_RESULT_INVALID_SIGNATURE:
case SGX_QL_QV_RESULT_REVOKED:
case SGX_QL_QV_RESULT_UNSPECIFIED:
default:
THROW_ERROR("\tError: App: Verification completed with Terminal result: %x\n",
quote_verification_result);
}
}
static int do_SGXIOC_GENERATE_AND_VERIFY_DCAP_QUOTE(int sgx_fd) {
int is_dcap_driver_installed = 0;
if (ioctl(sgx_fd, SGXIOC_DETECT_DCAP_DRIVER, &is_dcap_driver_installed) < 0) {
THROW_ERROR("failed to detect DCAP driver");
}
if (is_dcap_driver_installed == 0) {
printf("Warning: test_sgx_ioctl_SGXIOC_GENERATE_AND_VERIFY_DCAP_QUOTE is skipped\n");
return 0;
}
int nretries = 0;
while (nretries < IOCTL_MAX_RETRIES) {
int ret = generate_and_verify_dcap_quote(sgx_fd);
if (ret == 0) {
break;
} else if (errno != EBUSY) {
THROW_ERROR("failed to ioctl /dev/sgx");
}
printf("WARN: /dev/sgx is temporarily busy. Try again after 1 second.");
sleep(1);
nretries++;
}
if (nretries == IOCTL_MAX_RETRIES) {
THROW_ERROR("failed to ioctl /dev/sgx due to timeout");
}
return 0;
}
int test_sgx_ioctl_SGXIOC_GENERATE_AND_VERIFY_DCAP_QUOTE(void) {
return do_sgx_ioctl_test(do_SGXIOC_GENERATE_AND_VERIFY_DCAP_QUOTE);
}
#endif
int test_sgx_ioctl_SGXIOC_IS_EDMM_SUPPORTED(void) {
return do_sgx_ioctl_test(do_SGXIOC_IS_EDMM_SUPPORTED);
}
@ -207,7 +353,7 @@ int test_sgx_ioctl_SGXIOC_GET_EPID_GROUP_ID(void) {
return do_sgx_ioctl_test(do_SGXIOC_GET_EPID_GROUP_ID);
}
int test_sgx_ioctl_SGXIOC_GEN_QUOTE(void) {
int test_sgx_ioctl_SGXIOC_GEN_EPID_QUOTE(void) {
return do_sgx_ioctl_test(do_SGXIOC_GEN_QUOTE);
}
@ -319,9 +465,12 @@ static test_case_t test_cases[] = {
TEST_CASE(test_tty_ioctl_TIOCGWINSZ),
TEST_CASE(test_sgx_ioctl_SGXIOC_IS_EDMM_SUPPORTED),
TEST_CASE(test_sgx_ioctl_SGXIOC_GET_EPID_GROUP_ID),
TEST_CASE(test_sgx_ioctl_SGXIOC_GEN_QUOTE),
TEST_CASE(test_sgx_ioctl_SGXIOC_GEN_EPID_QUOTE),
TEST_CASE(test_sgx_ioctl_SGXIOC_SELF_TARGET),
TEST_CASE(test_sgx_ioctl_SGXIOC_CREATE_AND_VERIFY_REPORT),
#ifndef OCCLUM_DISABLE_DCAP
TEST_CASE(test_sgx_ioctl_SGXIOC_GENERATE_AND_VERIFY_DCAP_QUOTE),
#endif
TEST_CASE(test_ioctl_SIOCGIFCONF),
TEST_CASE(test_ioctl_FIONBIO),
};

@ -55,7 +55,7 @@ RUN wget http://www.etallen.com/cpuid/cpuid-20200211.x86_64.tar.gz && \
# Install SGX SDK
WORKDIR /tmp
RUN git clone -b sgx_2.11_for_occlum https://github.com/occlum/linux-sgx && \
cd linux-sgx && make preparation && \
cd linux-sgx && \
./compile_and_install.sh no_mitigation USE_OPT_LIBS=2 && \
echo 'source /opt/intel/sgxsdk/environment' >> /root/.bashrc && \
rm -rf /tmp/linux-sgx

@ -67,7 +67,7 @@ RUN wget http://www.etallen.com/cpuid/cpuid-20200211.x86_64.tar.gz && \
WORKDIR /tmp
RUN git clone -b sgx_2.11_for_occlum https://github.com/occlum/linux-sgx && \
mkdir /etc/init && \
cd linux-sgx && make preparation && \
cd linux-sgx && \
./compile_and_install.sh no_mitigation USE_OPT_LIBS=2 && \
echo 'source /opt/intel/sgxsdk/environment' >> /root/.bashrc && \
rm -rf /tmp/linux-sgx