Add dcap library into Occlum prebuilt toolchains

This commit is contained in:
Zheng, Qi 2022-02-08 14:18:49 +08:00 committed by Zongmin.Gu
parent 555ab9c598
commit 637dc73b1b
8 changed files with 503 additions and 0 deletions

28
tools/toolchains/dcap_lib/Cargo.lock generated Normal file

@ -0,0 +1,28 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "libc"
version = "0.2.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9"
[[package]]
name = "occlum_dcap"
version = "0.1.0"
dependencies = [
"cfg-if",
"libc",
"sgx_types",
]
[[package]]
name = "sgx_types"
version = "1.1.4"

@ -0,0 +1,15 @@
[package]
name = "occlum_dcap"
version = "0.1.0"
authors = ["Zheng, Qi <huaiqing.zq@antgroup.com>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
sgx_types = { path = "../../../deps/rust-sgx-sdk/sgx_types" }
libc = "0.2"
cfg-if = "1.0.0"
[lib]
crate-type = ["cdylib", "rlib", "staticlib"]

@ -0,0 +1,24 @@
#!/bin/bash
set -e
INSTALL_DIR=/opt/occlum/toolchains/dcap_lib
echo "*** Build and install musl-libc dcap ***"
occlum-cargo clean
occlum-cargo build --all-targets --release
mkdir -p ${INSTALL_DIR}/musl
cp target/x86_64-unknown-linux-musl/release/libocclum_dcap.a ${INSTALL_DIR}/musl/
cp target/x86_64-unknown-linux-musl/release/libocclum_dcap.so ${INSTALL_DIR}/musl/
cp target/x86_64-unknown-linux-musl/release/examples/dcap_test ${INSTALL_DIR}/musl/
echo "*** Build and install glibc dcap ***"
cargo clean
cargo build --all-targets --release
mkdir -p ${INSTALL_DIR}/glibc
cp target/release/libocclum_dcap.a ${INSTALL_DIR}/glibc/
cp target/release/libocclum_dcap.so ${INSTALL_DIR}/glibc/
cp target/release/examples/dcap_test ${INSTALL_DIR}/glibc/
cp -r inc ${INSTALL_DIR}/

@ -0,0 +1,169 @@
extern crate occlum_dcap;
use std::str;
use std::io::Result;
use std::convert::TryFrom;
use occlum_dcap::*;
struct DcapDemo {
dcap_quote: DcapQuote,
quote_size: u32,
quote_buf: Vec<u8>,
req_data: sgx_report_data_t,
supplemental_size: u32,
suppl_buf: Vec<u8>
}
impl DcapDemo {
pub fn new(report_data: &str) -> Self {
let mut dcap = DcapQuote::new();
let quote_size = dcap.get_quote_size();
let supplemental_size = dcap.get_supplemental_data_size();
let quote_buf: Vec<u8> = vec![0; quote_size as usize];
let suppl_buf: Vec<u8> = vec![0; supplemental_size as usize];
let mut req_data = sgx_report_data_t::default();
//fill in the report data array
for (pos, val) in report_data.as_bytes().iter().enumerate() {
req_data.d[pos] = *val;
}
Self {
dcap_quote: dcap,
quote_size: quote_size,
quote_buf: quote_buf,
req_data: req_data,
supplemental_size: supplemental_size,
suppl_buf: suppl_buf
}
}
fn dcap_quote_gen(&mut self) -> Result<i32> {
self.dcap_quote.generate_quote(self.quote_buf.as_mut_ptr(), &mut self.req_data).unwrap();
println!("DCAP generate quote successfully");
Ok( 0 )
}
// Quote has type `sgx_quote3_t` and is structured as
// pub struct sgx_quote3_t {
// pub header: sgx_quote_header_t,
// pub report_body: sgx_report_body_t,
// pub signature_data_len: uint32_t,
// pub signature_data: [uint8_t; 0],
// }
fn dcap_quote_get_report_body(&mut self) -> Result<*const sgx_report_body_t> {
let report_body_offset = std::mem::size_of::<sgx_quote_header_t>();
let report_body: *const sgx_report_body_t
= (self.quote_buf[report_body_offset..]).as_ptr() as _;
Ok(report_body)
}
fn dcap_quote_get_report_data(&mut self) -> Result<*const sgx_report_data_t> {
let report_body_ptr = self.dcap_quote_get_report_body().unwrap();
let report_data_ptr = unsafe { &(*report_body_ptr).report_data };
Ok(report_data_ptr)
}
fn dcap_quote_ver(&mut self) -> Result<sgx_ql_qv_result_t> {
let mut quote_verification_result = sgx_ql_qv_result_t::SGX_QL_QV_RESULT_UNSPECIFIED;
let mut status = 1;
let mut verify_arg = IoctlVerDCAPQuoteArg {
quote_buf: self.quote_buf.as_mut_ptr(),
quote_size: self.quote_size,
collateral_expiration_status: &mut status,
quote_verification_result: &mut quote_verification_result,
supplemental_data_size: self.supplemental_size,
supplemental_data: self.suppl_buf.as_mut_ptr(),
};
self.dcap_quote.verify_quote(&mut verify_arg).unwrap();
println!("DCAP verify quote successfully");
Ok( quote_verification_result )
}
fn dcap_dump_quote_info(&mut self) {
let report_body_ptr = self.dcap_quote_get_report_body().unwrap();
// Dump ISV FAMILY ID
let family_id = unsafe { (*report_body_ptr).isv_family_id };
let (fam_id_l, fam_id_h) = family_id.split_at(8);
let fam_id_l = <&[u8; 8]>::try_from(fam_id_l).unwrap();
let fam_id_l = u64::from_le_bytes(*fam_id_l);
let fam_id_h = <&[u8; 8]>::try_from(fam_id_h).unwrap();
let fam_id_h = u64::from_le_bytes(*fam_id_h);
println!("\nSGX ISV Family ID:");
println!("\t Low 8 bytes: 0x{:016x?}\t", fam_id_l);
println!("\t high 8 bytes: 0x{:016x?}\t", fam_id_h);
// Dump ISV EXT Product ID
let prod_id = unsafe { (*report_body_ptr).isv_ext_prod_id };
let (prod_id_l, prod_id_h) = prod_id.split_at(8);
let prod_id_l = <&[u8; 8]>::try_from(prod_id_l).unwrap();
let prod_id_l = u64::from_le_bytes(*prod_id_l);
let prod_id_h = <&[u8; 8]>::try_from(prod_id_h).unwrap();
let prod_id_h = u64::from_le_bytes(*prod_id_h);
println!("\nSGX ISV EXT Product ID:");
println!("\t Low 8 bytes: 0x{:016x?}\t", prod_id_l);
println!("\t high 8 bytes: 0x{:016x?}\t", prod_id_h);
// Dump CONFIG ID
let conf_id = unsafe { (*report_body_ptr).config_id };
println!("\nSGX CONFIG ID:");
println!("\t{:02x?}", &conf_id[..16]);
println!("\t{:02x?}", &conf_id[16..32]);
println!("\t{:02x?}", &conf_id[32..48]);
println!("\t{:02x?}", &conf_id[48..]);
// Dump CONFIG SVN
let conf_svn = unsafe { (*report_body_ptr).config_svn };
println!("\nSGX CONFIG SVN:\t {:04x?}", conf_svn);
}
}
impl Drop for DcapDemo {
fn drop(&mut self) {
self.dcap_quote.close();
}
}
fn main() {
let report_str = "Dcap demo sample";
let mut dcap_demo = DcapDemo::new(report_str);
println!("Generate quote with report data : {}", report_str);
dcap_demo.dcap_quote_gen().unwrap();
// compare the report data in quote buffer
let report_data_ptr = dcap_demo.dcap_quote_get_report_data().unwrap();
let string = str::from_utf8( unsafe { &(*report_data_ptr).d } ).unwrap();
if report_str == &string[..report_str.len()] {
println!("Report data from Quote: '{}' exactly matches.", string);
} else {
println!("Report data from Quote: '{}' doesn't match !!!", string);
}
dcap_demo.dcap_dump_quote_info();
let result = dcap_demo.dcap_quote_ver().unwrap();
match result {
sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OK => {
println!("Succeed to verify the quote!");
},
sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_NEEDED |
sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE |
sgx_ql_qv_result_t::SGX_QL_QV_RESULT_OUT_OF_DATE_CONFIG_NEEDED |
sgx_ql_qv_result_t::SGX_QL_QV_RESULT_SW_HARDENING_NEEDED |
sgx_ql_qv_result_t::SGX_QL_QV_RESULT_CONFIG_AND_SW_HARDENING_NEEDED => {
println!("WARN: App: Verification completed with Non-terminal result: {:?}", result);
},
_ => println!("Error: App: Verification completed with Terminal result: {:?}", result),
}
}

@ -0,0 +1,38 @@
#ifndef _OCCLUM_DCAP_H
#define _OCCLUM_DCAP_H
#include <stdint.h>
#include <stdlib.h>
#include "sgx_report.h"
#include "sgx_qve_header.h"
#ifdef __cplusplus
extern "C" {
#endif
void *dcap_quote_open(void);
uint32_t dcap_get_quote_size(void *handle);
int32_t dcap_generate_quote(void *handle, uint8_t *quote_buf, const sgx_report_data_t *report_data);
uint32_t dcap_get_supplemental_data_size(void *handle);
int32_t dcap_verify_quote(void *handle,
const uint8_t *quote_buf,
uint32_t quote_size,
uint32_t *collateral_expiration_status,
sgx_ql_qv_result_t *quote_verification_result,
uint32_t supplemental_data_size,
uint8_t *supplemental_data);
void dcap_quote_close(void *handle);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,105 @@
mod occlum_dcap;
mod prelude;
pub use crate::prelude::*;
pub use crate::occlum_dcap::*;
#[no_mangle]
pub extern "C" fn dcap_quote_open() -> *mut c_void {
Box::into_raw(Box::new(DcapQuote::new())) as *mut c_void
}
#[no_mangle]
pub extern "C" fn dcap_get_quote_size(handle: *mut c_void) -> u32 {
if handle.is_null() {
return 0
}
let dcap = unsafe {
&mut *(handle as *mut DcapQuote)
};
dcap.get_quote_size()
}
#[no_mangle]
pub extern "C" fn dcap_generate_quote(
handle: *mut c_void,
quote_buf: *mut u8,
report_data: *const sgx_report_data_t) -> i32
{
if handle.is_null() {
return -1
}
let dcap = unsafe {
&mut *(handle as *mut DcapQuote)
};
dcap.generate_quote(quote_buf, report_data).unwrap();
0
}
#[no_mangle]
pub extern "C" fn dcap_get_supplemental_data_size(handle: *mut c_void) -> u32 {
if handle.is_null() {
return 0
}
let dcap = unsafe {
&mut *(handle as *mut DcapQuote)
};
dcap.get_supplemental_data_size()
}
#[no_mangle]
pub extern "C" fn dcap_verify_quote(
handle: *mut c_void,
quote_buf: *const u8,
quote_size: u32,
collateral_expiration_status: *mut u32,
quote_verification_result: *mut sgx_ql_qv_result_t,
supplemental_data_size: u32,
supplemental_data: *mut u8) -> i32
{
if handle.is_null() {
return -1
}
let dcap = unsafe {
&mut *(handle as *mut DcapQuote)
};
let mut verify_arg = IoctlVerDCAPQuoteArg {
quote_buf: quote_buf,
quote_size: quote_size,
collateral_expiration_status: collateral_expiration_status,
quote_verification_result: quote_verification_result,
supplemental_data_size: supplemental_data_size,
supplemental_data: supplemental_data,
};
dcap.verify_quote(&mut verify_arg).unwrap();
0
}
#[no_mangle]
pub extern "C" fn dcap_quote_close(handle: *mut c_void) {
if handle.is_null() {
return
}
let dcap = unsafe {
&mut *(handle as *mut DcapQuote)
};
dcap.close();
unsafe {
Box::from_raw(handle);
}
}

@ -0,0 +1,117 @@
use std::ffi::CString;
use crate::prelude::*;
const SGXIOC_GET_DCAP_QUOTE_SIZE: u64 = 0x80047307;
const SGXIOC_GEN_DCAP_QUOTE: u64 = 0xc0187308;
const SGXIOC_GET_DCAP_SUPPLEMENTAL_SIZE: u64 = 0x80047309;
const SGXIOC_VER_DCAP_QUOTE: u64 = 0xc030730a;
cfg_if::cfg_if! {
if #[cfg(target_env = "musl")] {
const IOCTL_GET_DCAP_QUOTE_SIZE: i32 = SGXIOC_GET_DCAP_QUOTE_SIZE as i32;
const IOCTL_GEN_DCAP_QUOTE: i32 = SGXIOC_GEN_DCAP_QUOTE as i32;
const IOCTL_GET_DCAP_SUPPLEMENTAL_SIZE: i32 = SGXIOC_GET_DCAP_SUPPLEMENTAL_SIZE as i32;
const IOCTL_VER_DCAP_QUOTE: i32 = SGXIOC_VER_DCAP_QUOTE as i32;
} else {
const IOCTL_GET_DCAP_QUOTE_SIZE: u64 = SGXIOC_GET_DCAP_QUOTE_SIZE;
const IOCTL_GEN_DCAP_QUOTE: u64 = SGXIOC_GEN_DCAP_QUOTE;
const IOCTL_GET_DCAP_SUPPLEMENTAL_SIZE: u64 = SGXIOC_GET_DCAP_SUPPLEMENTAL_SIZE;
const IOCTL_VER_DCAP_QUOTE: u64 = SGXIOC_VER_DCAP_QUOTE;
}
}
// Copy from occlum/src/libos/src/fs/dev_fs/dev_sgx/mod.rs
//#[allow(dead_code)]
#[repr(C)]
pub struct IoctlGenDCAPQuoteArg {
pub report_data: *const sgx_report_data_t, // Input
pub quote_size: *mut u32, // Input/output
pub quote_buf: *mut u8, // Output
}
// Copy from occlum/src/libos/src/fs/dev_fs/dev_sgx/mod.rs
//#[allow(dead_code)]
#[repr(C)]
pub struct IoctlVerDCAPQuoteArg {
pub quote_buf: *const u8, // Input
pub quote_size: u32, // Input
pub collateral_expiration_status: *mut u32, // Output
pub quote_verification_result: *mut sgx_ql_qv_result_t, // Output
pub supplemental_data_size: u32, // Input (optional)
pub supplemental_data: *mut u8, // Output (optional)
}
pub struct DcapQuote {
fd: c_int,
quote_size: u32,
supplemental_size: u32,
}
impl DcapQuote {
pub fn new() -> Self {
let path = CString::new("/dev/sgx").unwrap();
let fd = unsafe { libc::open(path.as_ptr(), O_RDONLY) };
if fd > 0 {
Self {
fd: fd,
quote_size: 0,
supplemental_size: 0,
}
} else {
panic!("Open /dev/sgx failed")
}
}
pub fn get_quote_size(&mut self) -> u32 {
let size: u32 = 0;
let ret = unsafe { libc::ioctl(self.fd, IOCTL_GET_DCAP_QUOTE_SIZE, &size) };
if ret < 0 {
panic!("IOCTRL IOCTL_GET_DCAP_QUOTE_SIZE failed");
} else {
self.quote_size = size;
size
}
}
pub fn generate_quote(&mut self, quote_buf: *mut u8, report_data: *const sgx_report_data_t) -> Result<i32, &'static str> {
let quote_arg: IoctlGenDCAPQuoteArg = IoctlGenDCAPQuoteArg {
report_data: report_data,
quote_size: &mut self.quote_size,
quote_buf: quote_buf,
};
let ret = unsafe { libc::ioctl(self.fd, IOCTL_GEN_DCAP_QUOTE, &quote_arg) };
if ret < 0 {
Err("IOCTRL IOCTL_GEN_DCAP_QUOTE failed")
} else {
Ok( 0 )
}
}
pub fn get_supplemental_data_size(&mut self) -> u32 {
let size: u32 = 0;
let ret = unsafe { libc::ioctl(self.fd, IOCTL_GET_DCAP_SUPPLEMENTAL_SIZE, &size) };
if ret < 0 {
panic!("IOCTRL IOCTL_GET_DCAP_SUPPLEMENTAL_SIZE failed");
} else {
self.supplemental_size = size;
size
}
}
pub fn verify_quote(&mut self, verify_arg: *mut IoctlVerDCAPQuoteArg) -> Result<i32, &'static str> {
let ret = unsafe { libc::ioctl(self.fd, IOCTL_VER_DCAP_QUOTE, verify_arg) };
if ret < 0 {
println!("ret = {}", ret);
Err("IOCTRL IOCTL_VER_DCAP_QUOTE failed")
} else {
Ok( 0 )
}
}
pub fn close(&mut self) {
unsafe { libc::close(self.fd) };
}
}

@ -0,0 +1,7 @@
pub use std::boxed::Box;
pub use libc::{open, ioctl, close, c_void, c_int, O_RDONLY};
// Defined in "occlum/deps/rust-sgx-sdk/sgx_types"
pub use sgx_types::{
sgx_quote_header_t, sgx_report_data_t, sgx_ql_qv_result_t, sgx_report_body_t, sgx_quote3_t
};