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:
parent
dc7599c87c
commit
f1e5f574ca
14
Makefile
14
Makefile
@ -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("e);
|
||||
}
|
||||
#[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)
|
||||
}
|
||||
|
7
src/libos/src/util/sgx/dcap/mod.rs
Normal file
7
src/libos/src/util/sgx/dcap/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
use super::*;
|
||||
|
||||
mod quote_generator;
|
||||
mod quote_verifier;
|
||||
|
||||
pub use quote_generator::QuoteGenerator;
|
||||
pub use quote_verifier::QuoteVerifier;
|
76
src/libos/src/util/sgx/dcap/quote_generator.rs
Normal file
76
src/libos/src/util/sgx/dcap/quote_generator.rs
Normal file
@ -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;
|
||||
}
|
116
src/libos/src/util/sgx/dcap/quote_verifier.rs
Normal file
116
src/libos/src/util/sgx/dcap/quote_verifier.rs
Normal file
@ -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;
|
||||
}
|
20
src/libos/src/util/sgx/sgx_attestation_agent.rs → src/libos/src/util/sgx/epid/attestation_agent.rs
20
src/libos/src/util/sgx/sgx_attestation_agent.rs → src/libos/src/util/sgx/epid/attestation_agent.rs
@ -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("e_buf, &nonce, &qe_report)?;
|
||||
let quote = Quote::new("e_buf, &nonce, &qe_report)?;
|
||||
|
||||
Ok(quote)
|
||||
}
|
7
src/libos/src/util/sgx/epid/mod.rs
Normal file
7
src/libos/src/util/sgx/epid/mod.rs
Normal file
@ -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("e_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, "e_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 = "e_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 = "e_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
|
||||
|
Loading…
Reference in New Issue
Block a user