This commit is contained in:
Noor 2024-10-21 10:59:42 +00:00 committed by Valentyn Faychuk
parent 966819d0e6
commit 2cd8fc0e56
23 changed files with 517 additions and 406 deletions

@ -2,11 +2,11 @@
# All rights reserved. # All rights reserved.
[package] [package]
name = "occlum-ratls" name = "occlum-sgx"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
authors = ["Valentyn Faychuk <faitchouk.valentyn@gmail.com>", "Ivan Chirkin <chirkin.ivan@gmail.com>"] authors = ["Valentyn Faychuk <faitchouk.valentyn@gmail.com>"]
description = "Remote attestation for Intel SGX" description = "Intel SGX Occlum interface"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
keywords = ["occlum", "rustls", "ratls"] keywords = ["occlum", "rustls", "ratls"]
# Inspired by https://github.com/aggregion/occlum-ratls # Inspired by https://github.com/aggregion/occlum-ratls
@ -14,7 +14,6 @@ keywords = ["occlum", "rustls", "ratls"]
[dependencies] [dependencies]
rustls = "0.23" rustls = "0.23"
x509-parser = "0.16" x509-parser = "0.16"
#occlum-sgx = "0.1" # get/verify quote
ring = "0.17" # hash256 ring = "0.17" # hash256
rcgen = "0.13" rcgen = "0.13"
log = "0.4" log = "0.4"
@ -28,10 +27,6 @@ hyper-rustls = { version = "0.27", features = ["http2"] }
prost = "0.13" prost = "0.13"
base64 = "0.22" base64 = "0.22"
lazy_static = "1.5" lazy_static = "1.5"
#sgx_tse = { version = "1.1", features = ["capi"] }
#sgx_tse = "1.1"
#sgx_types = "1.1"
#sgx_tseal = "1.1"
[dependencies.tonic] [dependencies.tonic]
version = "0.12" version = "0.12"
@ -57,6 +52,19 @@ default-features = false
features = ["__rustls"] features = ["__rustls"]
optional = true optional = true
[dependencies.pbkdf2]
version = "0.12.2"
optional = true
features = ["hmac"]
[dependencies.sha2]
version = "0.10.8"
optional = true
[dependencies.aes-gcm]
version = "0.10.3"
optional = true
[dev-dependencies.env_logger] [dev-dependencies.env_logger]
version = "0.11" version = "0.11"
@ -76,26 +84,29 @@ tonic-build = "0.12"
default = [] default = []
# TOOD: rename to testing and reverse uses in the code # TOOD: rename to testing and reverse uses in the code
occlum = [] occlum = []
sealing = ["occlum", "dep:pbkdf2", "dep:sha2", "dep:aes-gcm"]
reqwest = ["dep:reqwest"] reqwest = ["dep:reqwest"]
actix-web = ["dep:actix-web", "actix-service", "actix-http"] actix-web = ["dep:actix-web", "actix-service", "actix-http"]
tonic = ["dep:tonic"] tonic = ["dep:tonic"]
full = ["occlum", "sealing", "reqwest", "actix-web", "tonic"]
[[example]] [[example]]
name = "mratls_https_server" name = "mratls_https_server"
required-features = ["actix-web"] required-features = ["actix-web", "occlum"]
[[example]] [[example]]
name = "mratls_https_client" name = "mratls_https_client"
required-features = ["reqwest"] required-features = ["reqwest", "occlum"]
[[example]] [[example]]
name = "mratls_grpcs_server" name = "mratls_grpcs_server"
required-features = ["tonic"] required-features = ["tonic", "occlum"]
[[example]] [[example]]
name = "mratls_grpcs_client" name = "mratls_grpcs_client"
required-features = ["tonic"] required-features = ["tonic", "occlum"]
[[example]] [[example]]
name = "sealing" name = "sealing"
required-features = ["sealing"]

@ -1,4 +1,4 @@
# Occlum SGX Remote Attestation integrated in TLS connection # Occlum SGX Remote Attestation integrated in TLS connection and many more
The MRSIGNER of the `example/signing_key.pem` is hardcoded in the enclave code: The MRSIGNER of the `example/signing_key.pem` is hardcoded in the enclave code:
@ -60,14 +60,14 @@ Run the occlum image in the docker environment:
```bash ```bash
# Notice that there is no SGX device mounted # Notice that there is no SGX device mounted
docker run --rm -it -v /path/to/occlum-ratls:/root/occlum-ratls occlum/occlum:latest-ubuntu20.04 docker run --rm -it -v /path/to/occlum-sgx:/root/occlum-sgx occlum/occlum:latest-ubuntu20.04
# Inside the docker container do env preparation to build the image # Inside the docker container do env preparation to build the image
rustup install stable-x86_64-unknown-linux-gnu rustup install stable-x86_64-unknown-linux-gnu
rustup default stable rustup default stable
rustup target add x86_64-unknown-linux-musl rustup target add x86_64-unknown-linux-musl
# Build the server and the client # Build the server and the client
cd occlum-ratls cd occlum-sgx
./build_server.sh grpcs ./build_server.sh grpcs
./build_client.sh grpcs ./build_client.sh grpcs
``` ```

@ -4,6 +4,7 @@ fn main() {
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
{ {
let target = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default(); let target = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
let dcap_lib_path = match target.as_str() { let dcap_lib_path = match target.as_str() {
"musl" => "/opt/occlum/toolchains/dcap_lib/musl", "musl" => "/opt/occlum/toolchains/dcap_lib/musl",
_ => "/opt/occlum/toolchains/dcap_lib/glibc", // gnu, msvc, sgx... _ => "/opt/occlum/toolchains/dcap_lib/glibc", // gnu, msvc, sgx...
@ -21,6 +22,16 @@ fn main() {
println!("cargo:rustc-link-search={}", dcap_lib_path); println!("cargo:rustc-link-search={}", dcap_lib_path);
println!("cargo:rustc-link-lib=occlum_dcap"); println!("cargo:rustc-link-lib=occlum_dcap");
// println!("cargo:rustc-link-lib=static:+whole-archive=occlum_dcap"); // println!("cargo:rustc-link-lib=static:+whole-archive=occlum_dcap");
/* ---occlum_utils--- */
let util_lib_path = match target.as_str() {
"musl" => "/opt/occlum/toolchains/utils_lib/musl",
_ => "/opt/occlum/toolchains/utils_lib/glibc", // gnu, msvc, sgx...
};
println!("cargo:rustc-link-search={}", util_lib_path);
println!("cargo:rustc-link-lib=occlum_utils");
} }
#[cfg(feature = "tonic")] #[cfg(feature = "tonic")]

@ -4,7 +4,7 @@ set -e
SCRIPT=$0 SCRIPT=$0
EXEC=$1 EXEC=$1
occlum-cargo build --release --example sealing --features="occlum" occlum-cargo build --release --example sealing --features="sealing"
strip target/x86_64-unknown-linux-musl/release/examples/sealing strip target/x86_64-unknown-linux-musl/release/examples/sealing
cat > sealing.yaml <<EOF cat > sealing.yaml <<EOF
@ -19,6 +19,7 @@ targets:
copy: copy:
- files: - files:
- /opt/occlum/toolchains/dcap_lib/musl/libocclum_dcap.so.0.1.0 - /opt/occlum/toolchains/dcap_lib/musl/libocclum_dcap.so.0.1.0
- /opt/occlum/toolchains/utils_lib/musl/libocclum_utils.so.0.1.0
EOF EOF
rm -rf sealing_instance && mkdir sealing_instance && cd sealing_instance rm -rf sealing_instance && mkdir sealing_instance && cd sealing_instance

@ -1,7 +1,51 @@
use occlum_ratls::prelude::*; use occlum_ratls::prelude::*;
use std::{
fs,
path::Path,
time::{SystemTime, UNIX_EPOCH},
};
const DATA_PATH: &str = "/host/sealed_data";
fn main() { fn main() {
println!("Example of sealing"); println!("Example of sealing");
let config = SealingConfig::new().unwrap(); let sgx_sealing = SgxSealing::new().unwrap();
config.print_sealing_key(); println!("sealing : {:?}", sgx_sealing);
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
println!("timestamp: {:?}", &timestamp);
if !Path::new(DATA_PATH).exists() {
// seal data
let payload = format!("this is sealing paylod; timestamp {}", timestamp)
.as_bytes()
.to_vec();
seal_and_write_data(sgx_sealing, payload);
} else {
// unseal data
let sealed_data = std::fs::read(DATA_PATH).unwrap();
unseal_data(sgx_sealing, sealed_data);
}
}
fn seal_and_write_data(sgx_sealing: SgxSealing, payload: Vec<u8>) {
let sealed_data = sgx_sealing.seal_data(payload).unwrap();
println!("sealed_data: {:?}", &sealed_data);
fs::write(DATA_PATH, &sealed_data).expect("Failed to write file {DATA_PATH}");
}
fn unseal_data(sgx_sealing: SgxSealing, sealed_data: Vec<u8>) {
println!("sealed_data: {:?}", &sealed_data);
let unsealed_data = sgx_sealing.un_seal_data(sealed_data).unwrap();
println!("unsealed_data: {:?}", &unsealed_data);
let unsealed_utf8_string = String::from_utf8_lossy(&unsealed_data);
println!("unsealed data utf8: \"{unsealed_utf8_string}\"");
} }

@ -1978,13 +1978,20 @@ extern "C" {
supplemental_data_size: u32, supplemental_data_size: u32,
supplemental_data: *mut u8, supplemental_data: *mut u8,
) -> i32; ) -> i32;
pub fn dcap_generate_key( pub fn dcap_quote_close(handle: *mut ::std::os::raw::c_void);
}
// occlum_utils occlum-detee/tools/toolchains/utils_lib
extern "C" {
pub fn utils_ioctl_open() -> *mut ::std::os::raw::c_void;
pub fn utils_gen_key(
handle: *mut ::std::os::raw::c_void, handle: *mut ::std::os::raw::c_void,
key: *mut sgx_key_128bit_t, key: *mut sgx_key_128bit_t,
key_request: *const sgx_key_request_t, key_request: *const sgx_key_request_t,
) -> i32; ) -> i32;
pub fn dcap_quote_close(handle: *mut ::std::os::raw::c_void); pub fn utils_ioctl_close(handle: *mut ::std::os::raw::c_void);
} }
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct __locale_data { pub struct __locale_data {

@ -2,7 +2,7 @@ use std::sync::Arc;
use crate::{ use crate::{
racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder}, racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder},
RaTlsConfig, RaTlsConfigBuilder, RaTlsError, RaTlsConfig, RaTlsConfigBuilder, SgxError,
}; };
use rustls::client::danger::HandshakeSignatureValid; use rustls::client::danger::HandshakeSignatureValid;
use rustls::crypto::{aws_lc_rs, verify_tls12_signature, verify_tls13_signature, CryptoProvider}; use rustls::crypto::{aws_lc_rs, verify_tls12_signature, verify_tls13_signature, CryptoProvider};
@ -79,7 +79,7 @@ pub struct RaTlsClientCertResolver {
} }
impl RaTlsClientCertResolver { impl RaTlsClientCertResolver {
pub fn new() -> Result<Self, RaTlsError> { pub fn new() -> Result<Self, SgxError> {
let builder = RaTlsCertificateBuilder::new().with_common_name("Client".to_string()); let builder = RaTlsCertificateBuilder::new().with_common_name("Client".to_string());
let cert = builder.build().map(Arc::new)?; let cert = builder.build().map(Arc::new)?;
Ok(Self { cert }) Ok(Self { cert })
@ -101,7 +101,7 @@ impl ResolvesClientCert for RaTlsClientCertResolver {
} }
impl RaTlsConfigBuilder<ClientConfig> for ClientConfig { impl RaTlsConfigBuilder<ClientConfig> for ClientConfig {
fn from_ratls_config(config: RaTlsConfig) -> Result<Self, RaTlsError> { fn from_ratls_config(config: RaTlsConfig) -> Result<Self, SgxError> {
Ok(Self::builder() Ok(Self::builder()
.dangerous() .dangerous()
.with_custom_certificate_verifier(Arc::new(RaTlsServerCertVerifier::new(config))) .with_custom_certificate_verifier(Arc::new(RaTlsServerCertVerifier::new(config)))

@ -1,11 +1,11 @@
use crate::{RaTlsConfigBuilder, RaTlsError}; use crate::{RaTlsConfigBuilder, SgxError};
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
use crate::quote::{Quote, STATIC_QUOTE}; use crate::quote::{Quote, STATIC_QUOTE};
use crate::quote::{SealingKeyPolicy, Sgx128BitKey, IOCTL_CLIENT};
use rustls::{ClientConfig, ServerConfig}; use rustls::{ClientConfig, ServerConfig};
#[cfg(feature = "occlum")]
pub type Measurement = [u8; 32]; pub type Measurement = [u8; 32];
#[derive(Default, Debug)] #[derive(Default, Debug)]
@ -57,7 +57,7 @@ impl InstanceMeasurement {
} }
} }
pub fn with_current_mrsigner(self) -> Result<Self, RaTlsError> { pub fn with_current_mrsigner(self) -> Result<Self, SgxError> {
let quote = Self::generate_static_empty_quote()?; let quote = Self::generate_static_empty_quote()?;
let mrsigner_from_quote = quote.mrsigner().into(); let mrsigner_from_quote = quote.mrsigner().into();
@ -78,7 +78,7 @@ impl InstanceMeasurement {
} }
} }
pub fn with_current_mrenclave(self) -> Result<Self, RaTlsError> { pub fn with_current_mrenclave(self) -> Result<Self, SgxError> {
let quote = Self::generate_static_empty_quote()?; let quote = Self::generate_static_empty_quote()?;
let mrenclave_from_quote = quote.mrenclave().into(); let mrenclave_from_quote = quote.mrenclave().into();
@ -99,7 +99,7 @@ impl InstanceMeasurement {
} }
} }
pub fn with_current_measurements() -> Result<Self, RaTlsError> { pub fn with_current_measurements() -> Result<Self, SgxError> {
let quote = Self::generate_static_empty_quote()?; let quote = Self::generate_static_empty_quote()?;
Ok(Self { Ok(Self {
@ -110,7 +110,7 @@ impl InstanceMeasurement {
}) })
} }
fn generate_static_empty_quote() -> Result<&'static Quote, RaTlsError> { fn generate_static_empty_quote() -> Result<&'static Quote, SgxError> {
Ok(STATIC_QUOTE.as_ref().map_err(|e| e.clone())?) Ok(STATIC_QUOTE.as_ref().map_err(|e| e.clone())?)
} }
@ -163,60 +163,22 @@ impl RaTlsConfig {
} }
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
pub(crate) fn is_allowed_quote(&self, quote: &Quote) -> Result<(), RaTlsError> { pub(crate) fn is_allowed_quote(&self, quote: &Quote) -> Result<(), SgxError> {
match self match self
.allowed_instances .allowed_instances
.iter() .iter()
.any(|im| im.check_quote_measurements(quote)) .any(|im| im.check_quote_measurements(quote))
{ {
true => Ok(()), true => Ok(()),
false => Err(RaTlsError::QuoteError(format!( false => Err(SgxError::QuoteError(format!("{:?} is not allowed", quote))),
"{:?} is not allowed",
quote
))),
} }
} }
pub fn into_server_config(self) -> Result<ServerConfig, RaTlsError> { pub fn into_server_config(self) -> Result<ServerConfig, SgxError> {
ServerConfig::from_ratls_config(self) ServerConfig::from_ratls_config(self)
} }
pub fn into_client_config(self) -> Result<ClientConfig, RaTlsError> { pub fn into_client_config(self) -> Result<ClientConfig, SgxError> {
ClientConfig::from_ratls_config(self) ClientConfig::from_ratls_config(self)
} }
} }
pub struct SealingConfig {
#[cfg(feature = "occlum")]
pub sealing_key: Sgx128BitKey,
}
impl SealingConfig {
#[cfg(feature = "occlum")]
fn generate_static_empty_quote() -> Result<&'static Quote, RaTlsError> {
Ok(STATIC_QUOTE.as_ref().map_err(|e| e.clone())?)
}
#[cfg(feature = "occlum")]
pub fn new() -> Result<Self, RaTlsError> {
let quote = Self::generate_static_empty_quote()?;
let policy = SealingKeyPolicy::MrEnclave;
let sealing_key = IOCTL_CLIENT
.lock()
.unwrap()
.generate_sealing_key(quote, policy)?;
Ok(Self { sealing_key })
}
pub fn print_sealing_key(&self) {
#[cfg(feature = "occlum")]
println!("Sealing key: {:?}", self.sealing_key);
#[cfg(not(feature = "occlum"))]
println!("Enable occlum feature");
}
#[cfg(not(feature = "occlum"))]
pub fn new() -> Result<Self, RaTlsError> {
Ok(Self {})
}
}

@ -1,22 +1,28 @@
use std::{error::Error, fmt::Display}; use std::{error::Error, fmt::Display};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum RaTlsError { pub enum SgxError {
CertificateBuildError(String), CertificateBuildError(String),
QuoteError(String), QuoteError(String),
DcapError(String), DcapError(String),
SealingError(String),
UnSealingError(String),
} }
impl Display for RaTlsError { impl Display for SgxError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self { match *self {
RaTlsError::CertificateBuildError(ref message) => { SgxError::CertificateBuildError(ref message) => {
write!(f, "CertificateBuildError: {}", message) write!(f, "CertificateBuildError: {}", message)
} }
RaTlsError::QuoteError(ref message) => write!(f, "QuoteVerifyError: {}", message), SgxError::QuoteError(ref message) => write!(f, "QuoteVerifyError: {}", message),
RaTlsError::DcapError(ref message) => write!(f, "DcapError: {}", message), SgxError::DcapError(ref message) => write!(f, "DcapError: {}", message),
SgxError::SealingError(ref message) => write!(f, "SealingError: {}", message),
SgxError::UnSealingError(ref message) => {
write!(f, "UnSealingError: {}", message)
}
} }
} }
} }
impl Error for RaTlsError {} impl Error for SgxError {}

142
src/ioctl.rs Normal file

@ -0,0 +1,142 @@
use crate::bindings::*;
use crate::error::SgxError;
use crate::quote::{ReportData, VerifyResult};
use log::{trace, warn};
use std::time::Instant;
type HandleType = *mut ::std::os::raw::c_void;
// TODO: it should be refactored. makes it abstract and hide quote_size and supplemental_size
pub struct SgxIoctlClient {
fd: HandleType,
quote_size: Option<u32>,
supplemental_size: Option<u32>,
}
// Needed to numb the compiler
unsafe impl Send for SgxIoctlClient {}
impl SgxIoctlClient {
pub(crate) fn new() -> Self {
Self {
fd: std::ptr::null_mut(),
quote_size: None,
supplemental_size: None,
}
}
pub(crate) fn handle(&mut self) -> Result<HandleType, SgxError> {
if self.fd.is_null() {
let handle = unsafe { dcap_quote_open() };
if handle.is_null() {
return Err(SgxError::DcapError(
"Failed to open DCAP quote device".to_string(),
));
}
self.fd = handle;
}
Ok(self.fd)
}
fn get_quote_size(&mut self) -> Result<u32, SgxError> {
if self.quote_size.is_none() {
let size = unsafe { dcap_get_quote_size(self.handle()?) };
trace!("DCAP quote size is {}", size);
self.quote_size = Some(size);
}
Ok(*self.quote_size.as_ref().unwrap())
}
fn get_supplemental_data_size(&mut self) -> Result<u32, SgxError> {
if self.supplemental_size.is_none() {
let size = unsafe { dcap_get_supplemental_data_size(self.handle()?) };
trace!("DCAP supplemental data size is {}", size);
self.supplemental_size = Some(size);
}
Ok(*self.supplemental_size.as_ref().unwrap())
}
pub fn generate_quote(&mut self, report_data: ReportData) -> Result<Vec<u8>, SgxError> {
let instant = Instant::now();
let quote_buf = self.generate_quote_inner(report_data)?;
trace!("Generated quote in {:?}ms", instant.elapsed().as_millis());
Ok(quote_buf)
}
fn generate_quote_inner(&mut self, report_data: ReportData) -> Result<Vec<u8>, SgxError> {
let quote_size = self.get_quote_size()?;
let mut quote_buf: Vec<u8> = vec![0; quote_size as usize];
let instant = Instant::now();
let ret_code = unsafe {
dcap_generate_quote(self.handle()?, quote_buf.as_mut_ptr(), &report_data.into())
};
trace!("Generated quote in {:?}ms", instant.elapsed().as_millis());
if ret_code < 0 {
return Err(SgxError::DcapError(
"Failed to generate DCAP quote".to_string(),
));
}
Ok(quote_buf)
}
pub fn verify_quote(&mut self, quote_buf: &[u8]) -> Result<VerifyResult, SgxError> {
let instant = Instant::now();
let result = self.verify_quote_inner(quote_buf)?;
trace!("Verified quote in {:?}ms", instant.elapsed().as_millis());
if result.is_negligible() {
if !result.is_ok() {
warn!("DCAP quote verification returned: {:?}", result);
}
return Ok(result);
}
Err(SgxError::QuoteError(format!(
"DCAP quote verification returned: {:?}",
result
)))
}
fn verify_quote_inner(&mut self, quote_buf: &[u8]) -> Result<VerifyResult, SgxError> {
let supplemental_data_size = self.get_supplemental_data_size()?;
let mut status = 1;
let mut result = SGX_QL_QV_RESULT_UNSPECIFIED;
let mut suppl_buf: Vec<u8> = vec![0; supplemental_data_size as usize];
let ret_code = unsafe {
dcap_verify_quote(
self.handle()?,
quote_buf.as_ptr(),
quote_buf.len() as u32,
&mut status,
&mut result,
supplemental_data_size,
suppl_buf.as_mut_ptr(),
)
};
if ret_code < 0 {
return Err(SgxError::DcapError(
"Failed to verify DCAP quote".to_string(),
));
}
Ok(result.into())
}
}
impl Drop for SgxIoctlClient {
fn drop(&mut self) {
unsafe {
if !self.fd.is_null() {
dcap_quote_close(self.fd);
}
}
}
}

@ -7,20 +7,30 @@ mod server;
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
mod utils; mod utils;
#[cfg(feature = "occlum")]
mod ioctl;
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
mod bindings; mod bindings;
pub mod prelude; pub mod prelude;
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
mod quote; mod quote;
//mod sscert;
#[allow(dead_code)]
#[cfg(feature = "occlum")]
mod sgx_consts;
#[cfg(feature = "sealing")]
mod sealing;
pub use crate::config::RaTlsConfig; pub use crate::config::RaTlsConfig;
pub use crate::config::SealingConfig; #[cfg(feature = "sealing")]
pub use crate::sealing::SgxSealing;
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
pub use crate::config::InstanceMeasurement; pub use crate::config::InstanceMeasurement;
pub use crate::error::RaTlsError; pub use crate::error::SgxError;
#[cfg(feature = "actix-web")] #[cfg(feature = "actix-web")]
pub use crate::http::actix_web; pub use crate::http::actix_web;
@ -29,5 +39,5 @@ pub use crate::http::actix_web;
pub use crate::http::reqwest; pub use crate::http::reqwest;
pub trait RaTlsConfigBuilder<T> { pub trait RaTlsConfigBuilder<T> {
fn from_ratls_config(config: RaTlsConfig) -> Result<T, RaTlsError>; fn from_ratls_config(config: RaTlsConfig) -> Result<T, SgxError>;
} }

@ -1,5 +1,6 @@
pub use crate::RaTlsConfig; pub use crate::RaTlsConfig;
pub use crate::SealingConfig; #[cfg(feature = "sealing")]
pub use crate::SgxSealing;
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
pub use crate::config::InstanceMeasurement; pub use crate::config::InstanceMeasurement;

@ -1,63 +1,18 @@
use crate::bindings::*; use crate::bindings::*;
use crate::error::RaTlsError; use crate::error::SgxError;
use crate::ioctl::SgxIoctlClient;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use log::{trace, warn};
use std::fmt::Debug; use std::fmt::Debug;
use std::ops::Deref; use std::ops::Deref;
use std::sync::Mutex; use std::sync::Mutex;
use std::time::Instant;
pub const SGX_FLAGS_INITTED: uint64_t = 0x0000_0000_0000_0001; //If set, then the enclave is initialized
pub const SGX_FLAGS_DEBUG: uint64_t = 0x0000_0000_0000_0002; //If set, then the enclave is debug
pub const SGX_FLAGS_MODE64BIT: uint64_t = 0x0000_0000_0000_0004; //If set, then the enclave is 64 bit
pub const SGX_FLAGS_PROVISION_KEY: uint64_t = 0x0000_0000_0000_0010; //If set, then the enclave has access to provision key
pub const SGX_FLAGS_EINITTOKEN_KEY: uint64_t = 0x0000_0000_0000_0020; //If set, then the enclave has access to EINITTOKEN key
pub const SGX_FLAGS_KSS: uint64_t = 0x0000_0000_0000_0080; //If set enclave uses KSS
pub const SGX_FLAGS_AEX_NOTIFY: uint64_t = 0x0000_0000_0000_0400; //If set, then the enclave enables AEX Notify
pub const FLAGS_NON_SECURITY_BITS: uint64_t = 0x00FF_FFFF_FFFF_FFC0
| SGX_FLAGS_MODE64BIT
| SGX_FLAGS_PROVISION_KEY
| SGX_FLAGS_EINITTOKEN_KEY;
pub const TSEAL_DEFAULT_FLAGSMASK: uint64_t = !FLAGS_NON_SECURITY_BITS;
pub const FLAGS_SECURITY_BITS_RESERVED: uint64_t =
!(FLAGS_NON_SECURITY_BITS | SGX_FLAGS_INITTED | SGX_FLAGS_DEBUG | SGX_FLAGS_KSS);
pub const MISC_NON_SECURITY_BITS: uint32_t = 0x0FFF_FFFF;
pub const TSEAL_DEFAULT_MISCMASK: uint32_t = !MISC_NON_SECURITY_BITS;
// TODO Intel sgx sdk 2.4
pub const SGX_KEYSELECT_LICENSE: uint16_t = 0x0000;
pub const SGX_KEYSELECT_PROVISION: uint16_t = 0x0001;
pub const SGX_KEYSELECT_PROVISION_SEAL: uint16_t = 0x0002;
pub const SGX_KEYSELECT_REPORT: uint16_t = 0x0003;
pub const SGX_KEYSELECT_SEAL: uint16_t = 0x0004;
// Key Policy
pub const SGX_KEYPOLICY_MRENCLAVE: uint16_t = 0x0001; /* Derive key using the enclave's ENCLAVE measurement register */
pub const SGX_KEYPOLICY_MRSIGNER: uint16_t = 0x0002; /* Derive key using the enclave's SINGER measurement register */
pub const SGX_KEYPOLICY_NOISVPRODID: uint16_t = 0x0004; /* Derive key without the enclave's ISVPRODID */
pub const SGX_KEYPOLICY_CONFIGID: uint16_t = 0x0008; /* Derive key with the enclave's CONFIGID */
pub const SGX_KEYPOLICY_ISVFAMILYID: uint16_t = 0x0010; /* Derive key with the enclave's ISVFAMILYID */
pub const SGX_KEYPOLICY_ISVEXTPRODID: uint16_t = 0x0020; /* Derive key with the enclave's ISVEXTPRODID */
pub const SGX_KEYID_SIZE: size_t = 32;
pub const SGX_CPUSVN_SIZE: size_t = 16;
pub const SGX_CONFIGID_SIZE: size_t = 64;
pub const SGX_KEY_REQUEST_RESERVED2_BYTES: size_t = 434;
pub enum SealingKeyPolicy {
MrSigner,
MrEnclave,
}
pub type Sgx128BitKey = sgx_key_128bit_t;
pub struct Quote { pub struct Quote {
buf: Vec<u8>, buf: Vec<u8>,
report_body: *const sgx_report_body_t, pub(crate) report_body: *const sgx_report_body_t,
} }
impl TryFrom<Vec<u8>> for Quote { impl TryFrom<Vec<u8>> for Quote {
type Error = RaTlsError; type Error = SgxError;
fn try_from(buf: Vec<u8>) -> Result<Self, Self::Error> { fn try_from(buf: Vec<u8>) -> Result<Self, Self::Error> {
let report_body_offset = size_of::<QuoteHeader>(); let report_body_offset = size_of::<QuoteHeader>();
let report_body_size = size_of::<sgx_report_body_t>(); let report_body_size = size_of::<sgx_report_body_t>();
@ -65,7 +20,7 @@ impl TryFrom<Vec<u8>> for Quote {
if buf.len() < report_body_offset + report_body_size { if buf.len() < report_body_offset + report_body_size {
let minimal = report_body_offset + report_body_size; let minimal = report_body_offset + report_body_size;
let actual = buf.len(); let actual = buf.len();
return Err(RaTlsError::QuoteError(format!( return Err(SgxError::QuoteError(format!(
"Failed to parse DCAP quote, min {minimal}, act {actual}" "Failed to parse DCAP quote, min {minimal}, act {actual}"
))); )));
} }
@ -88,7 +43,7 @@ struct QuoteHeader {
} }
impl TryFrom<&[u8]> for Quote { impl TryFrom<&[u8]> for Quote {
type Error = RaTlsError; type Error = SgxError;
fn try_from(buf: &[u8]) -> Result<Self, Self::Error> { fn try_from(buf: &[u8]) -> Result<Self, Self::Error> {
buf.to_vec().try_into() buf.to_vec().try_into()
@ -96,7 +51,7 @@ impl TryFrom<&[u8]> for Quote {
} }
impl TryFrom<ReportData> for Quote { impl TryFrom<ReportData> for Quote {
type Error = RaTlsError; type Error = SgxError;
fn try_from(value: ReportData) -> Result<Self, Self::Error> { fn try_from(value: ReportData) -> Result<Self, Self::Error> {
Self::from_report_data(value) Self::from_report_data(value)
@ -112,7 +67,7 @@ impl Deref for Quote {
} }
impl Quote { impl Quote {
pub fn from_report_data(data: ReportData) -> Result<Self, RaTlsError> { pub fn from_report_data(data: ReportData) -> Result<Self, SgxError> {
IOCTL_CLIENT IOCTL_CLIENT
.lock() .lock()
.unwrap() .unwrap()
@ -120,7 +75,7 @@ impl Quote {
.try_into() .try_into()
} }
pub fn from_slice(slice: &[u8]) -> Result<Self, RaTlsError> { pub fn from_slice(slice: &[u8]) -> Result<Self, SgxError> {
slice.try_into() slice.try_into()
} }
@ -128,7 +83,7 @@ impl Quote {
self self
} }
pub fn verify(&self) -> Result<VerifyResult, RaTlsError> { pub fn verify(&self) -> Result<VerifyResult, SgxError> {
IOCTL_CLIENT.lock().unwrap().verify_quote(self.buf.as_ref()) IOCTL_CLIENT.lock().unwrap().verify_quote(self.buf.as_ref())
} }
@ -181,8 +136,8 @@ impl Debug for Quote {
} }
lazy_static! { lazy_static! {
pub static ref IOCTL_CLIENT: Mutex<IoctlClient> = { pub static ref IOCTL_CLIENT: Mutex<SgxIoctlClient> = {
let client = IoctlClient::new(); let client = SgxIoctlClient::new();
Mutex::new(client) Mutex::new(client)
}; };
} }
@ -194,200 +149,11 @@ lazy_static! {
// unsafe impl Send for Quote {} // unsafe impl Send for Quote {}
lazy_static! { lazy_static! {
pub static ref STATIC_QUOTE: Result<Quote, RaTlsError> = Quote::from_report_data([0u8; 64]); pub static ref STATIC_QUOTE: Result<Quote, SgxError> = Quote::from_report_data([0u8; 64]);
} }
unsafe impl Sync for Quote {} unsafe impl Sync for Quote {}
pub struct IoctlClient {
fd: HandleType,
quote_size: Option<u32>,
supplemental_size: Option<u32>,
}
// Needed to numb the compiler
unsafe impl Send for IoctlClient {}
impl IoctlClient {
fn new() -> Self {
Self {
fd: std::ptr::null_mut(),
quote_size: None,
supplemental_size: None,
}
}
fn handle(&mut self) -> Result<HandleType, RaTlsError> {
if self.fd.is_null() {
let handle = unsafe { dcap_quote_open() };
if handle.is_null() {
return Err(RaTlsError::DcapError(
"Failed to open DCAP quote device".to_string(),
));
}
self.fd = handle;
}
Ok(self.fd)
}
fn get_quote_size(&mut self) -> Result<u32, RaTlsError> {
if self.quote_size.is_none() {
let size = unsafe { dcap_get_quote_size(self.handle()?) };
trace!("DCAP quote size is {}", size);
self.quote_size = Some(size);
}
Ok(*self.quote_size.as_ref().unwrap())
}
fn get_supplemental_data_size(&mut self) -> Result<u32, RaTlsError> {
if self.supplemental_size.is_none() {
let size = unsafe { dcap_get_supplemental_data_size(self.handle()?) };
trace!("DCAP supplemental data size is {}", size);
self.supplemental_size = Some(size);
}
Ok(*self.supplemental_size.as_ref().unwrap())
}
pub fn generate_quote(&mut self, report_data: ReportData) -> Result<Vec<u8>, RaTlsError> {
let instant = Instant::now();
let quote_buf = self.generate_quote_inner(report_data)?;
trace!("Generated quote in {:?}ms", instant.elapsed().as_millis());
Ok(quote_buf)
}
fn generate_quote_inner(&mut self, report_data: ReportData) -> Result<Vec<u8>, RaTlsError> {
let quote_size = self.get_quote_size()?;
let mut quote_buf: Vec<u8> = vec![0; quote_size as usize];
let instant = Instant::now();
let ret_code = unsafe {
dcap_generate_quote(self.handle()?, quote_buf.as_mut_ptr(), &report_data.into())
};
trace!("Generated quote in {:?}ms", instant.elapsed().as_millis());
if ret_code < 0 {
return Err(RaTlsError::DcapError(
"Failed to generate DCAP quote".to_string(),
));
}
Ok(quote_buf)
}
pub fn verify_quote(&mut self, quote_buf: &[u8]) -> Result<VerifyResult, RaTlsError> {
let instant = Instant::now();
let result = self.verify_quote_inner(quote_buf)?;
trace!("Verified quote in {:?}ms", instant.elapsed().as_millis());
if result.is_negligible() {
if !result.is_ok() {
warn!("DCAP quote verification returned: {:?}", result);
}
return Ok(result);
}
Err(RaTlsError::QuoteError(format!(
"DCAP quote verification returned: {:?}",
result
)))
}
fn verify_quote_inner(&mut self, quote_buf: &[u8]) -> Result<VerifyResult, RaTlsError> {
let supplemental_data_size = self.get_supplemental_data_size()?;
let mut status = 1;
let mut result = SGX_QL_QV_RESULT_UNSPECIFIED;
let mut suppl_buf: Vec<u8> = vec![0; supplemental_data_size as usize];
let ret_code = unsafe {
dcap_verify_quote(
self.handle()?,
quote_buf.as_ptr(),
quote_buf.len() as u32,
&mut status,
&mut result,
supplemental_data_size,
suppl_buf.as_mut_ptr(),
)
};
if ret_code < 0 {
return Err(RaTlsError::DcapError(
"Failed to verify DCAP quote".to_string(),
));
}
Ok(result.into())
}
/// Generate a sealing key for the given policy and SGX report
/// The sealing key is used to encrypt/decrypt data in the enclave
/// The quote must be previously generated using the `generate_quote`
pub fn generate_sealing_key(
&mut self,
quote: &Quote,
policy: SealingKeyPolicy,
) -> Result<Sgx128BitKey, RaTlsError> {
let report_body = unsafe { *quote.report_body };
let mut key_policy = match policy {
SealingKeyPolicy::MrSigner => SGX_KEYPOLICY_MRSIGNER,
SealingKeyPolicy::MrEnclave => SGX_KEYPOLICY_MRENCLAVE,
};
if (report_body.attributes.flags & SGX_FLAGS_KSS) != 0 {
const KEY_POLICY_KSS: uint16_t =
SGX_KEYPOLICY_CONFIGID | SGX_KEYPOLICY_ISVFAMILYID | SGX_KEYPOLICY_ISVEXTPRODID;
key_policy = key_policy | KEY_POLICY_KSS;
}
// Intel sgx sdk 1.8
let attribute_mask = sgx_attributes_t {
flags: TSEAL_DEFAULT_FLAGSMASK,
xfrm: 0,
};
let mut key_id = sgx_key_id_t::default();
let misc_mask: sgx_misc_select_t = TSEAL_DEFAULT_MISCMASK;
let mut key = sgx_key_128bit_t::default();
let key_request = sgx_key_request_t {
key_name: SGX_KEYSELECT_SEAL,
key_policy,
isv_svn: report_body.isv_svn,
reserved1: 0_u16,
cpu_svn: report_body.cpu_svn,
attribute_mask,
key_id,
misc_mask,
config_svn: report_body.config_svn,
reserved2: [0_u8; SGX_KEY_REQUEST_RESERVED2_BYTES],
};
let ret_code = unsafe { dcap_generate_key(self.handle()?, &mut key, &key_request) };
if ret_code < 0 {
return Err(RaTlsError::DcapError(
"Failed to generate DCAP sealing key".to_string(),
));
}
Ok(key)
}
}
impl Drop for IoctlClient {
fn drop(&mut self) {
unsafe {
if !self.fd.is_null() {
dcap_quote_close(self.fd);
}
}
}
}
type HandleType = *mut ::std::os::raw::c_void;
pub type ReportData = [u8; 64]; pub type ReportData = [u8; 64];
#[derive(Debug)] #[derive(Debug)]

@ -2,7 +2,7 @@ use std::error::Error;
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
use crate::utils::hash_sha512; use crate::utils::hash_sha512;
use crate::{error::RaTlsError, RaTlsConfig}; use crate::{error::SgxError, RaTlsConfig};
use log::error; use log::error;
#[cfg(feature = "occlum")] #[cfg(feature = "occlum")]
@ -18,7 +18,7 @@ use rustls::{pki_types::CertificateDer, sign::CertifiedKey};
use x509_parser::{nom::Parser, oid_registry::Oid, prelude::X509CertificateParser, public_key}; use x509_parser::{nom::Parser, oid_registry::Oid, prelude::X509CertificateParser, public_key};
pub trait CertificateBuilder: Send + Sync { pub trait CertificateBuilder: Send + Sync {
fn build(&self) -> Result<CertifiedKey, RaTlsError>; fn build(&self) -> Result<CertifiedKey, SgxError>;
} }
struct RaTlsCertifiedKey { struct RaTlsCertifiedKey {
@ -86,16 +86,16 @@ impl RaTlsCertificateBuilder {
} }
impl CertificateBuilder for RaTlsCertificateBuilder { impl CertificateBuilder for RaTlsCertificateBuilder {
fn build(&self) -> Result<CertifiedKey, RaTlsError> { fn build(&self) -> Result<CertifiedKey, SgxError> {
let cert_key = self.build_internal().map_err(|e| { let cert_key = self.build_internal().map_err(|e| {
let err = RaTlsError::CertificateBuildError(e.to_string()); let err = SgxError::CertificateBuildError(e.to_string());
error!("{}", err); error!("{}", err);
err err
})?; })?;
let private_key_der = PrivateKeyDer::from(PrivatePkcs8KeyDer::from(cert_key.key_der)); let private_key_der = PrivateKeyDer::from(PrivatePkcs8KeyDer::from(cert_key.key_der));
let signing_key = any_supported_type(&private_key_der).map_err(|e| { let signing_key = any_supported_type(&private_key_der).map_err(|e| {
let err = RaTlsError::CertificateBuildError(e.to_string()); let err = SgxError::CertificateBuildError(e.to_string());
error!("{}", err); error!("{}", err);
err err
})?; })?;

@ -1,2 +0,0 @@
#[cfg(feature = "occlum")]
use crate::quote::{Quote, STATIC_QUOTE};

21
src/sealing/decrypt.rs Normal file

@ -0,0 +1,21 @@
use aes_gcm::{aead::Aead, Aes256Gcm, Key, KeyInit, Nonce};
use super::SgxSealing;
use crate::SgxError;
impl SgxSealing {
pub fn un_seal_data(self, payload_encrypted_packet: Vec<u8>) -> Result<Vec<u8>, SgxError> {
let sealing_key = self.get_aes256_sealing_key()?;
let aes_encryption_256bit_key = Key::<Aes256Gcm>::from_slice(&sealing_key);
let nonce = Nonce::from_slice(&payload_encrypted_packet[..12]); // nonce (IV) 96-bits (12); is prepending while encryping
let raw_cipher_text = &payload_encrypted_packet[12..];
let cipher = Aes256Gcm::new(aes_encryption_256bit_key);
let clear_text = cipher
.decrypt(nonce, raw_cipher_text.as_ref())
.map_err(|e| SgxError::UnSealingError(e.to_string()))?;
Ok(clear_text)
}
}

26
src/sealing/encrypt.rs Normal file

@ -0,0 +1,26 @@
use aes_gcm::{
aead::{Aead, AeadCore, OsRng},
Aes256Gcm, Key, KeyInit,
};
use super::SgxSealing;
use crate::SgxError;
impl SgxSealing {
pub fn seal_data(self, payload_plain_text: Vec<u8>) -> Result<Vec<u8>, SgxError> {
let sealing_key = self.get_aes256_sealing_key()?;
let aes_encryption_256bit_key = Key::<Aes256Gcm>::from_slice(&sealing_key);
let nonce = Aes256Gcm::generate_nonce(&mut OsRng); // 96-bits (12); unique per message
let cipher = Aes256Gcm::new(aes_encryption_256bit_key);
let mut ciphertext = cipher
.encrypt(&nonce, payload_plain_text.as_ref())
.map_err(|e| SgxError::SealingError(e.to_string()))?;
let mut encrypted_packet = nonce.to_vec();
encrypted_packet.append(&mut ciphertext);
Ok(encrypted_packet)
}
}

@ -0,0 +1,19 @@
use pbkdf2::pbkdf2_hmac_array;
use sha2::Sha256;
use super::SgxSealing;
use crate::SgxError;
pub type SealingKey256BitDerived = [u8; 32];
impl SgxSealing {
pub fn get_aes256_sealing_key(self) -> Result<SealingKey256BitDerived, SgxError> {
let mrsigner_for_salt = Self::get_current_sgx_quote()?.mrsigner().m;
Ok(pbkdf2_hmac_array::<Sha256, 32>(
&self.sealing_key,
&mrsigner_for_salt,
25519,
))
}
}

8
src/sealing/mod.rs Normal file

@ -0,0 +1,8 @@
mod decrypt;
mod encrypt;
pub mod key_derivation;
pub mod sealing_config;
pub mod sealing_error;
pub use sealing_config::SealingConfig;
pub use sealing_error::SealingError;

107
src/sealing/sgx_sealing.rs Normal file

@ -0,0 +1,107 @@
use crate::bindings::*;
use crate::error::SgxError;
use crate::ioctl::SgxIoctlClient;
#[cfg(feature = "occlum")]
use crate::quote::{Quote, IOCTL_CLIENT, STATIC_QUOTE};
use crate::sgx_consts::{
SGX_FLAGS_KSS, SGX_KEYPOLICY_CONFIGID, SGX_KEYPOLICY_ISVEXTPRODID, SGX_KEYPOLICY_ISVFAMILYID,
SGX_KEYPOLICY_MRENCLAVE, SGX_KEYPOLICY_MRSIGNER, SGX_KEYSELECT_SEAL,
SGX_KEY_REQUEST_RESERVED2_BYTES, TSEAL_DEFAULT_FLAGSMASK, TSEAL_DEFAULT_MISCMASK,
};
#[allow(dead_code)]
pub enum SealingKeyPolicy {
MrSigner,
MrEnclave,
}
pub type Sgx128BitKey = sgx_key_128bit_t;
#[derive(Debug)]
pub struct SgxSealing {
#[cfg(feature = "occlum")]
pub sealing_key: Sgx128BitKey,
}
impl SgxSealing {
#[cfg(feature = "occlum")]
pub(crate) fn get_current_sgx_quote() -> Result<&'static Quote, SgxError> {
Ok(STATIC_QUOTE.as_ref().map_err(|e| e.clone())?)
}
#[cfg(feature = "occlum")]
pub fn new() -> Result<Self, SgxError> {
// by default, use MrEnclave key policy
Self::with_policy(SealingKeyPolicy::MrEnclave)
}
pub fn with_policy(policy: SealingKeyPolicy) -> Result<Self, SgxError> {
let quote = Self::get_current_sgx_quote()?;
let sealing_key = IOCTL_CLIENT
.lock()
.unwrap()
.generate_sealing_key(quote, policy)?;
Ok(Self { sealing_key })
}
#[cfg(not(feature = "occlum"))]
pub fn new() -> Result<Self, SgxError> {
Ok(Self {})
}
}
impl SgxIoctlClient {
/// Generate a sealing key for the given policy and SGX report
/// The sealing key is used to encrypt/decrypt data in the enclave
/// The quote must be previously generated using the `generate_quote`
fn generate_sealing_key(
&mut self,
quote: &Quote,
policy: SealingKeyPolicy,
) -> Result<Sgx128BitKey, SgxError> {
let report_body = unsafe { *quote.report_body };
let mut key_policy = match policy {
SealingKeyPolicy::MrSigner => SGX_KEYPOLICY_MRSIGNER,
SealingKeyPolicy::MrEnclave => SGX_KEYPOLICY_MRENCLAVE,
};
if (report_body.attributes.flags & SGX_FLAGS_KSS) != 0 {
const KEY_POLICY_KSS: uint16_t =
SGX_KEYPOLICY_CONFIGID | SGX_KEYPOLICY_ISVFAMILYID | SGX_KEYPOLICY_ISVEXTPRODID;
key_policy = key_policy | KEY_POLICY_KSS;
}
// Intel sgx sdk 1.8
let attribute_mask = sgx_attributes_t {
flags: TSEAL_DEFAULT_FLAGSMASK,
xfrm: 0,
};
let key_id = sgx_key_id_t::default();
let misc_mask: sgx_misc_select_t = TSEAL_DEFAULT_MISCMASK;
let mut key = sgx_key_128bit_t::default();
let key_request = sgx_key_request_t {
key_name: SGX_KEYSELECT_SEAL,
key_policy,
isv_svn: report_body.isv_svn,
reserved1: 0_u16,
cpu_svn: report_body.cpu_svn,
attribute_mask,
key_id,
misc_mask,
config_svn: report_body.config_svn,
reserved2: [0_u8; SGX_KEY_REQUEST_RESERVED2_BYTES],
};
let ret_code = unsafe { utils_gen_key(self.handle()?, &mut key, &key_request) };
if ret_code < 0 {
return Err(SgxError::DcapError(
"Failed to generate DCAP sealing key".to_string(),
));
}
Ok(key)
}
}

@ -1,6 +1,6 @@
use crate::{ use crate::{
racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder}, racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder},
RaTlsConfig, RaTlsConfigBuilder, RaTlsError, RaTlsConfig, RaTlsConfigBuilder, SgxError,
}; };
use rustls::client::danger::HandshakeSignatureValid; use rustls::client::danger::HandshakeSignatureValid;
use rustls::crypto::{aws_lc_rs, verify_tls12_signature, verify_tls13_signature, CryptoProvider}; use rustls::crypto::{aws_lc_rs, verify_tls12_signature, verify_tls13_signature, CryptoProvider};
@ -81,7 +81,7 @@ pub struct RaTlsServerCertResolver {
} }
impl RaTlsServerCertResolver { impl RaTlsServerCertResolver {
pub fn new() -> Result<Self, RaTlsError> { pub fn new() -> Result<Self, SgxError> {
let builder = RaTlsCertificateBuilder::new().with_common_name("Client".to_string()); let builder = RaTlsCertificateBuilder::new().with_common_name("Client".to_string());
let cert = builder.build().map(Arc::new)?; let cert = builder.build().map(Arc::new)?;
Ok(Self { cert }) Ok(Self { cert })
@ -95,7 +95,7 @@ impl ResolvesServerCert for RaTlsServerCertResolver {
} }
impl RaTlsConfigBuilder<ServerConfig> for ServerConfig { impl RaTlsConfigBuilder<ServerConfig> for ServerConfig {
fn from_ratls_config(config: RaTlsConfig) -> Result<Self, RaTlsError> { fn from_ratls_config(config: RaTlsConfig) -> Result<Self, SgxError> {
Ok(Self::builder() Ok(Self::builder()
.with_client_cert_verifier(Arc::new(RaTlsClientCertVerifier::new(config))) .with_client_cert_verifier(Arc::new(RaTlsClientCertVerifier::new(config)))
.with_cert_resolver(Arc::new(RaTlsServerCertResolver::new()?))) .with_cert_resolver(Arc::new(RaTlsServerCertResolver::new()?)))

38
src/sgx_consts.rs Normal file

@ -0,0 +1,38 @@
use crate::bindings::*;
pub const SGX_FLAGS_INITTED: uint64_t = 0x0000_0000_0000_0001; //If set, then the enclave is initialized
pub const SGX_FLAGS_DEBUG: uint64_t = 0x0000_0000_0000_0002; //If set, then the enclave is debug
pub const SGX_FLAGS_MODE64BIT: uint64_t = 0x0000_0000_0000_0004; //If set, then the enclave is 64 bit
pub const SGX_FLAGS_PROVISION_KEY: uint64_t = 0x0000_0000_0000_0010; //If set, then the enclave has access to provision key
pub const SGX_FLAGS_EINITTOKEN_KEY: uint64_t = 0x0000_0000_0000_0020; //If set, then the enclave has access to EINITTOKEN key
pub const SGX_FLAGS_KSS: uint64_t = 0x0000_0000_0000_0080; //If set enclave uses KSS
pub const SGX_FLAGS_AEX_NOTIFY: uint64_t = 0x0000_0000_0000_0400; //If set, then the enclave enables AEX Notify
pub const FLAGS_NON_SECURITY_BITS: uint64_t = 0x00FF_FFFF_FFFF_FFC0
| SGX_FLAGS_MODE64BIT
| SGX_FLAGS_PROVISION_KEY
| SGX_FLAGS_EINITTOKEN_KEY;
pub const TSEAL_DEFAULT_FLAGSMASK: uint64_t = !FLAGS_NON_SECURITY_BITS;
pub const FLAGS_SECURITY_BITS_RESERVED: uint64_t =
!(FLAGS_NON_SECURITY_BITS | SGX_FLAGS_INITTED | SGX_FLAGS_DEBUG | SGX_FLAGS_KSS);
pub const MISC_NON_SECURITY_BITS: uint32_t = 0x0FFF_FFFF;
pub const TSEAL_DEFAULT_MISCMASK: uint32_t = !MISC_NON_SECURITY_BITS;
// TODO Intel sgx sdk 2.4
pub const SGX_KEYSELECT_LICENSE: uint16_t = 0x0000;
pub const SGX_KEYSELECT_PROVISION: uint16_t = 0x0001;
pub const SGX_KEYSELECT_PROVISION_SEAL: uint16_t = 0x0002;
pub const SGX_KEYSELECT_REPORT: uint16_t = 0x0003;
pub const SGX_KEYSELECT_SEAL: uint16_t = 0x0004;
// Key Policy
pub const SGX_KEYPOLICY_MRENCLAVE: uint16_t = 0x0001; /* Derive key using the enclave's ENCLAVE measurement register */
pub const SGX_KEYPOLICY_MRSIGNER: uint16_t = 0x0002; /* Derive key using the enclave's SINGER measurement register */
pub const SGX_KEYPOLICY_NOISVPRODID: uint16_t = 0x0004; /* Derive key without the enclave's ISVPRODID */
pub const SGX_KEYPOLICY_CONFIGID: uint16_t = 0x0008; /* Derive key with the enclave's CONFIGID */
pub const SGX_KEYPOLICY_ISVFAMILYID: uint16_t = 0x0010; /* Derive key with the enclave's ISVFAMILYID */
pub const SGX_KEYPOLICY_ISVEXTPRODID: uint16_t = 0x0020; /* Derive key with the enclave's ISVEXTPRODID */
pub const SGX_KEYID_SIZE: size_t = 32;
pub const SGX_CPUSVN_SIZE: size_t = 16;
pub const SGX_CONFIGID_SIZE: size_t = 64;
pub const SGX_KEY_REQUEST_RESERVED2_BYTES: size_t = 434;

@ -1,67 +0,0 @@
// use rustls::{server::{ClientCertVerified, ClientCertVerifier, ResolvesServerCert}, sign::CertifiedKey, Certificate, Error, ServerConfig, DistinguishedNames};
// use std::{sync::Arc, time::SystemTime};
//
// use crate::{
// racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder},
// RaTlsConfig, RaTlsConfigBuilder, RaTlsError,
// };
//
// pub struct RaTlsClientCertVerifier {
// config: RaTlsConfig,
// }
//
// impl RaTlsClientCertVerifier {
// pub fn new(config: RaTlsConfig) -> Self {
// Self { config }
// }
// }
//
// impl ClientCertVerifier for RaTlsClientCertVerifier {
// fn verify_client_cert(
// &self,
// end_entity: &Certificate,
// _intermediates: &[Certificate],
// _now: SystemTime,
// ) -> Result<ClientCertVerified, Error> {
// end_entity.verify_quote(&self.config).map_err(|e| {
// println!("{:?}", e);
// rustls::Error::General(e.to_string())
// })?;
//
// Ok(ClientCertVerified::assertion())
// }
//
// fn client_auth_root_subjects(&self) -> Option<DistinguishedNames> {
// Some(DistinguishedNames::new())
// }
// }
//
// pub struct RaTlsServerCertResolver {
// cert: Arc<CertifiedKey>,
// }
//
// impl RaTlsServerCertResolver {
// pub fn new() -> Result<Self, RaTlsError> {
// let builder = RaTlsCertificateBuilder::new().with_common_name("Client".to_string());
// let cert = builder.build().map(Arc::new)?;
// Ok(Self { cert })
// }
// }
//
// impl ResolvesServerCert for RaTlsServerCertResolver {
// fn resolve(
// &self,
// _client_hello: rustls::server::ClientHello,
// ) -> Option<std::sync::Arc<CertifiedKey>> {
// Some(self.cert.clone())
// }
// }
//
// impl RaTlsConfigBuilder<ServerConfig> for ServerConfig {
// fn from_ratls_config(config: RaTlsConfig) -> Result<Self, RaTlsError> {
// Ok(Self::builder()
// .with_safe_defaults()
// .with_client_cert_verifier(Arc::new(RaTlsClientCertVerifier::new(config)))
// .with_cert_resolver(Arc::new(RaTlsServerCertResolver::new()?)))
// }
// }