From 2cd8fc0e56d8411c27caf81707ea4ed6be47d857 Mon Sep 17 00:00:00 2001 From: Noor Date: Mon, 21 Oct 2024 10:59:42 +0000 Subject: [PATCH] refactor --- Cargo.toml | 35 +++-- README.md | 6 +- build.rs | 11 ++ build_sealing.sh | 3 +- examples/sealing.rs | 48 ++++++- src/bindings.rs | 11 +- src/client.rs | 6 +- src/config.rs | 58 ++------ src/error.rs | 18 ++- src/ioctl.rs | 142 +++++++++++++++++++ src/lib.rs | 18 ++- src/prelude.rs | 3 +- src/quote.rs | 260 ++-------------------------------- src/racert.rs | 10 +- src/sealing.rs | 2 - src/sealing/decrypt.rs | 21 +++ src/sealing/encrypt.rs | 26 ++++ src/sealing/key_derivation.rs | 19 +++ src/sealing/mod.rs | 8 ++ src/sealing/sgx_sealing.rs | 107 ++++++++++++++ src/server.rs | 6 +- src/sgx_consts.rs | 38 +++++ src/sscert.rs | 67 --------- 23 files changed, 517 insertions(+), 406 deletions(-) create mode 100644 src/ioctl.rs delete mode 100644 src/sealing.rs create mode 100644 src/sealing/decrypt.rs create mode 100644 src/sealing/encrypt.rs create mode 100644 src/sealing/key_derivation.rs create mode 100644 src/sealing/mod.rs create mode 100644 src/sealing/sgx_sealing.rs create mode 100644 src/sgx_consts.rs delete mode 100644 src/sscert.rs diff --git a/Cargo.toml b/Cargo.toml index 7f25006..f17d726 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,11 +2,11 @@ # All rights reserved. [package] -name = "occlum-ratls" +name = "occlum-sgx" version = "0.1.0" edition = "2021" -authors = ["Valentyn Faychuk ", "Ivan Chirkin "] -description = "Remote attestation for Intel SGX" +authors = ["Valentyn Faychuk "] +description = "Intel SGX Occlum interface" license = "MIT OR Apache-2.0" keywords = ["occlum", "rustls", "ratls"] # Inspired by https://github.com/aggregion/occlum-ratls @@ -14,7 +14,6 @@ keywords = ["occlum", "rustls", "ratls"] [dependencies] rustls = "0.23" x509-parser = "0.16" -#occlum-sgx = "0.1" # get/verify quote ring = "0.17" # hash256 rcgen = "0.13" log = "0.4" @@ -28,10 +27,6 @@ hyper-rustls = { version = "0.27", features = ["http2"] } prost = "0.13" base64 = "0.22" 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] version = "0.12" @@ -57,6 +52,19 @@ default-features = false features = ["__rustls"] 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] version = "0.11" @@ -76,26 +84,29 @@ tonic-build = "0.12" default = [] # TOOD: rename to testing and reverse uses in the code occlum = [] +sealing = ["occlum", "dep:pbkdf2", "dep:sha2", "dep:aes-gcm"] reqwest = ["dep:reqwest"] actix-web = ["dep:actix-web", "actix-service", "actix-http"] tonic = ["dep:tonic"] +full = ["occlum", "sealing", "reqwest", "actix-web", "tonic"] [[example]] name = "mratls_https_server" -required-features = ["actix-web"] +required-features = ["actix-web", "occlum"] [[example]] name = "mratls_https_client" -required-features = ["reqwest"] +required-features = ["reqwest", "occlum"] [[example]] name = "mratls_grpcs_server" -required-features = ["tonic"] +required-features = ["tonic", "occlum"] [[example]] name = "mratls_grpcs_client" -required-features = ["tonic"] +required-features = ["tonic", "occlum"] [[example]] name = "sealing" +required-features = ["sealing"] diff --git a/README.md b/README.md index e73ea1e..6bde319 100644 --- a/README.md +++ b/README.md @@ -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: @@ -60,14 +60,14 @@ Run the occlum image in the docker environment: ```bash # 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 rustup install stable-x86_64-unknown-linux-gnu rustup default stable rustup target add x86_64-unknown-linux-musl # Build the server and the client -cd occlum-ratls +cd occlum-sgx ./build_server.sh grpcs ./build_client.sh grpcs ``` diff --git a/build.rs b/build.rs index 78703f9..e6195bf 100644 --- a/build.rs +++ b/build.rs @@ -4,6 +4,7 @@ fn main() { #[cfg(feature = "occlum")] { let target = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default(); + let dcap_lib_path = match target.as_str() { "musl" => "/opt/occlum/toolchains/dcap_lib/musl", _ => "/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-lib=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")] diff --git a/build_sealing.sh b/build_sealing.sh index 5004d26..eb73a36 100755 --- a/build_sealing.sh +++ b/build_sealing.sh @@ -4,7 +4,7 @@ set -e SCRIPT=$0 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 cat > sealing.yaml <) { + 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) { + 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}\""); } diff --git a/src/bindings.rs b/src/bindings.rs index 9b17d78..084b86e 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -1978,13 +1978,20 @@ extern "C" { supplemental_data_size: u32, supplemental_data: *mut u8, ) -> 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, key: *mut sgx_key_128bit_t, key_request: *const sgx_key_request_t, ) -> 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)] #[derive(Debug, Copy, Clone)] pub struct __locale_data { diff --git a/src/client.rs b/src/client.rs index f5c5b43..4164771 100644 --- a/src/client.rs +++ b/src/client.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use crate::{ racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder}, - RaTlsConfig, RaTlsConfigBuilder, RaTlsError, + RaTlsConfig, RaTlsConfigBuilder, SgxError, }; use rustls::client::danger::HandshakeSignatureValid; use rustls::crypto::{aws_lc_rs, verify_tls12_signature, verify_tls13_signature, CryptoProvider}; @@ -79,7 +79,7 @@ pub struct RaTlsClientCertResolver { } impl RaTlsClientCertResolver { - pub fn new() -> Result { + pub fn new() -> Result { let builder = RaTlsCertificateBuilder::new().with_common_name("Client".to_string()); let cert = builder.build().map(Arc::new)?; Ok(Self { cert }) @@ -101,7 +101,7 @@ impl ResolvesClientCert for RaTlsClientCertResolver { } impl RaTlsConfigBuilder for ClientConfig { - fn from_ratls_config(config: RaTlsConfig) -> Result { + fn from_ratls_config(config: RaTlsConfig) -> Result { Ok(Self::builder() .dangerous() .with_custom_certificate_verifier(Arc::new(RaTlsServerCertVerifier::new(config))) diff --git a/src/config.rs b/src/config.rs index b7a7d7a..f23ad87 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,11 +1,11 @@ -use crate::{RaTlsConfigBuilder, RaTlsError}; +use crate::{RaTlsConfigBuilder, SgxError}; #[cfg(feature = "occlum")] use crate::quote::{Quote, STATIC_QUOTE}; -use crate::quote::{SealingKeyPolicy, Sgx128BitKey, IOCTL_CLIENT}; use rustls::{ClientConfig, ServerConfig}; +#[cfg(feature = "occlum")] pub type Measurement = [u8; 32]; #[derive(Default, Debug)] @@ -57,7 +57,7 @@ impl InstanceMeasurement { } } - pub fn with_current_mrsigner(self) -> Result { + pub fn with_current_mrsigner(self) -> Result { let quote = Self::generate_static_empty_quote()?; let mrsigner_from_quote = quote.mrsigner().into(); @@ -78,7 +78,7 @@ impl InstanceMeasurement { } } - pub fn with_current_mrenclave(self) -> Result { + pub fn with_current_mrenclave(self) -> Result { let quote = Self::generate_static_empty_quote()?; let mrenclave_from_quote = quote.mrenclave().into(); @@ -99,7 +99,7 @@ impl InstanceMeasurement { } } - pub fn with_current_measurements() -> Result { + pub fn with_current_measurements() -> Result { let quote = Self::generate_static_empty_quote()?; 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())?) } @@ -163,60 +163,22 @@ impl RaTlsConfig { } #[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 .allowed_instances .iter() .any(|im| im.check_quote_measurements(quote)) { true => Ok(()), - false => Err(RaTlsError::QuoteError(format!( - "{:?} is not allowed", - quote - ))), + false => Err(SgxError::QuoteError(format!("{:?} is not allowed", quote))), } } - pub fn into_server_config(self) -> Result { + pub fn into_server_config(self) -> Result { ServerConfig::from_ratls_config(self) } - pub fn into_client_config(self) -> Result { + pub fn into_client_config(self) -> Result { 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 { - 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 { - Ok(Self {}) - } -} diff --git a/src/error.rs b/src/error.rs index 6ef74df..527c928 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,22 +1,28 @@ use std::{error::Error, fmt::Display}; #[derive(Debug, Clone)] -pub enum RaTlsError { +pub enum SgxError { CertificateBuildError(String), QuoteError(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 { match *self { - RaTlsError::CertificateBuildError(ref message) => { + SgxError::CertificateBuildError(ref message) => { write!(f, "CertificateBuildError: {}", message) } - RaTlsError::QuoteError(ref message) => write!(f, "QuoteVerifyError: {}", message), - RaTlsError::DcapError(ref message) => write!(f, "DcapError: {}", message), + SgxError::QuoteError(ref message) => write!(f, "QuoteVerifyError: {}", 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 {} diff --git a/src/ioctl.rs b/src/ioctl.rs new file mode 100644 index 0000000..0491c72 --- /dev/null +++ b/src/ioctl.rs @@ -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, + supplemental_size: Option, +} + +// 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 { + 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 { + 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 { + 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, 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, SgxError> { + let quote_size = self.get_quote_size()?; + let mut quote_buf: Vec = 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 { + 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 { + 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 = 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); + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 6ebbf2f..3eb73a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,20 +7,30 @@ mod server; #[cfg(feature = "occlum")] mod utils; +#[cfg(feature = "occlum")] +mod ioctl; + #[cfg(feature = "occlum")] mod bindings; pub mod prelude; #[cfg(feature = "occlum")] 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::SealingConfig; +#[cfg(feature = "sealing")] +pub use crate::sealing::SgxSealing; #[cfg(feature = "occlum")] pub use crate::config::InstanceMeasurement; -pub use crate::error::RaTlsError; +pub use crate::error::SgxError; #[cfg(feature = "actix-web")] pub use crate::http::actix_web; @@ -29,5 +39,5 @@ pub use crate::http::actix_web; pub use crate::http::reqwest; pub trait RaTlsConfigBuilder { - fn from_ratls_config(config: RaTlsConfig) -> Result; + fn from_ratls_config(config: RaTlsConfig) -> Result; } diff --git a/src/prelude.rs b/src/prelude.rs index 46b8635..d448e85 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,5 +1,6 @@ pub use crate::RaTlsConfig; -pub use crate::SealingConfig; +#[cfg(feature = "sealing")] +pub use crate::SgxSealing; #[cfg(feature = "occlum")] pub use crate::config::InstanceMeasurement; diff --git a/src/quote.rs b/src/quote.rs index f696516..c35060c 100644 --- a/src/quote.rs +++ b/src/quote.rs @@ -1,63 +1,18 @@ use crate::bindings::*; -use crate::error::RaTlsError; +use crate::error::SgxError; +use crate::ioctl::SgxIoctlClient; use lazy_static::lazy_static; -use log::{trace, warn}; use std::fmt::Debug; use std::ops::Deref; 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 { buf: Vec, - report_body: *const sgx_report_body_t, + pub(crate) report_body: *const sgx_report_body_t, } impl TryFrom> for Quote { - type Error = RaTlsError; + type Error = SgxError; fn try_from(buf: Vec) -> Result { let report_body_offset = size_of::(); let report_body_size = size_of::(); @@ -65,7 +20,7 @@ impl TryFrom> for Quote { if buf.len() < report_body_offset + report_body_size { let minimal = report_body_offset + report_body_size; let actual = buf.len(); - return Err(RaTlsError::QuoteError(format!( + return Err(SgxError::QuoteError(format!( "Failed to parse DCAP quote, min {minimal}, act {actual}" ))); } @@ -88,7 +43,7 @@ struct QuoteHeader { } impl TryFrom<&[u8]> for Quote { - type Error = RaTlsError; + type Error = SgxError; fn try_from(buf: &[u8]) -> Result { buf.to_vec().try_into() @@ -96,7 +51,7 @@ impl TryFrom<&[u8]> for Quote { } impl TryFrom for Quote { - type Error = RaTlsError; + type Error = SgxError; fn try_from(value: ReportData) -> Result { Self::from_report_data(value) @@ -112,7 +67,7 @@ impl Deref for Quote { } impl Quote { - pub fn from_report_data(data: ReportData) -> Result { + pub fn from_report_data(data: ReportData) -> Result { IOCTL_CLIENT .lock() .unwrap() @@ -120,7 +75,7 @@ impl Quote { .try_into() } - pub fn from_slice(slice: &[u8]) -> Result { + pub fn from_slice(slice: &[u8]) -> Result { slice.try_into() } @@ -128,7 +83,7 @@ impl Quote { self } - pub fn verify(&self) -> Result { + pub fn verify(&self) -> Result { IOCTL_CLIENT.lock().unwrap().verify_quote(self.buf.as_ref()) } @@ -181,8 +136,8 @@ impl Debug for Quote { } lazy_static! { - pub static ref IOCTL_CLIENT: Mutex = { - let client = IoctlClient::new(); + pub static ref IOCTL_CLIENT: Mutex = { + let client = SgxIoctlClient::new(); Mutex::new(client) }; } @@ -194,200 +149,11 @@ lazy_static! { // unsafe impl Send for Quote {} lazy_static! { - pub static ref STATIC_QUOTE: Result = Quote::from_report_data([0u8; 64]); + pub static ref STATIC_QUOTE: Result = Quote::from_report_data([0u8; 64]); } unsafe impl Sync for Quote {} -pub struct IoctlClient { - fd: HandleType, - quote_size: Option, - supplemental_size: Option, -} - -// 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 { - 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 { - 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 { - 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, 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, RaTlsError> { - let quote_size = self.get_quote_size()?; - let mut quote_buf: Vec = 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 { - 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 { - 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 = 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 { - 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]; #[derive(Debug)] diff --git a/src/racert.rs b/src/racert.rs index 284fb0a..895c19f 100644 --- a/src/racert.rs +++ b/src/racert.rs @@ -2,7 +2,7 @@ use std::error::Error; #[cfg(feature = "occlum")] use crate::utils::hash_sha512; -use crate::{error::RaTlsError, RaTlsConfig}; +use crate::{error::SgxError, RaTlsConfig}; use log::error; #[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}; pub trait CertificateBuilder: Send + Sync { - fn build(&self) -> Result; + fn build(&self) -> Result; } struct RaTlsCertifiedKey { @@ -86,16 +86,16 @@ impl RaTlsCertificateBuilder { } impl CertificateBuilder for RaTlsCertificateBuilder { - fn build(&self) -> Result { + fn build(&self) -> Result { 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); err })?; 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 err = RaTlsError::CertificateBuildError(e.to_string()); + let err = SgxError::CertificateBuildError(e.to_string()); error!("{}", err); err })?; diff --git a/src/sealing.rs b/src/sealing.rs deleted file mode 100644 index 9acdf8b..0000000 --- a/src/sealing.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[cfg(feature = "occlum")] -use crate::quote::{Quote, STATIC_QUOTE}; diff --git a/src/sealing/decrypt.rs b/src/sealing/decrypt.rs new file mode 100644 index 0000000..d6cc9d7 --- /dev/null +++ b/src/sealing/decrypt.rs @@ -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) -> Result, SgxError> { + let sealing_key = self.get_aes256_sealing_key()?; + + let aes_encryption_256bit_key = Key::::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) + } +} diff --git a/src/sealing/encrypt.rs b/src/sealing/encrypt.rs new file mode 100644 index 0000000..8603b1d --- /dev/null +++ b/src/sealing/encrypt.rs @@ -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) -> Result, SgxError> { + let sealing_key = self.get_aes256_sealing_key()?; + + let aes_encryption_256bit_key = Key::::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) + } +} diff --git a/src/sealing/key_derivation.rs b/src/sealing/key_derivation.rs new file mode 100644 index 0000000..0d6aaae --- /dev/null +++ b/src/sealing/key_derivation.rs @@ -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 { + let mrsigner_for_salt = Self::get_current_sgx_quote()?.mrsigner().m; + + Ok(pbkdf2_hmac_array::( + &self.sealing_key, + &mrsigner_for_salt, + 25519, + )) + } +} diff --git a/src/sealing/mod.rs b/src/sealing/mod.rs new file mode 100644 index 0000000..87d039f --- /dev/null +++ b/src/sealing/mod.rs @@ -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; diff --git a/src/sealing/sgx_sealing.rs b/src/sealing/sgx_sealing.rs new file mode 100644 index 0000000..4d06d5a --- /dev/null +++ b/src/sealing/sgx_sealing.rs @@ -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 { + // by default, use MrEnclave key policy + Self::with_policy(SealingKeyPolicy::MrEnclave) + } + + pub fn with_policy(policy: SealingKeyPolicy) -> Result { + 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 { + 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 { + 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) + } +} diff --git a/src/server.rs b/src/server.rs index d6a5f54..5dce3eb 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,6 +1,6 @@ use crate::{ racert::{CertificateBuilder, RaTlsCertificate, RaTlsCertificateBuilder}, - RaTlsConfig, RaTlsConfigBuilder, RaTlsError, + RaTlsConfig, RaTlsConfigBuilder, SgxError, }; use rustls::client::danger::HandshakeSignatureValid; use rustls::crypto::{aws_lc_rs, verify_tls12_signature, verify_tls13_signature, CryptoProvider}; @@ -81,7 +81,7 @@ pub struct RaTlsServerCertResolver { } impl RaTlsServerCertResolver { - pub fn new() -> Result { + pub fn new() -> Result { let builder = RaTlsCertificateBuilder::new().with_common_name("Client".to_string()); let cert = builder.build().map(Arc::new)?; Ok(Self { cert }) @@ -95,7 +95,7 @@ impl ResolvesServerCert for RaTlsServerCertResolver { } impl RaTlsConfigBuilder for ServerConfig { - fn from_ratls_config(config: RaTlsConfig) -> Result { + fn from_ratls_config(config: RaTlsConfig) -> Result { Ok(Self::builder() .with_client_cert_verifier(Arc::new(RaTlsClientCertVerifier::new(config))) .with_cert_resolver(Arc::new(RaTlsServerCertResolver::new()?))) diff --git a/src/sgx_consts.rs b/src/sgx_consts.rs new file mode 100644 index 0000000..83e6b4c --- /dev/null +++ b/src/sgx_consts.rs @@ -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; diff --git a/src/sscert.rs b/src/sscert.rs deleted file mode 100644 index f5138f6..0000000 --- a/src/sscert.rs +++ /dev/null @@ -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 { -// 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 { -// Some(DistinguishedNames::new()) -// } -// } -// -// pub struct RaTlsServerCertResolver { -// cert: Arc, -// } -// -// impl RaTlsServerCertResolver { -// pub fn new() -> Result { -// 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> { -// Some(self.cert.clone()) -// } -// } -// -// impl RaTlsConfigBuilder for ServerConfig { -// fn from_ratls_config(config: RaTlsConfig) -> Result { -// Ok(Self::builder() -// .with_safe_defaults() -// .with_client_cert_verifier(Arc::new(RaTlsClientCertVerifier::new(config))) -// .with_cert_resolver(Arc::new(RaTlsServerCertResolver::new()?))) -// } -// }