Add ioctls for SGX local attestation

This commit is contained in:
Tate, Hongliang Tian 2020-02-19 14:48:12 +00:00
parent 76b90efa8f
commit a6e55881b9
6 changed files with 166 additions and 12 deletions

@ -56,7 +56,7 @@ LIBOS_CORE_RS_A := $(BUILD_DIR)/lib/libocclum_libos_core_rs.a
LIBCOMPILER_RT_PATCH_A := $(BUILD_DIR)/lib/libcompiler-rt-patch.a LIBCOMPILER_RT_PATCH_A := $(BUILD_DIR)/lib/libcompiler-rt-patch.a
# All source code # All source code
RUST_SRCS := $(wildcard src/*.rs src/*/*.rs src/*/*/*.rs src/*/*/*/*.rs) RUST_SRCS := $(wildcard src/*.rs src/*/*.rs src/*/*/*.rs src/*/*/*/*.rs src/*/*/*/*/*.rs)
RUST_TARGET_DIR := $(BUILD_DIR)/src/libos/cargo-target RUST_TARGET_DIR := $(BUILD_DIR)/src/libos/cargo-target
RUST_OUT_DIR := $(BUILD_DIR)/lib RUST_OUT_DIR := $(BUILD_DIR)/lib
EDL_C_SRCS := $(addprefix $(BUILD_DIR)/src/libos/,src/Enclave_t.c src/Enclave_t.h) EDL_C_SRCS := $(addprefix $(BUILD_DIR)/src/libos/,src/Enclave_t.c src/Enclave_t.h)

@ -7,11 +7,13 @@ use sgx_types::*;
mod sgx_attestation_agent; mod sgx_attestation_agent;
mod sgx_quote; mod sgx_quote;
mod sgx_report;
pub use sgx_types::{ pub use sgx_types::{
sgx_epid_group_id_t, sgx_quote_nonce_t, sgx_quote_sign_type_t, sgx_quote_t, sgx_report_data_t, sgx_create_report, sgx_epid_group_id_t, sgx_quote_nonce_t, sgx_quote_sign_type_t, sgx_quote_t,
sgx_spid_t, sgx_target_info_t, 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_attestation_agent::SgxAttestationAgent;
pub use self::sgx_quote::SgxQuote; pub use self::sgx_quote::SgxQuote;
pub use self::sgx_report::{create_report, get_self_target, verify_report};

@ -0,0 +1,41 @@
use super::*;
use std::ptr;
pub fn get_self_target() -> Result<sgx_target_info_t> {
let mut self_target = sgx_target_info_t::default();
let sgx_status = unsafe { sgx_self_target(&mut self_target) };
match sgx_status {
sgx_status_t::SGX_SUCCESS => Ok(self_target),
_ => return_errno!(EINVAL, "unexpected SGX error"),
}
}
pub fn create_report(
target_info: Option<&sgx_target_info_t>,
report_data: Option<&sgx_report_data_t>,
) -> Result<sgx_report_t> {
let mut report = sgx_report_t::default();
let sgx_status = unsafe {
sgx_create_report(
target_info.map_or(ptr::null(), |t| t),
report_data.map_or(ptr::null(), |t| t),
&mut report,
)
};
match sgx_status {
sgx_status_t::SGX_SUCCESS => Ok(report),
sgx_status_t::SGX_ERROR_INVALID_PARAMETER => return_errno!(EINVAL, "invalid paramters"),
_ => return_errno!(EINVAL, "unexpected SGX error"),
}
}
pub fn verify_report(report: &sgx_report_t) -> Result<()> {
let sgx_status = unsafe { sgx_verify_report(report) };
match sgx_status {
sgx_status_t::SGX_SUCCESS => Ok(()),
sgx_status_t::SGX_ERROR_MAC_MISMATCH => return_errno!(EINVAL, "report MAC mismatch"),
sgx_status_t::SGX_ERROR_INVALID_PARAMETER => return_errno!(EINVAL, "invalid report"),
_ => return_errno!(EINVAL, "unexpected SGX error"),
}
}

@ -17,6 +17,21 @@ pub const SGX_CMD_NUM_GEN_QUOTE: u32 = StructuredIoctlNum::new::<IoctlGenQuoteAr
StructuredIoctlArgType::InputOutput, StructuredIoctlArgType::InputOutput,
) )
.as_u32(); .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,
SGX_MAGIC_CHAR,
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();
/// A magical number that distinguishes SGX ioctls for other ioctls /// A magical number that distinguishes SGX ioctls for other ioctls
const SGX_MAGIC_CHAR: u8 = 's' as u8; const SGX_MAGIC_CHAR: u8 = 's' as u8;

@ -60,8 +60,37 @@ impl File for DevSgx {
)?; )?;
quote.dump_to_buf(quote_output_buf)?; quote.dump_to_buf(quote_output_buf)?;
} }
SGX_CMD_NUM_SELF_TARGET => {
let arg = nonbuiltin_cmd.arg_mut::<sgx_target_info_t>()?;
*arg = get_self_target()?;
}
SGX_CMD_NUM_CREATE_REPORT => {
// Prepare the arguments
let arg = nonbuiltin_cmd.arg_mut::<IoctlCreateReportArg>()?;
let target_info = if !arg.target_info.is_null() {
Some(unsafe { &*arg.target_info })
} else {
None
};
let report_data = if !arg.report_data.is_null() {
Some(unsafe { &*arg.report_data })
} else {
None
};
let report = {
if arg.report.is_null() {
return_errno!(EINVAL, "output pointer for report must not be null");
}
unsafe { &mut *arg.report }
};
*report = create_report(target_info, report_data)?;
}
SGX_CMD_NUM_VERIFY_REPORT => {
let arg = nonbuiltin_cmd.arg::<sgx_report_t>()?;
verify_report(arg)?;
}
_ => { _ => {
return_errno!(EINVAL, "unknown ioctl cmd for /dev/sgx"); return_errno!(ENOSYS, "unknown ioctl cmd for /dev/sgx");
} }
} }
Ok(()) Ok(())
@ -90,3 +119,10 @@ struct IoctlGenQuoteArg {
quote_buf_len: u32, // Input quote_buf_len: u32, // Input
quote_buf: *mut u8, // Output quote_buf: *mut u8, // Output
} }
#[repr(C)]
struct IoctlCreateReportArg {
target_info: *const sgx_target_info_t, // Input (optional)
report_data: *const sgx_report_data_t, // Input (optional)
report: *mut sgx_report_t, // Output
}

@ -7,6 +7,7 @@
#include <string.h> #include <string.h>
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#include <sgx_report.h>
#include <sgx_quote.h> #include <sgx_quote.h>
#include "test.h" #include "test.h"
@ -40,18 +41,27 @@ typedef struct {
} quote; // output } quote; // output
} sgxioc_gen_quote_arg_t; } sgxioc_gen_quote_arg_t;
#define SGXIOC_IS_EDDM_SUPPORTED _IOR('s', 0, int) typedef struct {
const sgx_target_info_t* target_info; // input (optinal)
const sgx_report_data_t* report_data; // input (optional)
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_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_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)
// The max number of retries if ioctl returns EBUSY // The max number of retries if ioctl returns EBUSY
#define IOCTL_MAX_RETRIES 20 #define IOCTL_MAX_RETRIES 20
typedef int(*sgx_ioctl_test_body_t)(int sgx_fd); typedef int(*sgx_ioctl_test_body_t)(int sgx_fd);
static int do_SGXIOC_IS_EDDM_SUPPORTED(int sgx_fd) { static int do_SGXIOC_IS_EDMM_SUPPORTED(int sgx_fd) {
int is_edmm_supported = 0; int is_edmm_supported = 0;
if (ioctl(sgx_fd, SGXIOC_IS_EDDM_SUPPORTED, &is_edmm_supported) < 0) { if (ioctl(sgx_fd, SGXIOC_IS_EDMM_SUPPORTED, &is_edmm_supported) < 0) {
THROW_ERROR("failed to ioctl /dev/sgx"); THROW_ERROR("failed to ioctl /dev/sgx");
} }
if (is_edmm_supported != 0) { if (is_edmm_supported != 0) {
@ -60,7 +70,6 @@ static int do_SGXIOC_IS_EDDM_SUPPORTED(int sgx_fd) {
return 0; return 0;
} }
static int do_SGXIOC_GET_EPID_GROUP_ID(int sgx_fd) { static int do_SGXIOC_GET_EPID_GROUP_ID(int sgx_fd) {
int nretries = 0; int nretries = 0;
while (nretries < IOCTL_MAX_RETRIES) { while (nretries < IOCTL_MAX_RETRIES) {
@ -141,8 +150,49 @@ static int do_sgx_ioctl_test(sgx_ioctl_test_body_t test_body) {
return ret; return ret;
} }
int test_sgx_ioctl_SGXIOC_IS_EDDM_SUPPORTED(void) { static int do_SGXIOC_SELF_TARGET(int sgx_fd) {
return do_sgx_ioctl_test(do_SGXIOC_IS_EDDM_SUPPORTED); sgx_target_info_t target_info;
if (ioctl(sgx_fd, SGXIOC_SELF_TARGET, &target_info) < 0) {
THROW_ERROR("failed to ioctl /dev/sgx");
}
return 0;
}
static int do_SGXIOC_CREATE_AND_VERIFY_REPORT(int sgx_fd) {
sgx_target_info_t target_info;
if (ioctl(sgx_fd, SGXIOC_SELF_TARGET, &target_info) < 0) {
THROW_ERROR("failed to ioctl /dev/sgx");
}
sgx_report_t report_data;
sgx_report_t report;
sgxioc_create_report_arg_t args[] = {
{
.target_info = (const sgx_target_info_t*) &target_info,
.report_data = NULL,
.report = &report
},
{
.target_info = (const sgx_target_info_t*) &target_info,
.report_data = (const sgx_report_data_t*) &report_data,
.report = &report
}
};
for (int arg_i = 0; arg_i < ARRAY_SIZE(args); arg_i++) {
memset(&report, 0, sizeof(report));
sgxioc_create_report_arg_t* arg = &args[arg_i];
if (ioctl(sgx_fd, SGXIOC_CREATE_REPORT, arg) < 0) {
THROW_ERROR("failed to create report");
}
if (ioctl(sgx_fd, SGXIOC_VERIFY_REPORT, &report) < 0) {
THROW_ERROR("failed to verify report");
}
}
return 0;
}
int test_sgx_ioctl_SGXIOC_IS_EDMM_SUPPORTED(void) {
return do_sgx_ioctl_test(do_SGXIOC_IS_EDMM_SUPPORTED);
} }
int test_sgx_ioctl_SGXIOC_GET_EPID_GROUP_ID(void) { int test_sgx_ioctl_SGXIOC_GET_EPID_GROUP_ID(void) {
@ -153,15 +203,25 @@ int test_sgx_ioctl_SGXIOC_GEN_QUOTE(void) {
return do_sgx_ioctl_test(do_SGXIOC_GEN_QUOTE); return do_sgx_ioctl_test(do_SGXIOC_GEN_QUOTE);
} }
int test_sgx_ioctl_SGXIOC_SELF_TARGET(void) {
return do_sgx_ioctl_test(do_SGXIOC_SELF_TARGET);
}
int test_sgx_ioctl_SGXIOC_CREATE_AND_VERIFY_REPORT(void) {
return do_sgx_ioctl_test(do_SGXIOC_CREATE_AND_VERIFY_REPORT);
}
// ============================================================================ // ============================================================================
// Test suite // Test suite
// ============================================================================ // ============================================================================
static test_case_t test_cases[] = { static test_case_t test_cases[] = {
TEST_CASE(test_tty_ioctl_TIOCGWINSZ), TEST_CASE(test_tty_ioctl_TIOCGWINSZ),
TEST_CASE(test_sgx_ioctl_SGXIOC_IS_EDDM_SUPPORTED), 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_GET_EPID_GROUP_ID),
TEST_CASE(test_sgx_ioctl_SGXIOC_GEN_QUOTE) TEST_CASE(test_sgx_ioctl_SGXIOC_GEN_QUOTE),
TEST_CASE(test_sgx_ioctl_SGXIOC_SELF_TARGET),
TEST_CASE(test_sgx_ioctl_SGXIOC_CREATE_AND_VERIFY_REPORT)
}; };
int main() { int main() {