From e0c4f54bc63f75932a54aaae040a272c82081954 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 6 Dec 2022 07:42:15 +0100 Subject: [PATCH 01/39] First version that manages to register a quoting enclave --- Makefile | 4 +- .../src/attestation_handler.rs | 12 +- core-primitives/enclave-api/build.rs | 1 + core-primitives/enclave-api/ffi/src/lib.rs | 7 + .../enclave-api/src/remote_attestation.rs | 160 +++++++++++++++++- .../node-api/metadata/src/metadata_mocks.rs | 8 + .../node-api/metadata/src/pallet_teerex.rs | 12 ++ enclave-runtime/Cargo.toml | 1 + enclave-runtime/Enclave.edl | 4 + enclave-runtime/src/attestation.rs | 112 +++++++++++- service/build.rs | 1 + service/src/main.rs | 26 ++- 12 files changed, 332 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 3679f66dc2..e39dce0633 100755 --- a/Makefile +++ b/Makefile @@ -77,12 +77,12 @@ ifeq ($(SGX_PRODUCTION), 1) SGX_ENCLAVE_MODE = "Production Mode" SGX_ENCLAVE_CONFIG = "enclave-runtime/Enclave.config.production.xml" SGX_SIGN_KEY = $(SGX_COMMERCIAL_KEY) - WORKER_FEATURES = --features=production,$(WORKER_MODE),$(ADDITIONAL_FEATURES) + WORKER_FEATURES = --features=production,dcap,$(WORKER_MODE),$(ADDITIONAL_FEATURES) else SGX_ENCLAVE_MODE = "Development Mode" SGX_ENCLAVE_CONFIG = "enclave-runtime/Enclave.config.xml" SGX_SIGN_KEY = "enclave-runtime/Enclave_private.pem" - WORKER_FEATURES = --features=default,$(WORKER_MODE),$(ADDITIONAL_FEATURES) + WORKER_FEATURES = --features=default,dcap,$(WORKER_MODE),$(ADDITIONAL_FEATURES) endif CLIENT_FEATURES = --features=$(WORKER_MODE),$(ADDITIONAL_FEATURES) diff --git a/core-primitives/attestation-handler/src/attestation_handler.rs b/core-primitives/attestation-handler/src/attestation_handler.rs index 8bb00fc20d..9c44a4da0e 100644 --- a/core-primitives/attestation-handler/src/attestation_handler.rs +++ b/core-primitives/attestation-handler/src/attestation_handler.rs @@ -254,7 +254,7 @@ where let (prv_k, pub_k) = ecc_handle.create_key_pair()?; info!("Enclave Attestation] Generated ephemeral ECDSA keypair:"); - let payload = if !skip_ra { + let qe_quote = if !skip_ra { let qe_quote = match self.retrieve_qe_dcap_quote( &chain_signer.public().0, quoting_enclave_target_info, @@ -267,24 +267,26 @@ where }, }; // Verify the quote via qve enclave - self.ecdsa_quote_verification(qe_quote)? + //self.ecdsa_quote_verification(qe_quote)? + qe_quote } else { Default::default() }; // generate an ECC certificate debug!("[Enclave] Generate ECC Certificate"); - let (key_der, cert_der) = match cert::gen_ecc_cert(&payload, &prv_k, &pub_k, &ecc_handle) { + /*let (key_der, cert_der) = match cert::gen_ecc_cert(&payload, &prv_k, &pub_k, &ecc_handle) { Ok(r) => r, Err(e) => { error!("[Enclave] gen_ecc_cert failed: {:?}", e); return Err(e.into()) }, - }; + };*/ let _ = ecc_handle.close(); - Ok((key_der, cert_der)) + //Ok((key_der, cert_der)) + Ok((vec![], qe_quote)) } } diff --git a/core-primitives/enclave-api/build.rs b/core-primitives/enclave-api/build.rs index 5b181fe3d2..1c20ea4c84 100644 --- a/core-primitives/enclave-api/build.rs +++ b/core-primitives/enclave-api/build.rs @@ -20,4 +20,5 @@ fn main() { // ln -s libsgx_dcap_ql.so.1 libsgx_dcap_ql.so println!("cargo:rustc-link-lib=dylib=sgx_dcap_ql"); println!("cargo:rustc-link-lib=dylib=sgx_dcap_quoteverify"); + println!("cargo:rustc-link-lib=dylib=dcap_quoteprov"); } diff --git a/core-primitives/enclave-api/ffi/src/lib.rs b/core-primitives/enclave-api/ffi/src/lib.rs index d8dc4d66c2..bd4b38e7b7 100644 --- a/core-primitives/enclave-api/ffi/src/lib.rs +++ b/core-primitives/enclave-api/ffi/src/lib.rs @@ -112,6 +112,13 @@ extern "C" { quote_size: u32, ) -> sgx_status_t; + pub fn generate_qe_extrinsic( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_size: u32, + ) -> sgx_status_t; + pub fn dump_ias_ra_cert_to_disk( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index 5005c570a1..8e4c9523d5 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -23,7 +23,9 @@ use itp_enclave_api_ffi as ffi; use itp_settings::worker::EXTRINSIC_MAX_SIZE; use itp_types::ShardIdentifier; use log::*; +use serde_json::Value; use sgx_types::*; +use std::io::prelude::*; const OS_SYSTEM_PATH: &str = "/usr/lib/x86_64-linux-gnu/"; const C_STRING_ENDING: &str = "\0"; @@ -47,10 +49,18 @@ pub trait RemoteAttestation { fn generate_dcap_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult>; + fn generate_qe_extrinsic(&self) -> EnclaveResult>; + fn dump_ias_ra_cert_to_disk(&self) -> EnclaveResult<()>; fn dump_dcap_ra_cert_to_disk(&self) -> EnclaveResult<()>; + fn get_collateral(&self, fmspc: [u8; 6]) -> EnclaveResult; + + fn get_tcb_info(&self, fmspc: [u8; 6]) -> EnclaveResult<(String, String)>; + + fn dump_dcap_collateral_to_disk(&self, fmspc: [u8; 6]) -> EnclaveResult<()>; + fn set_ql_qe_enclave_paths(&self) -> EnclaveResult<()>; fn qe_get_target_info(&self) -> EnclaveResult; @@ -110,6 +120,98 @@ pub trait TlsRemoteAttestation { ) -> EnclaveResult<()>; } +// This is a rust-ified version of the type sgx_ql_qve_collateral_t +pub struct SgxQlQveCollateral { + pub version: u32, // version = 1. PCK Cert chain is in the Quote. + /* intel DCAP 1.13 */ + pub tee_type: u32, // 0x00000000: SGX or 0x00000081: TDX + pub pck_crl_issuer_chain: Vec, + pub root_ca_crl: Vec, + pub pck_crl: Vec, + pub tcb_info_issuer_chain: Vec, + pub tcb_info: Vec, + pub qe_identity_issuer_chain: Vec, + pub qe_identity: Vec, +} + +impl SgxQlQveCollateral { + unsafe fn from_c_version(q: &sgx_ql_qve_collateral_t) -> Self { + let pck_crl_issuer_chain = std::slice::from_raw_parts( + q.pck_crl_issuer_chain as *const u8, + q.pck_crl_issuer_chain_size as usize, + ) + .to_vec(); + let root_ca_crl = + std::slice::from_raw_parts(q.root_ca_crl as *const u8, q.root_ca_crl_size as usize) + .to_vec(); + let pck_crl = + std::slice::from_raw_parts(q.pck_crl as *const u8, q.pck_crl_size as usize).to_vec(); + let tcb_info_issuer_chain = std::slice::from_raw_parts( + q.tcb_info_issuer_chain as *const u8, + q.tcb_info_issuer_chain_size as usize, + ) + .to_vec(); + let tcb_info = + std::slice::from_raw_parts(q.tcb_info as *const u8, q.tcb_info_size as usize).to_vec(); + let qe_identity_issuer_chain = std::slice::from_raw_parts( + q.qe_identity_issuer_chain as *const u8, + q.qe_identity_issuer_chain_size as usize, + ) + .to_vec(); + let qe_identity = + std::slice::from_raw_parts(q.qe_identity as *const u8, q.qe_identity_size as usize) + .to_vec(); + SgxQlQveCollateral { + version: q.version, + tee_type: q.tee_type, + pck_crl_issuer_chain, + root_ca_crl, + pck_crl, + tcb_info_issuer_chain, + tcb_info, + qe_identity_issuer_chain, + qe_identity, + } + } + + fn dump_to_disk(&self) { + Self::write_data_to_disk("pck_crl_issuer_chain", &self.pck_crl_issuer_chain); + Self::write_data_to_disk("root_ca_crl", &self.root_ca_crl); + Self::write_data_to_disk("pck_crl", &self.pck_crl); + Self::write_data_to_disk("tcb_info_issuer_chain", &self.tcb_info_issuer_chain); + Self::write_data_to_disk("tcb_info", &self.tcb_info); + Self::write_data_to_disk("qe_identity_issuer_chain", &self.qe_identity_issuer_chain); + Self::write_data_to_disk("qe_identity", &self.qe_identity); + } + + /// Returns the tcb_info split into two parts: tcb_info and signature + fn get_tcb_info_split(&self) -> Option<(String, String)> { + Self::separate_json_data_and_signature("enclaveIdentity", &self.qe_identity) + } + + /// Separates the actual data part from the signature for an Intel collateral in JSON format + /// Returns the data part and signature as a pair + fn separate_json_data_and_signature(data_name: &str, data: &[u8]) -> Option<(String, String)> { + let json = String::from_utf8_lossy(data); + // search pattern is something like `{"tcbInfo":`. Should be at the very beginning + let search_pattern = format!("{{\"{}\":", data_name); + let json = json.replace(&search_pattern, ""); + + let parts = json.split(r#","signature":""#).collect::>(); + if parts.len() != 2 || parts[1].len() < 2 { + return None + } + let data = &parts[0]; + let signature = &parts[1][0..parts[1].len() - 2]; // Remove the two last chars that 'close' the json + Some((data.to_string(), signature.to_string())) + } + + fn write_data_to_disk(filename: &str, contents: &[u8]) { + let mut file = std::fs::File::create(filename).unwrap(); + file.write_all(contents).unwrap(); + } +} + impl RemoteAttestation for Enclave { fn generate_ias_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult> { let mut retval = sgx_status_t::SGX_SUCCESS; @@ -168,6 +270,26 @@ impl RemoteAttestation for Enclave { Ok(unchecked_extrinsic) } + fn generate_qe_extrinsic(&self) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + + let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; + + let result = unsafe { + ffi::generate_qe_extrinsic( + self.eid, + &mut retval, + unchecked_extrinsic.as_mut_ptr(), + unchecked_extrinsic.len() as u32, + ) + }; + + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(unchecked_extrinsic) + } + fn dump_ias_ra_cert_to_disk(&self) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; @@ -229,6 +351,43 @@ impl RemoteAttestation for Enclave { Ok(quote_size) } + + fn get_tcb_info(&self, fmspc: [u8; 6]) -> EnclaveResult<(String, String)> { + let collateral = self.get_collateral(fmspc)?; + Ok(collateral.get_tcb_info_split().unwrap()) + } + + fn get_collateral(&self, fmspc: [u8; 6]) -> EnclaveResult { + let pck_ra = b"processor\x00"; + unsafe { + let mut collateral_prt: *mut sgx_ql_qve_collateral_t = std::mem::zeroed(); + let collateral_prt_ptr: *mut *mut sgx_ql_qve_collateral_t = &mut collateral_prt; + let sgx_status = sgx_ql_get_quote_verification_collateral( + fmspc.as_ptr(), + fmspc.len() as uint16_t, //fmspc len is fixed in the function signature + pck_ra.as_ptr() as _, + collateral_prt_ptr, + ); + + println!("SGX status: {}", sgx_status); + ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); + + println!("Collateral size: {}", std::mem::size_of::()); + let quote_collateral = &(**collateral_prt_ptr); + let collateral = SgxQlQveCollateral::from_c_version(quote_collateral); + let sgx_status = sgx_ql_free_quote_verification_collateral(quote_collateral); + println!("SGX status: {}", sgx_status); + Ok(collateral) + } + } + + fn dump_dcap_collateral_to_disk(&self, fmspc: [u8; 6]) -> EnclaveResult<()> { + let collateral = self.get_collateral(fmspc)?; + collateral.dump_to_disk(); + println!("Collateral version: {}", collateral.version); + + Ok(()) + } } impl RemoteAttestationCallBacks for Enclave { @@ -299,7 +458,6 @@ impl RemoteAttestationCallBacks for Enclave { fn get_dcap_quote(&self, report: sgx_report_t, quote_size: u32) -> EnclaveResult> { let mut quote_vec: Vec = vec![0; quote_size as usize]; - let qe3_ret = unsafe { sgx_qe_get_quote(&report, quote_size, quote_vec.as_mut_ptr() as _) }; ensure!(qe3_ret == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(qe3_ret)); diff --git a/core-primitives/node-api/metadata/src/metadata_mocks.rs b/core-primitives/node-api/metadata/src/metadata_mocks.rs index 7fe6d4245b..909de8fa3c 100644 --- a/core-primitives/node-api/metadata/src/metadata_mocks.rs +++ b/core-primitives/node-api/metadata/src/metadata_mocks.rs @@ -58,6 +58,14 @@ impl TeerexCallIndexes for NodeMetadataMock { Ok([self.teerex_module, self.register_enclave]) } + fn register_dcap_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.register_enclave]) + } + + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.register_enclave]) + } + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]> { Ok([self.teerex_module, self.unregister_enclave]) } diff --git a/core-primitives/node-api/metadata/src/pallet_teerex.rs b/core-primitives/node-api/metadata/src/pallet_teerex.rs index 0dfad40691..37d54e968a 100644 --- a/core-primitives/node-api/metadata/src/pallet_teerex.rs +++ b/core-primitives/node-api/metadata/src/pallet_teerex.rs @@ -23,6 +23,10 @@ const TEEREX: &str = "Teerex"; pub trait TeerexCallIndexes { fn register_enclave_call_indexes(&self) -> Result<[u8; 2]>; + fn register_dcap_enclave_call_indexes(&self) -> Result<[u8; 2]>; + + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]>; + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]>; fn call_worker_call_indexes(&self) -> Result<[u8; 2]>; @@ -45,6 +49,14 @@ impl TeerexCallIndexes for NodeMetadata { self.call_indexes(TEEREX, "register_enclave") } + fn register_dcap_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "register_dcap_enclave") + } + + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "register_quoting_enclave") + } + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]> { self.call_indexes(TEEREX, "unregister_enclave") } diff --git a/enclave-runtime/Cargo.toml b/enclave-runtime/Cargo.toml index 5a6efcb0a9..1228b5ab17 100644 --- a/enclave-runtime/Cargo.toml +++ b/enclave-runtime/Cargo.toml @@ -62,6 +62,7 @@ sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-s [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } derive_more = { version = "0.99.5" } +hex-literal = { version = "0.3.2" } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } ipfs-unixfs = { default-features = false, git = "https://github.com/whalelephant/rust-ipfs", branch = "w-nstd" } lazy_static = { version = "1.1.0", features = ["spin_no_std"] } diff --git a/enclave-runtime/Enclave.edl b/enclave-runtime/Enclave.edl index 6808ff284d..d39e722140 100644 --- a/enclave-runtime/Enclave.edl +++ b/enclave-runtime/Enclave.edl @@ -97,6 +97,10 @@ enclave { uint32_t quote_size ); + public sgx_status_t generate_qe_extrinsic( + [out, size=unchecked_extrinsic_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_size + ); + public sgx_status_t update_market_data_xt( [in, size=crypto_currency_size] uint8_t* crypto_currency, uint32_t crypto_currency_size, [in, size=fiat_currency_size] uint8_t* fiat_currency, uint32_t fiat_currency_size, diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index f24c6063a5..8687159d0b 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -36,6 +36,7 @@ use crate::{ Error as EnclaveError, Result as EnclaveResult, }; use codec::{Decode, Encode}; +use hex_literal::hex; use itp_attestation_handler::AttestationHandler; use itp_component_container::ComponentGetter; use itp_extrinsics_factory::CreateExtrinsics; @@ -127,16 +128,61 @@ pub unsafe extern "C" fn generate_ias_ra_extrinsic( sgx_status_t::SGX_SUCCESS } +pub fn get_quoting_enclave_data() -> (Vec, Vec, Vec) { + let data = br#"{"id":"QE","version":2,"issueDate":"2022-11-17T14:34:49Z","nextUpdate":"2023-04-16T14:34:49Z","tcbEvaluationDataNumber":12,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":6},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00477"]},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00202","INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]}]}"#; + let signature = hex!("a9456c69e5878ee2f689b3d449bc961add61a6b80d30804a5510dbd2813d6c748ee8562a02de8d02b1528e83d9740e34736495512eff4a45db11c42002a4c8cf"); + let certs = br#"-----BEGIN CERTIFICATE----- +MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG +A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw +b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD +VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv +P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju +ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f +BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz +LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK +QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG +SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj +ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE-----"#; + (data.to_vec(), signature.to_vec(), certs.to_vec()) +} + #[no_mangle] pub unsafe extern "C" fn generate_dcap_ra_extrinsic( - _w_url: *const u8, - _w_url_size: u32, - _unchecked_extrinsic: *mut u8, - _unchecked_extrinsic_size: u32, - _skip_ra: c_int, + w_url: *const u8, + w_url_size: u32, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_size: u32, + skip_ra: c_int, quoting_enclave_target_info: &sgx_target_info_t, quote_size: u32, ) -> sgx_status_t { + if w_url.is_null() || unchecked_extrinsic.is_null() { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let mut url_slice = slice::from_raw_parts(w_url, w_url_size as usize); + let url = String::decode(&mut url_slice).expect("Could not decode url slice to a valid String"); + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { Ok(r) => r, Err(e) => { @@ -145,15 +191,30 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic( }, }; - let (_key_der, _cert_der) = match attestation_handler.generate_dcap_ra_cert( + let (_key_der, cert_der) = match attestation_handler.generate_dcap_ra_cert( quoting_enclave_target_info, quote_size, - false, + skip_ra == 1, ) { Ok(r) => r, Err(e) => return e.into(), }; // TODO Need to send this to the teerex pallet (something similar to perform_ra_internal) + let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain().unwrap(); + let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); + + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.register_dcap_enclave_call_indexes()) + .unwrap() + .map_err(MetadataProviderError::MetadataError) + .unwrap(); + info!(" [Enclave] Compose register enclave call DCAP IDS: {:?}", call_ids); + let call = OpaqueCall::from_tuple(&(call_ids, cert_der, url)); + + let extrinsic = extrinsics_factory.create_extrinsics(&[call], None).unwrap()[0].clone(); + if let Err(e) = write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { + return EnclaveError::Other(Box::new(e)).into() + }; sgx_status_t::SGX_SUCCESS } @@ -179,6 +240,43 @@ fn generate_ias_ra_extrinsic_internal( Ok(extrinsics[0].clone()) } +#[no_mangle] +pub unsafe extern "C" fn generate_qe_extrinsic( + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_size: u32, +) -> sgx_status_t { + if unchecked_extrinsic.is_null() { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); + let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { + Ok(r) => r, + Err(e) => { + error!("Component get failure: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + let (data, signature, certs) = get_quoting_enclave_data(); + + let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain().unwrap(); + let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); + + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.register_quoting_enclave_call_indexes()) + .unwrap() + .map_err(MetadataProviderError::MetadataError) + .unwrap(); + info!(" [Enclave] Compose register quoting enclave call: {:?}", call_ids); + let call = OpaqueCall::from_tuple(&(call_ids, data, signature, certs)); + + let extrinsic = extrinsics_factory.create_extrinsics(&[call], None).unwrap()[0].clone(); + if let Err(e) = write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { + return EnclaveError::Other(Box::new(e)).into() + }; + sgx_status_t::SGX_SUCCESS +} + #[no_mangle] pub extern "C" fn dump_ias_ra_cert_to_disk() -> sgx_status_t { let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { diff --git a/service/build.rs b/service/build.rs index 01874c908e..8f18978c62 100644 --- a/service/build.rs +++ b/service/build.rs @@ -46,6 +46,7 @@ fn main() { // ln -s libsgx_dcap_ql.so.1 libsgx_dcap_ql.so println!("cargo:rustc-link-lib=dylib=sgx_dcap_ql"); println!("cargo:rustc-link-lib=dylib=sgx_dcap_quoteverify"); + println!("cargo:rustc-link-lib=dylib=dcap_quoteprov"); match is_sim.as_ref() { "SW" => { println!("cargo:rustc-link-lib=dylib=sgx_urts_sim"); diff --git a/service/src/main.rs b/service/src/main.rs index 5decc203cb..e31bc16f26 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -222,7 +222,11 @@ fn main() { #[cfg(not(feature = "dcap"))] enclave.dump_ias_ra_cert_to_disk().unwrap(); #[cfg(feature = "dcap")] - enclave.dump_dcap_ra_cert_to_disk().unwrap(); + { + let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; + enclave.dump_dcap_collateral_to_disk(fmspc).unwrap(); + enclave.dump_dcap_ra_cert_to_disk().unwrap(); + } } else if matches.is_present("mrenclave") { println!("{}", enclave.get_mrenclave().unwrap().encode().to_base58()); } else if let Some(sub_matches) = matches.subcommand_matches("init-shard") { @@ -415,6 +419,26 @@ fn start_worker( ) .expect("Could not set the node metadata in the enclave"); + { + let uxt = enclave.generate_qe_extrinsic().unwrap(); + + let mut xthex = hex::encode(uxt); + xthex.insert_str(0, "0x"); + + // Account funds + if let Err(x) = + setup_account_funding(&node_api, &tee_accountid, xthex.clone(), is_development_mode) + { + error!("Starting worker failed: {:?}", x); + // Return without registering the enclave. This will fail and the transaction will be banned for 30min. + return + } + + println!("[>] Register the quoting enclave (send the extrinsic)"); + let register_qe_xt_hash = node_api.send_extrinsic(xthex, XtStatus::Finalized).unwrap(); + println!("[<] Extrinsic got finalized. Hash: {:?}\n", register_qe_xt_hash); + } + // ------------------------------------------------------------------------ // Perform a remote attestation and get an unchecked extrinsic back. let trusted_url = config.trusted_worker_url_external(); From f48cde3f6ff140b29fd2c1548ffa2a3b4293cdda Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 6 Dec 2022 09:04:55 +0100 Subject: [PATCH 02/39] Move collateral to attestation-handler --- .../attestation-handler/Cargo.toml | 1 + .../src/attestation_handler.rs | 41 +++++++++++++++++++ .../enclave-api/src/remote_attestation.rs | 1 - enclave-runtime/Cargo.toml | 1 - enclave-runtime/src/attestation.rs | 41 +------------------ 5 files changed, 43 insertions(+), 42 deletions(-) diff --git a/core-primitives/attestation-handler/Cargo.toml b/core-primitives/attestation-handler/Cargo.toml index f5d474f3b4..5deff25a11 100644 --- a/core-primitives/attestation-handler/Cargo.toml +++ b/core-primitives/attestation-handler/Cargo.toml @@ -10,6 +10,7 @@ arrayvec = { version = "0.7.1", default-features = false } bit-vec = { version = "0.6", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } +hex-literal = { version = "0.3.2" } itertools = { default-features = false, version = "0.10.1" } log = { version = "0.4", default-features = false } diff --git a/core-primitives/attestation-handler/src/attestation_handler.rs b/core-primitives/attestation-handler/src/attestation_handler.rs index 9c44a4da0e..0c156b58d2 100644 --- a/core-primitives/attestation-handler/src/attestation_handler.rs +++ b/core-primitives/attestation-handler/src/attestation_handler.rs @@ -33,6 +33,7 @@ use crate::sgx_reexport_prelude::*; use crate::{cert, Error as EnclaveError, Error, Result as EnclaveResult}; use codec::Encode; use core::{convert::TryInto, default::Default}; +use hex_literal::hex; use itertools::Itertools; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_settings::{ @@ -90,6 +91,8 @@ pub trait AttestationHandler { skip_ra: bool, ) -> EnclaveResult<(Vec, Vec)>; + fn get_quoting_enclave_collateral(&self) -> (Vec, Vec, Vec); + /// Get the measurement register value of the enclave fn get_mrenclave(&self) -> EnclaveResult<[u8; MR_ENCLAVE_SIZE]>; @@ -288,6 +291,44 @@ where //Ok((key_der, cert_der)) Ok((vec![], qe_quote)) } + + fn get_quoting_enclave_collateral(&self) -> (Vec, Vec, Vec) { + let data = br#"{"id":"QE","version":2,"issueDate":"2022-11-17T14:34:49Z","nextUpdate":"2023-04-16T14:34:49Z","tcbEvaluationDataNumber":12,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":6},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00477"]},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00202","INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]}]}"#; + let signature = hex!("a9456c69e5878ee2f689b3d449bc961add61a6b80d30804a5510dbd2813d6c748ee8562a02de8d02b1528e83d9740e34736495512eff4a45db11c42002a4c8cf"); + let certs = br#"-----BEGIN CERTIFICATE----- +MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG +A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw +b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD +VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv +P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju +ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f +BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz +LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK +QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG +SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj +ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw +aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv +cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ +BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG +A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 +aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT +AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 +1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB +uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ +MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 +ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV +Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI +KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg +AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= +-----END CERTIFICATE-----"#; + (data.to_vec(), signature.to_vec(), certs.to_vec()) + } } impl IntelAttestationHandler diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index 8e4c9523d5..34d481057e 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -23,7 +23,6 @@ use itp_enclave_api_ffi as ffi; use itp_settings::worker::EXTRINSIC_MAX_SIZE; use itp_types::ShardIdentifier; use log::*; -use serde_json::Value; use sgx_types::*; use std::io::prelude::*; diff --git a/enclave-runtime/Cargo.toml b/enclave-runtime/Cargo.toml index 1228b5ab17..5a6efcb0a9 100644 --- a/enclave-runtime/Cargo.toml +++ b/enclave-runtime/Cargo.toml @@ -62,7 +62,6 @@ sgx_types = { branch = "master", git = "https://github.com/apache/teaclave-sgx-s [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } derive_more = { version = "0.99.5" } -hex-literal = { version = "0.3.2" } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } ipfs-unixfs = { default-features = false, git = "https://github.com/whalelephant/rust-ipfs", branch = "w-nstd" } lazy_static = { version = "1.1.0", features = ["spin_no_std"] } diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index 8687159d0b..c32593b914 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -36,7 +36,6 @@ use crate::{ Error as EnclaveError, Result as EnclaveResult, }; use codec::{Decode, Encode}; -use hex_literal::hex; use itp_attestation_handler::AttestationHandler; use itp_component_container::ComponentGetter; use itp_extrinsics_factory::CreateExtrinsics; @@ -128,44 +127,6 @@ pub unsafe extern "C" fn generate_ias_ra_extrinsic( sgx_status_t::SGX_SUCCESS } -pub fn get_quoting_enclave_data() -> (Vec, Vec, Vec) { - let data = br#"{"id":"QE","version":2,"issueDate":"2022-11-17T14:34:49Z","nextUpdate":"2023-04-16T14:34:49Z","tcbEvaluationDataNumber":12,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":6},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00477"]},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00202","INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]}]}"#; - let signature = hex!("a9456c69e5878ee2f689b3d449bc961add61a6b80d30804a5510dbd2813d6c748ee8562a02de8d02b1528e83d9740e34736495512eff4a45db11c42002a4c8cf"); - let certs = br#"-----BEGIN CERTIFICATE----- -MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw -aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv -cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ -BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG -A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw -b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD -VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv -P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju -ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f -BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz -LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK -QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG -SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj -ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw -aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv -cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ -BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG -A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 -aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT -AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 -1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB -uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ -MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 -ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV -Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI -KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg -AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= ------END CERTIFICATE-----"#; - (data.to_vec(), signature.to_vec(), certs.to_vec()) -} - #[no_mangle] pub unsafe extern "C" fn generate_dcap_ra_extrinsic( w_url: *const u8, @@ -257,7 +218,7 @@ pub unsafe extern "C" fn generate_qe_extrinsic( return sgx_status_t::SGX_ERROR_UNEXPECTED }, }; - let (data, signature, certs) = get_quoting_enclave_data(); + let (data, signature, certs) = attestation_handler.get_quoting_enclave_collateral(); let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain().unwrap(); let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); From 072aeeb901d0d1ec088a905ff09d6314efed679e Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 6 Dec 2022 11:19:29 +0100 Subject: [PATCH 03/39] Work on collateral handling --- Cargo.lock | 1 + core-primitives/enclave-api/ffi/src/lib.rs | 6 ++++- .../enclave-api/src/remote_attestation.rs | 24 ++++++++++++++++--- enclave-runtime/Enclave.edl | 1 + enclave-runtime/src/attestation.rs | 1 + service/src/main.rs | 3 ++- 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b53c02f3fe..e12e09b4f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3132,6 +3132,7 @@ dependencies = [ "chrono 0.4.11", "chrono 0.4.23", "hex", + "hex-literal", "httparse 1.4.1", "itertools", "itp-ocall-api", diff --git a/core-primitives/enclave-api/ffi/src/lib.rs b/core-primitives/enclave-api/ffi/src/lib.rs index bd4b38e7b7..0a9beca341 100644 --- a/core-primitives/enclave-api/ffi/src/lib.rs +++ b/core-primitives/enclave-api/ffi/src/lib.rs @@ -1,6 +1,9 @@ ///! FFI's that call into the enclave. These functions need to be added to the /// enclave edl file and be implemented within the enclave. -use sgx_types::{c_int, sgx_enclave_id_t, sgx_quote_sign_type_t, sgx_status_t, sgx_target_info_t}; +use sgx_types::{ + c_int, sgx_enclave_id_t, sgx_ql_qve_collateral_t, sgx_quote_sign_type_t, sgx_status_t, + sgx_target_info_t, +}; extern "C" { @@ -115,6 +118,7 @@ extern "C" { pub fn generate_qe_extrinsic( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, + collateral: *const sgx_ql_qve_collateral_t, unchecked_extrinsic: *mut u8, unchecked_extrinsic_size: u32, ) -> sgx_status_t; diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index 34d481057e..b68255ac9f 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -48,7 +48,7 @@ pub trait RemoteAttestation { fn generate_dcap_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult>; - fn generate_qe_extrinsic(&self) -> EnclaveResult>; + fn generate_qe_extrinsic(&self, fmspc: [u8; 6]) -> EnclaveResult>; fn dump_ias_ra_cert_to_disk(&self) -> EnclaveResult<()>; @@ -269,20 +269,38 @@ impl RemoteAttestation for Enclave { Ok(unchecked_extrinsic) } - fn generate_qe_extrinsic(&self) -> EnclaveResult> { + fn generate_qe_extrinsic(&self, fmspc: [u8; 6]) -> EnclaveResult> { let mut retval = sgx_status_t::SGX_SUCCESS; - let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; + let pck_ra = b"processor\x00"; + let collateral_ptr = unsafe { + let mut collateral_ptr: *mut sgx_ql_qve_collateral_t = std::mem::zeroed(); + let collateral_ptr_ptr: *mut *mut sgx_ql_qve_collateral_t = &mut collateral_ptr; + let sgx_status = sgx_ql_get_quote_verification_collateral( + fmspc.as_ptr(), + fmspc.len() as uint16_t, //fmspc len is fixed in the function signature + pck_ra.as_ptr() as _, + collateral_ptr_ptr, + ); + ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); + collateral_ptr + }; + let result = unsafe { ffi::generate_qe_extrinsic( self.eid, &mut retval, + collateral_ptr, unchecked_extrinsic.as_mut_ptr(), unchecked_extrinsic.len() as u32, ) }; + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + let sgx_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; + println!("SGX status: {}", sgx_status); ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); diff --git a/enclave-runtime/Enclave.edl b/enclave-runtime/Enclave.edl index d39e722140..e17225b7e0 100644 --- a/enclave-runtime/Enclave.edl +++ b/enclave-runtime/Enclave.edl @@ -98,6 +98,7 @@ enclave { ); public sgx_status_t generate_qe_extrinsic( + [in] const sgx_ql_qve_collateral_t *p_quote_collateral, [out, size=unchecked_extrinsic_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_size ); diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index c32593b914..9b4abaa982 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -203,6 +203,7 @@ fn generate_ias_ra_extrinsic_internal( #[no_mangle] pub unsafe extern "C" fn generate_qe_extrinsic( + collateral: *const sgx_ql_qve_collateral_t, unchecked_extrinsic: *mut u8, unchecked_extrinsic_size: u32, ) -> sgx_status_t { diff --git a/service/src/main.rs b/service/src/main.rs index e31bc16f26..b257c0125e 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -420,7 +420,8 @@ fn start_worker( .expect("Could not set the node metadata in the enclave"); { - let uxt = enclave.generate_qe_extrinsic().unwrap(); + let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; + let uxt = enclave.generate_qe_extrinsic(fmspc).unwrap(); let mut xthex = hex::encode(uxt); xthex.insert_str(0, "0x"); From 6130fb822a288be23b946d25193143cd4c86942d Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 6 Dec 2022 15:48:00 +0100 Subject: [PATCH 04/39] Use the real collateral data for quoting enclave --- .../src/attestation_handler.rs | 42 +---- .../attestation-handler/src/collateral.rs | 131 ++++++++++++++ .../attestation-handler/src/lib.rs | 3 + core-primitives/enclave-api/ffi/src/lib.rs | 3 + .../enclave-api/src/remote_attestation.rs | 160 +++--------------- enclave-runtime/Enclave.edl | 2 + enclave-runtime/src/attestation.rs | 26 ++- 7 files changed, 183 insertions(+), 184 deletions(-) create mode 100644 core-primitives/attestation-handler/src/collateral.rs diff --git a/core-primitives/attestation-handler/src/attestation_handler.rs b/core-primitives/attestation-handler/src/attestation_handler.rs index 0c156b58d2..155074bd13 100644 --- a/core-primitives/attestation-handler/src/attestation_handler.rs +++ b/core-primitives/attestation-handler/src/attestation_handler.rs @@ -30,7 +30,7 @@ #[cfg(all(not(feature = "std"), feature = "sgx"))] use crate::sgx_reexport_prelude::*; -use crate::{cert, Error as EnclaveError, Error, Result as EnclaveResult}; +use crate::{cert, Error as EnclaveError, Error, Result as EnclaveResult, SgxQlQveCollateral}; use codec::Encode; use core::{convert::TryInto, default::Default}; use hex_literal::hex; @@ -91,8 +91,6 @@ pub trait AttestationHandler { skip_ra: bool, ) -> EnclaveResult<(Vec, Vec)>; - fn get_quoting_enclave_collateral(&self) -> (Vec, Vec, Vec); - /// Get the measurement register value of the enclave fn get_mrenclave(&self) -> EnclaveResult<[u8; MR_ENCLAVE_SIZE]>; @@ -291,44 +289,6 @@ where //Ok((key_der, cert_der)) Ok((vec![], qe_quote)) } - - fn get_quoting_enclave_collateral(&self) -> (Vec, Vec, Vec) { - let data = br#"{"id":"QE","version":2,"issueDate":"2022-11-17T14:34:49Z","nextUpdate":"2023-04-16T14:34:49Z","tcbEvaluationDataNumber":12,"miscselect":"00000000","miscselectMask":"FFFFFFFF","attributes":"11000000000000000000000000000000","attributesMask":"FBFFFFFFFFFFFFFF0000000000000000","mrsigner":"8C4F5775D796503E96137F77C68A829A0056AC8DED70140B081B094490C57BFF","isvprodid":1,"tcbLevels":[{"tcb":{"isvsvn":6},"tcbDate":"2021-11-10T00:00:00Z","tcbStatus":"UpToDate"},{"tcb":{"isvsvn":5},"tcbDate":"2020-11-11T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00477"]},{"tcb":{"isvsvn":4},"tcbDate":"2019-11-13T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":2},"tcbDate":"2019-05-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]},{"tcb":{"isvsvn":1},"tcbDate":"2018-08-15T00:00:00Z","tcbStatus":"OutOfDate","advisoryIDs":["INTEL-SA-00202","INTEL-SA-00219","INTEL-SA-00293","INTEL-SA-00334","INTEL-SA-00477"]}]}"#; - let signature = hex!("a9456c69e5878ee2f689b3d449bc961add61a6b80d30804a5510dbd2813d6c748ee8562a02de8d02b1528e83d9740e34736495512eff4a45db11c42002a4c8cf"); - let certs = br#"-----BEGIN CERTIFICATE----- -MIICizCCAjKgAwIBAgIUfjiC1ftVKUpASY5FhAPpFJG99FUwCgYIKoZIzj0EAwIw -aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv -cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ -BgNVBAYTAlVTMB4XDTE4MDUyMTEwNTAxMFoXDTI1MDUyMTEwNTAxMFowbDEeMBwG -A1UEAwwVSW50ZWwgU0dYIFRDQiBTaWduaW5nMRowGAYDVQQKDBFJbnRlbCBDb3Jw -b3JhdGlvbjEUMBIGA1UEBwwLU2FudGEgQ2xhcmExCzAJBgNVBAgMAkNBMQswCQYD -VQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABENFG8xzydWRfK92bmGv -P+mAh91PEyV7Jh6FGJd5ndE9aBH7R3E4A7ubrlh/zN3C4xvpoouGlirMba+W2lju -ypajgbUwgbIwHwYDVR0jBBgwFoAUImUM1lqdNInzg7SVUr9QGzknBqwwUgYDVR0f -BEswSTBHoEWgQ4ZBaHR0cHM6Ly9jZXJ0aWZpY2F0ZXMudHJ1c3RlZHNlcnZpY2Vz -LmludGVsLmNvbS9JbnRlbFNHWFJvb3RDQS5kZXIwHQYDVR0OBBYEFH44gtX7VSlK -QEmORYQD6RSRvfRVMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMAoGCCqG -SM49BAMCA0cAMEQCIB9C8wOAN/ImxDtGACV246KcqjagZOR0kyctyBrsGGJVAiAj -ftbrNGsGU8YH211dRiYNoPPu19Zp/ze8JmhujB0oBw== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw -aDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv -cnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ -BgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG -A1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0 -aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT -AlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7 -1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB -uzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ -MEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50 -ZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV -Ur9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI -KoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg -AiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI= ------END CERTIFICATE-----"#; - (data.to_vec(), signature.to_vec(), certs.to_vec()) - } } impl IntelAttestationHandler diff --git a/core-primitives/attestation-handler/src/collateral.rs b/core-primitives/attestation-handler/src/collateral.rs new file mode 100644 index 0000000000..eab177c589 --- /dev/null +++ b/core-primitives/attestation-handler/src/collateral.rs @@ -0,0 +1,131 @@ +/* + Copyright 2022 Integritee AG and Supercomputing Systems AG + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ +use sgx_types::sgx_ql_qve_collateral_t; +use std::{ + io::Write, + string::{String, ToString}, + vec::Vec, +}; + +// This is a rust-ified version of the type sgx_ql_qve_collateral_t +pub struct SgxQlQveCollateral { + pub version: u32, // version = 1. PCK Cert chain is in the Quote. + /* intel DCAP 1.13 */ + pub tee_type: u32, // 0x00000000: SGX or 0x00000081: TDX + pub pck_crl_issuer_chain: Vec, + pub root_ca_crl: Vec, + pub pck_crl: Vec, + pub tcb_info_issuer_chain: Vec, + pub tcb_info: Vec, + pub qe_identity_issuer_chain: Vec, + pub qe_identity: Vec, +} + +impl SgxQlQveCollateral { + /// Safety: The caller is in charge of ensuring that `c` is properly initialized and all + /// its members have a value that is not nullptr + pub unsafe fn from_c_type(c: &sgx_ql_qve_collateral_t) -> Self { + let pck_crl_issuer_chain = std::slice::from_raw_parts( + c.pck_crl_issuer_chain as *const u8, + c.pck_crl_issuer_chain_size as usize, + ) + .to_vec(); + let root_ca_crl = + std::slice::from_raw_parts(c.root_ca_crl as *const u8, c.root_ca_crl_size as usize) + .to_vec(); + let pck_crl = + std::slice::from_raw_parts(c.pck_crl as *const u8, c.pck_crl_size as usize).to_vec(); + let tcb_info_issuer_chain = std::slice::from_raw_parts( + c.tcb_info_issuer_chain as *const u8, + c.tcb_info_issuer_chain_size as usize, + ) + .to_vec(); + let tcb_info = + std::slice::from_raw_parts(c.tcb_info as *const u8, c.tcb_info_size as usize).to_vec(); + let qe_identity_issuer_chain = std::slice::from_raw_parts( + c.qe_identity_issuer_chain as *const u8, + c.qe_identity_issuer_chain_size as usize, + ) + .to_vec(); + let qe_identity = + std::slice::from_raw_parts(c.qe_identity as *const u8, c.qe_identity_size as usize) + .to_vec(); + SgxQlQveCollateral { + version: c.version, + tee_type: c.tee_type, + pck_crl_issuer_chain, + root_ca_crl, + pck_crl, + tcb_info_issuer_chain, + tcb_info, + qe_identity_issuer_chain, + qe_identity, + } + } + + pub fn dump_to_disk(&self) { + Self::write_data_to_disk("pck_crl_issuer_chain", &self.pck_crl_issuer_chain); + Self::write_data_to_disk("root_ca_crl", &self.root_ca_crl); + Self::write_data_to_disk("pck_crl", &self.pck_crl); + Self::write_data_to_disk("tcb_info_issuer_chain", &self.tcb_info_issuer_chain); + Self::write_data_to_disk("tcb_info", &self.tcb_info); + Self::write_data_to_disk("qe_identity_issuer_chain", &self.qe_identity_issuer_chain); + Self::write_data_to_disk("qe_identity", &self.qe_identity); + } + + /// Returns the tcb_info split into two parts: json_data and signature + pub fn get_tcb_info_split(&self) -> Option<(String, Vec)> { + let (json_data, signature) = + Self::separate_json_data_and_signature("tcbInfo", &self.tcb_info)?; + match hex::decode(signature) { + Ok(hex_signature) => Some((json_data, hex_signature)), + Err(_) => None, + } + } + + /// Returns the tcb_info split into two parts: json_data and signature + pub fn get_quoting_enclave_split(&self) -> Option<(String, Vec)> { + let (json_data, signature) = + Self::separate_json_data_and_signature("enclaveIdentity", &self.qe_identity)?; + match hex::decode(signature) { + Ok(hex_signature) => Some((json_data, hex_signature)), + Err(_) => None, + } + } + + /// Separates the actual data part from the signature for an Intel collateral in JSON format + /// Returns the data part and signature as a pair + fn separate_json_data_and_signature(data_name: &str, data: &[u8]) -> Option<(String, String)> { + let json = String::from_utf8_lossy(data); + // search pattern is something like `{"tcbInfo":`. Should be at the very beginning + let search_pattern = format!("{{\"{}\":", data_name); + let json = json.replace(&search_pattern, ""); + + let parts = json.split(r#","signature":""#).collect::>(); + if parts.len() != 2 || parts[1].len() < 2 { + return None + } + let data = &parts[0]; + let signature = &parts[1][0..parts[1].len() - 3]; // Remove the two last chars that 'close' the json + Some((data.to_string(), signature.to_string())) + } + + fn write_data_to_disk(filename: &str, contents: &[u8]) { + let mut file = std::fs::File::create(filename).unwrap(); + file.write_all(contents).unwrap(); + } +} diff --git a/core-primitives/attestation-handler/src/lib.rs b/core-primitives/attestation-handler/src/lib.rs index fb787dd395..651aeca924 100644 --- a/core-primitives/attestation-handler/src/lib.rs +++ b/core-primitives/attestation-handler/src/lib.rs @@ -39,11 +39,14 @@ pub mod sgx_reexport_prelude { #[cfg(all(not(feature = "std"), feature = "sgx"))] pub mod attestation_handler; +pub mod collateral; + pub mod cert; pub mod error; #[cfg(all(not(feature = "std"), feature = "sgx"))] pub use attestation_handler::{AttestationHandler, IntelAttestationHandler, DEV_HOSTNAME}; +pub use collateral::SgxQlQveCollateral; pub use error::{Error, Result}; diff --git a/core-primitives/enclave-api/ffi/src/lib.rs b/core-primitives/enclave-api/ffi/src/lib.rs index 0a9beca341..f0f8cd4304 100644 --- a/core-primitives/enclave-api/ffi/src/lib.rs +++ b/core-primitives/enclave-api/ffi/src/lib.rs @@ -135,6 +135,9 @@ extern "C" { quote_size: u32, ) -> sgx_status_t; + pub fn dump_dcap_collateral_to_disk(collateral: *const sgx_ql_qve_collateral_t) + -> sgx_status_t; + pub fn test_main_entrance(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t; pub fn call_rpc_methods( diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index b68255ac9f..bf371530c4 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -24,7 +24,6 @@ use itp_settings::worker::EXTRINSIC_MAX_SIZE; use itp_types::ShardIdentifier; use log::*; use sgx_types::*; -use std::io::prelude::*; const OS_SYSTEM_PATH: &str = "/usr/lib/x86_64-linux-gnu/"; const C_STRING_ENDING: &str = "\0"; @@ -54,10 +53,6 @@ pub trait RemoteAttestation { fn dump_dcap_ra_cert_to_disk(&self) -> EnclaveResult<()>; - fn get_collateral(&self, fmspc: [u8; 6]) -> EnclaveResult; - - fn get_tcb_info(&self, fmspc: [u8; 6]) -> EnclaveResult<(String, String)>; - fn dump_dcap_collateral_to_disk(&self, fmspc: [u8; 6]) -> EnclaveResult<()>; fn set_ql_qe_enclave_paths(&self) -> EnclaveResult<()>; @@ -119,95 +114,24 @@ pub trait TlsRemoteAttestation { ) -> EnclaveResult<()>; } -// This is a rust-ified version of the type sgx_ql_qve_collateral_t -pub struct SgxQlQveCollateral { - pub version: u32, // version = 1. PCK Cert chain is in the Quote. - /* intel DCAP 1.13 */ - pub tee_type: u32, // 0x00000000: SGX or 0x00000081: TDX - pub pck_crl_issuer_chain: Vec, - pub root_ca_crl: Vec, - pub pck_crl: Vec, - pub tcb_info_issuer_chain: Vec, - pub tcb_info: Vec, - pub qe_identity_issuer_chain: Vec, - pub qe_identity: Vec, -} - -impl SgxQlQveCollateral { - unsafe fn from_c_version(q: &sgx_ql_qve_collateral_t) -> Self { - let pck_crl_issuer_chain = std::slice::from_raw_parts( - q.pck_crl_issuer_chain as *const u8, - q.pck_crl_issuer_chain_size as usize, - ) - .to_vec(); - let root_ca_crl = - std::slice::from_raw_parts(q.root_ca_crl as *const u8, q.root_ca_crl_size as usize) - .to_vec(); - let pck_crl = - std::slice::from_raw_parts(q.pck_crl as *const u8, q.pck_crl_size as usize).to_vec(); - let tcb_info_issuer_chain = std::slice::from_raw_parts( - q.tcb_info_issuer_chain as *const u8, - q.tcb_info_issuer_chain_size as usize, - ) - .to_vec(); - let tcb_info = - std::slice::from_raw_parts(q.tcb_info as *const u8, q.tcb_info_size as usize).to_vec(); - let qe_identity_issuer_chain = std::slice::from_raw_parts( - q.qe_identity_issuer_chain as *const u8, - q.qe_identity_issuer_chain_size as usize, - ) - .to_vec(); - let qe_identity = - std::slice::from_raw_parts(q.qe_identity as *const u8, q.qe_identity_size as usize) - .to_vec(); - SgxQlQveCollateral { - version: q.version, - tee_type: q.tee_type, - pck_crl_issuer_chain, - root_ca_crl, - pck_crl, - tcb_info_issuer_chain, - tcb_info, - qe_identity_issuer_chain, - qe_identity, - } - } - - fn dump_to_disk(&self) { - Self::write_data_to_disk("pck_crl_issuer_chain", &self.pck_crl_issuer_chain); - Self::write_data_to_disk("root_ca_crl", &self.root_ca_crl); - Self::write_data_to_disk("pck_crl", &self.pck_crl); - Self::write_data_to_disk("tcb_info_issuer_chain", &self.tcb_info_issuer_chain); - Self::write_data_to_disk("tcb_info", &self.tcb_info); - Self::write_data_to_disk("qe_identity_issuer_chain", &self.qe_identity_issuer_chain); - Self::write_data_to_disk("qe_identity", &self.qe_identity); - } - - /// Returns the tcb_info split into two parts: tcb_info and signature - fn get_tcb_info_split(&self) -> Option<(String, String)> { - Self::separate_json_data_and_signature("enclaveIdentity", &self.qe_identity) - } - - /// Separates the actual data part from the signature for an Intel collateral in JSON format - /// Returns the data part and signature as a pair - fn separate_json_data_and_signature(data_name: &str, data: &[u8]) -> Option<(String, String)> { - let json = String::from_utf8_lossy(data); - // search pattern is something like `{"tcbInfo":`. Should be at the very beginning - let search_pattern = format!("{{\"{}\":", data_name); - let json = json.replace(&search_pattern, ""); - - let parts = json.split(r#","signature":""#).collect::>(); - if parts.len() != 2 || parts[1].len() < 2 { - return None - } - let data = &parts[0]; - let signature = &parts[1][0..parts[1].len() - 2]; // Remove the two last chars that 'close' the json - Some((data.to_string(), signature.to_string())) - } +impl Enclave { + unsafe fn get_collateral( + &self, + fmspc: [u8; 6], + ) -> EnclaveResult<*const sgx_ql_qve_collateral_t> { + let pck_ra = b"processor\x00"; - fn write_data_to_disk(filename: &str, contents: &[u8]) { - let mut file = std::fs::File::create(filename).unwrap(); - file.write_all(contents).unwrap(); + let mut collateral_ptr: *mut sgx_ql_qve_collateral_t = std::mem::zeroed(); + let collateral_ptr_ptr: *mut *mut sgx_ql_qve_collateral_t = &mut collateral_ptr; + let sgx_status = sgx_ql_get_quote_verification_collateral( + fmspc.as_ptr(), + fmspc.len() as uint16_t, //fmspc len is fixed in the function signature + pck_ra.as_ptr() as _, + collateral_ptr_ptr, + ); + ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); + println!("Collateral version: {}", (*collateral_ptr).version); + Ok(collateral_ptr) } } @@ -273,19 +197,7 @@ impl RemoteAttestation for Enclave { let mut retval = sgx_status_t::SGX_SUCCESS; let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; - let pck_ra = b"processor\x00"; - let collateral_ptr = unsafe { - let mut collateral_ptr: *mut sgx_ql_qve_collateral_t = std::mem::zeroed(); - let collateral_ptr_ptr: *mut *mut sgx_ql_qve_collateral_t = &mut collateral_ptr; - let sgx_status = sgx_ql_get_quote_verification_collateral( - fmspc.as_ptr(), - fmspc.len() as uint16_t, //fmspc len is fixed in the function signature - pck_ra.as_ptr() as _, - collateral_ptr_ptr, - ); - ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); - collateral_ptr - }; + let collateral_ptr = unsafe { self.get_collateral(fmspc)? }; let result = unsafe { ffi::generate_qe_extrinsic( @@ -369,40 +281,10 @@ impl RemoteAttestation for Enclave { Ok(quote_size) } - fn get_tcb_info(&self, fmspc: [u8; 6]) -> EnclaveResult<(String, String)> { - let collateral = self.get_collateral(fmspc)?; - Ok(collateral.get_tcb_info_split().unwrap()) - } - - fn get_collateral(&self, fmspc: [u8; 6]) -> EnclaveResult { - let pck_ra = b"processor\x00"; - unsafe { - let mut collateral_prt: *mut sgx_ql_qve_collateral_t = std::mem::zeroed(); - let collateral_prt_ptr: *mut *mut sgx_ql_qve_collateral_t = &mut collateral_prt; - let sgx_status = sgx_ql_get_quote_verification_collateral( - fmspc.as_ptr(), - fmspc.len() as uint16_t, //fmspc len is fixed in the function signature - pck_ra.as_ptr() as _, - collateral_prt_ptr, - ); - - println!("SGX status: {}", sgx_status); - ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); - - println!("Collateral size: {}", std::mem::size_of::()); - let quote_collateral = &(**collateral_prt_ptr); - let collateral = SgxQlQveCollateral::from_c_version(quote_collateral); - let sgx_status = sgx_ql_free_quote_verification_collateral(quote_collateral); - println!("SGX status: {}", sgx_status); - Ok(collateral) - } - } - fn dump_dcap_collateral_to_disk(&self, fmspc: [u8; 6]) -> EnclaveResult<()> { - let collateral = self.get_collateral(fmspc)?; - collateral.dump_to_disk(); - println!("Collateral version: {}", collateral.version); - + let collateral = unsafe { self.get_collateral(fmspc)? }; + let result = unsafe { ffi::dump_dcap_collateral_to_disk(collateral) }; + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); Ok(()) } } diff --git a/enclave-runtime/Enclave.edl b/enclave-runtime/Enclave.edl index e17225b7e0..7149ba9911 100644 --- a/enclave-runtime/Enclave.edl +++ b/enclave-runtime/Enclave.edl @@ -118,6 +118,8 @@ enclave { public sgx_status_t dump_dcap_ra_cert_to_disk([in] const sgx_target_info_t* quoting_enclave_target_info, uint32_t quote_size); + public sgx_status_t dump_dcap_collateral_to_disk([in] const sgx_ql_qve_collateral_t *p_quote_collateral); + public sgx_status_t run_state_provisioning_server(int fd, sgx_quote_sign_type_t quote_type, int skip_ra); public sgx_status_t request_state_provisioning( int fd, diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index 9b4abaa982..21455d9a19 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -36,7 +36,7 @@ use crate::{ Error as EnclaveError, Result as EnclaveResult, }; use codec::{Decode, Encode}; -use itp_attestation_handler::AttestationHandler; +use itp_attestation_handler::{AttestationHandler, SgxQlQveCollateral}; use itp_component_container::ComponentGetter; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::metadata::{ @@ -207,11 +207,12 @@ pub unsafe extern "C" fn generate_qe_extrinsic( unchecked_extrinsic: *mut u8, unchecked_extrinsic_size: u32, ) -> sgx_status_t { - if unchecked_extrinsic.is_null() { + if unchecked_extrinsic.is_null() || collateral.is_null() { return sgx_status_t::SGX_ERROR_INVALID_PARAMETER } let extrinsic_slice = slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); + let collateral = SgxQlQveCollateral::from_c_type(&*collateral); let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { Ok(r) => r, Err(e) => { @@ -219,7 +220,7 @@ pub unsafe extern "C" fn generate_qe_extrinsic( return sgx_status_t::SGX_ERROR_UNEXPECTED }, }; - let (data, signature, certs) = attestation_handler.get_quoting_enclave_collateral(); + let (data, signature) = collateral.get_quoting_enclave_split().unwrap(); let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain().unwrap(); let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); @@ -230,7 +231,8 @@ pub unsafe extern "C" fn generate_qe_extrinsic( .map_err(MetadataProviderError::MetadataError) .unwrap(); info!(" [Enclave] Compose register quoting enclave call: {:?}", call_ids); - let call = OpaqueCall::from_tuple(&(call_ids, data, signature, certs)); + let call = + OpaqueCall::from_tuple(&(call_ids, data, signature, collateral.qe_identity_issuer_chain)); let extrinsic = extrinsics_factory.create_extrinsics(&[call], None).unwrap()[0].clone(); if let Err(e) = write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { @@ -271,3 +273,19 @@ pub unsafe extern "C" fn dump_dcap_ra_cert_to_disk( Err(e) => e.into(), } } + +#[no_mangle] +pub unsafe extern "C" fn dump_dcap_collateral_to_disk( + collateral: *const sgx_ql_qve_collateral_t, +) -> sgx_status_t { + let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { + Ok(r) => r, + Err(e) => { + error!("Component get failure: {:?}", e); + return sgx_status_t::SGX_ERROR_UNEXPECTED + }, + }; + let collateral = SgxQlQveCollateral::from_c_type(&*collateral); + collateral.dump_to_disk(); + sgx_status_t::SGX_SUCCESS +} From ddabfbdf70c068fc479583eaff5eb61eae8ddefe Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Wed, 7 Dec 2022 11:35:04 +0100 Subject: [PATCH 05/39] Make the dump-ra CLI command work --- .../attestation-handler/src/attestation_handler.rs | 2 +- core-primitives/enclave-api/ffi/src/lib.rs | 7 +++++-- .../enclave-api/src/remote_attestation.rs | 5 ++++- enclave-runtime/src/attestation.rs | 14 -------------- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/core-primitives/attestation-handler/src/attestation_handler.rs b/core-primitives/attestation-handler/src/attestation_handler.rs index 155074bd13..63c4fa753c 100644 --- a/core-primitives/attestation-handler/src/attestation_handler.rs +++ b/core-primitives/attestation-handler/src/attestation_handler.rs @@ -30,7 +30,7 @@ #[cfg(all(not(feature = "std"), feature = "sgx"))] use crate::sgx_reexport_prelude::*; -use crate::{cert, Error as EnclaveError, Error, Result as EnclaveResult, SgxQlQveCollateral}; +use crate::{cert, Error as EnclaveError, Error, Result as EnclaveResult}; use codec::Encode; use core::{convert::TryInto, default::Default}; use hex_literal::hex; diff --git a/core-primitives/enclave-api/ffi/src/lib.rs b/core-primitives/enclave-api/ffi/src/lib.rs index f0f8cd4304..e5c63c92c4 100644 --- a/core-primitives/enclave-api/ffi/src/lib.rs +++ b/core-primitives/enclave-api/ffi/src/lib.rs @@ -135,8 +135,11 @@ extern "C" { quote_size: u32, ) -> sgx_status_t; - pub fn dump_dcap_collateral_to_disk(collateral: *const sgx_ql_qve_collateral_t) - -> sgx_status_t; + pub fn dump_dcap_collateral_to_disk( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + collateral: *const sgx_ql_qve_collateral_t, + ) -> sgx_status_t; pub fn test_main_entrance(eid: sgx_enclave_id_t, retval: *mut sgx_status_t) -> sgx_status_t; diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index bf371530c4..8d18489b93 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -282,9 +282,12 @@ impl RemoteAttestation for Enclave { } fn dump_dcap_collateral_to_disk(&self, fmspc: [u8; 6]) -> EnclaveResult<()> { + let mut retval = sgx_status_t::SGX_SUCCESS; let collateral = unsafe { self.get_collateral(fmspc)? }; - let result = unsafe { ffi::dump_dcap_collateral_to_disk(collateral) }; + let result = + unsafe { ffi::dump_dcap_collateral_to_disk(self.eid, &mut retval, collateral) }; ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); Ok(()) } } diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index 21455d9a19..f09cdf4289 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -213,13 +213,6 @@ pub unsafe extern "C" fn generate_qe_extrinsic( let extrinsic_slice = slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); let collateral = SgxQlQveCollateral::from_c_type(&*collateral); - let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { - Ok(r) => r, - Err(e) => { - error!("Component get failure: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; let (data, signature) = collateral.get_quoting_enclave_split().unwrap(); let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain().unwrap(); @@ -278,13 +271,6 @@ pub unsafe extern "C" fn dump_dcap_ra_cert_to_disk( pub unsafe extern "C" fn dump_dcap_collateral_to_disk( collateral: *const sgx_ql_qve_collateral_t, ) -> sgx_status_t { - let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { - Ok(r) => r, - Err(e) => { - error!("Component get failure: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; let collateral = SgxQlQveCollateral::from_c_type(&*collateral); collateral.dump_to_disk(); sgx_status_t::SGX_SUCCESS From 57e1548b108eac6f8ab61a2447949e2625d3111d Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 13 Dec 2022 08:34:40 +0100 Subject: [PATCH 06/39] Work towards register_tcb_info --- .../node-api/metadata/src/metadata_mocks.rs | 26 +++++++++++++------ .../node-api/metadata/src/pallet_teerex.rs | 12 ++++++--- enclave-runtime/src/attestation.rs | 2 +- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/core-primitives/node-api/metadata/src/metadata_mocks.rs b/core-primitives/node-api/metadata/src/metadata_mocks.rs index 909de8fa3c..aa6188c5e4 100644 --- a/core-primitives/node-api/metadata/src/metadata_mocks.rs +++ b/core-primitives/node-api/metadata/src/metadata_mocks.rs @@ -23,8 +23,11 @@ use codec::{Decode, Encode}; #[derive(Default, Encode, Decode, Debug, Clone)] pub struct NodeMetadataMock { teerex_module: u8, - register_enclave: u8, + register_ias_enclave: u8, + register_dcap_enclave: u8, unregister_enclave: u8, + register_quoting_enclave: u8, + register_tcb_info: u8, call_worker: u8, processed_parentchain_block: u8, shield_funds: u8, @@ -39,8 +42,11 @@ impl NodeMetadataMock { pub fn new() -> Self { NodeMetadataMock { teerex_module: 50u8, - register_enclave: 0u8, + register_ias_enclave: 0u8, + register_dcap_enclave: 6, unregister_enclave: 1u8, + register_quoting_enclave: 7, + register_tcb_info: 8, call_worker: 2u8, processed_parentchain_block: 3u8, shield_funds: 4u8, @@ -54,20 +60,24 @@ impl NodeMetadataMock { } impl TeerexCallIndexes for NodeMetadataMock { - fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.register_enclave]) + fn register_ias_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.register_ias_enclave]) } fn register_dcap_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.register_enclave]) + Ok([self.teerex_module, self.register_dcap_enclave]) + } + + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.unregister_enclave]) } fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.register_enclave]) + Ok([self.teerex_module, self.register_quoting_enclave]) } - fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]> { - Ok([self.teerex_module, self.unregister_enclave]) + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { + Ok([self.teerex_module, self.register_tcb_info]) } fn call_worker_call_indexes(&self) -> Result<[u8; 2]> { diff --git a/core-primitives/node-api/metadata/src/pallet_teerex.rs b/core-primitives/node-api/metadata/src/pallet_teerex.rs index 37d54e968a..cb07b342fc 100644 --- a/core-primitives/node-api/metadata/src/pallet_teerex.rs +++ b/core-primitives/node-api/metadata/src/pallet_teerex.rs @@ -21,13 +21,15 @@ use sp_core::storage::StorageKey; const TEEREX: &str = "Teerex"; pub trait TeerexCallIndexes { - fn register_enclave_call_indexes(&self) -> Result<[u8; 2]>; + fn register_ias_enclave_call_indexes(&self) -> Result<[u8; 2]>; fn register_dcap_enclave_call_indexes(&self) -> Result<[u8; 2]>; + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]>; + fn register_quoting_enclave_call_indexes(&self) -> Result<[u8; 2]>; - fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]>; + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]>; fn call_worker_call_indexes(&self) -> Result<[u8; 2]>; @@ -45,7 +47,7 @@ pub trait TeerexStorageKey { } impl TeerexCallIndexes for NodeMetadata { - fn register_enclave_call_indexes(&self) -> Result<[u8; 2]> { + fn register_ias_enclave_call_indexes(&self) -> Result<[u8; 2]> { self.call_indexes(TEEREX, "register_enclave") } @@ -57,6 +59,10 @@ impl TeerexCallIndexes for NodeMetadata { self.call_indexes(TEEREX, "register_quoting_enclave") } + fn register_tcb_info_call_indexes(&self) -> Result<[u8; 2]> { + self.call_indexes(TEEREX, "register_tcb_info") + } + fn unregister_enclave_call_indexes(&self) -> Result<[u8; 2]> { self.call_indexes(TEEREX, "unregister_enclave") } diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index f09cdf4289..b5cac05a16 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -191,7 +191,7 @@ fn generate_ias_ra_extrinsic_internal( info!(" [Enclave] Compose register enclave call"); let call_ids = node_metadata_repo - .get_from_metadata(|m| m.register_enclave_call_indexes())? + .get_from_metadata(|m| m.register_ias_enclave_call_indexes())? .map_err(MetadataProviderError::MetadataError)?; let call = OpaqueCall::from_tuple(&(call_ids, cert_der, url)); From af8e8557771e05e44d66af03adff1418434b9161 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 13 Dec 2022 10:23:57 +0100 Subject: [PATCH 07/39] Add all the boilerplate code to register TCB info --- core-primitives/enclave-api/ffi/src/lib.rs | 10 ++++- .../enclave-api/src/remote_attestation.rs | 38 +++++++++++++++++-- core-primitives/settings/src/lib.rs | 2 +- enclave-runtime/Cargo.lock | 7 ++++ enclave-runtime/Enclave.edl | 7 +++- enclave-runtime/src/attestation.rs | 35 ++++++++++++++++- service/src/main.rs | 23 ++++++++++- 7 files changed, 114 insertions(+), 8 deletions(-) diff --git a/core-primitives/enclave-api/ffi/src/lib.rs b/core-primitives/enclave-api/ffi/src/lib.rs index e5c63c92c4..5dcf464324 100644 --- a/core-primitives/enclave-api/ffi/src/lib.rs +++ b/core-primitives/enclave-api/ffi/src/lib.rs @@ -115,7 +115,15 @@ extern "C" { quote_size: u32, ) -> sgx_status_t; - pub fn generate_qe_extrinsic( + pub fn generate_register_quoting_enclave_extrinsic( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + collateral: *const sgx_ql_qve_collateral_t, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_size: u32, + ) -> sgx_status_t; + + pub fn generate_register_tcb_info_extrinsic( eid: sgx_enclave_id_t, retval: *mut sgx_status_t, collateral: *const sgx_ql_qve_collateral_t, diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index 8d18489b93..2bd220c070 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -47,7 +47,10 @@ pub trait RemoteAttestation { fn generate_dcap_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult>; - fn generate_qe_extrinsic(&self, fmspc: [u8; 6]) -> EnclaveResult>; + fn generate_register_quoting_enclave_extrinsic(&self, fmspc: [u8; 6]) + -> EnclaveResult>; + + fn generate_register_tcb_info_extrinsic(&self, fmspc: [u8; 6]) -> EnclaveResult>; fn dump_ias_ra_cert_to_disk(&self) -> EnclaveResult<()>; @@ -193,14 +196,43 @@ impl RemoteAttestation for Enclave { Ok(unchecked_extrinsic) } - fn generate_qe_extrinsic(&self, fmspc: [u8; 6]) -> EnclaveResult> { + fn generate_register_quoting_enclave_extrinsic( + &self, + fmspc: [u8; 6], + ) -> EnclaveResult> { + let mut retval = sgx_status_t::SGX_SUCCESS; + let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; + + let collateral_ptr = unsafe { self.get_collateral(fmspc)? }; + + let result = unsafe { + ffi::generate_register_quoting_enclave_extrinsic( + self.eid, + &mut retval, + collateral_ptr, + unchecked_extrinsic.as_mut_ptr(), + unchecked_extrinsic.len() as u32, + ) + }; + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + let sgx_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; + println!("SGX status: {}", sgx_status); + ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + + Ok(unchecked_extrinsic) + } + + fn generate_register_tcb_info_extrinsic(&self, fmspc: [u8; 6]) -> EnclaveResult> { let mut retval = sgx_status_t::SGX_SUCCESS; let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; let collateral_ptr = unsafe { self.get_collateral(fmspc)? }; let result = unsafe { - ffi::generate_qe_extrinsic( + ffi::generate_register_tcb_info_extrinsic( self.eid, &mut retval, collateral_ptr, diff --git a/core-primitives/settings/src/lib.rs b/core-primitives/settings/src/lib.rs index dc24f46129..1bfa54a1d0 100644 --- a/core-primitives/settings/src/lib.rs +++ b/core-primitives/settings/src/lib.rs @@ -71,7 +71,7 @@ pub mod files { /// Settings concerning the worker pub mod worker { // the maximum size of any extrinsic that the enclave will ever generate in B - pub const EXTRINSIC_MAX_SIZE: usize = 5500; + pub const EXTRINSIC_MAX_SIZE: usize = 13_000; // the maximum size of the header pub const HEADER_MAX_SIZE: usize = 200; // maximum size of shielding key diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index 098ed74b6b..7e3f7857d7 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -1285,6 +1285,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hmac" version = "0.12.1" @@ -1725,6 +1731,7 @@ dependencies = [ "bit-vec", "chrono 0.4.11", "hex", + "hex-literal", "httparse", "itertools", "itp-ocall-api", diff --git a/enclave-runtime/Enclave.edl b/enclave-runtime/Enclave.edl index 7149ba9911..dffd2dd139 100644 --- a/enclave-runtime/Enclave.edl +++ b/enclave-runtime/Enclave.edl @@ -97,7 +97,12 @@ enclave { uint32_t quote_size ); - public sgx_status_t generate_qe_extrinsic( + public sgx_status_t generate_register_quoting_enclave_extrinsic( + [in] const sgx_ql_qve_collateral_t *p_quote_collateral, + [out, size=unchecked_extrinsic_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_size + ); + + public sgx_status_t generate_register_tcb_info_extrinsic( [in] const sgx_ql_qve_collateral_t *p_quote_collateral, [out, size=unchecked_extrinsic_size] uint8_t* unchecked_extrinsic, uint32_t unchecked_extrinsic_size ); diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index b5cac05a16..d7d2af3e46 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -202,7 +202,7 @@ fn generate_ias_ra_extrinsic_internal( } #[no_mangle] -pub unsafe extern "C" fn generate_qe_extrinsic( +pub unsafe extern "C" fn generate_register_quoting_enclave_extrinsic( collateral: *const sgx_ql_qve_collateral_t, unchecked_extrinsic: *mut u8, unchecked_extrinsic_size: u32, @@ -234,6 +234,39 @@ pub unsafe extern "C" fn generate_qe_extrinsic( sgx_status_t::SGX_SUCCESS } +#[no_mangle] +pub unsafe extern "C" fn generate_register_tcb_info_extrinsic( + collateral: *const sgx_ql_qve_collateral_t, + unchecked_extrinsic: *mut u8, + unchecked_extrinsic_size: u32, +) -> sgx_status_t { + if unchecked_extrinsic.is_null() || collateral.is_null() { + return sgx_status_t::SGX_ERROR_INVALID_PARAMETER + } + let extrinsic_slice = + slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); + let collateral = SgxQlQveCollateral::from_c_type(&*collateral); + let (data, signature) = collateral.get_tcb_info_split().unwrap(); + + let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain().unwrap(); + let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); + + let call_ids = node_metadata_repo + .get_from_metadata(|m| m.register_tcb_info_call_indexes()) + .unwrap() + .map_err(MetadataProviderError::MetadataError) + .unwrap(); + info!(" [Enclave] Compose register TCB info call: {:?}", call_ids); + let call = + OpaqueCall::from_tuple(&(call_ids, data, signature, collateral.tcb_info_issuer_chain)); + + let extrinsic = extrinsics_factory.create_extrinsics(&[call], None).unwrap()[0].clone(); + if let Err(e) = write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { + return EnclaveError::Other(Box::new(e)).into() + }; + sgx_status_t::SGX_SUCCESS +} + #[no_mangle] pub extern "C" fn dump_ias_ra_cert_to_disk() -> sgx_status_t { let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { diff --git a/service/src/main.rs b/service/src/main.rs index b257c0125e..052ff26db9 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -421,7 +421,7 @@ fn start_worker( { let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; - let uxt = enclave.generate_qe_extrinsic(fmspc).unwrap(); + let uxt = enclave.generate_register_quoting_enclave_extrinsic(fmspc).unwrap(); let mut xthex = hex::encode(uxt); xthex.insert_str(0, "0x"); @@ -440,6 +440,27 @@ fn start_worker( println!("[<] Extrinsic got finalized. Hash: {:?}\n", register_qe_xt_hash); } + { + let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; + let uxt = enclave.generate_register_tcb_info_extrinsic(fmspc).unwrap(); + + let mut xthex = hex::encode(uxt); + xthex.insert_str(0, "0x"); + + // Account funds + if let Err(x) = + setup_account_funding(&node_api, &tee_accountid, xthex.clone(), is_development_mode) + { + error!("Starting worker failed: {:?}", x); + // Return without registering the enclave. This will fail and the transaction will be banned for 30min. + return + } + + println!("[>] Register the TCB info (send the extrinsic)"); + let register_qe_xt_hash = node_api.send_extrinsic(xthex, XtStatus::Finalized).unwrap(); + println!("[<] Extrinsic got finalized. Hash: {:?}\n", register_qe_xt_hash); + } + // ------------------------------------------------------------------------ // Perform a remote attestation and get an unchecked extrinsic back. let trusted_url = config.trusted_worker_url_external(); From 72a26059e11f4b9d22ceebb270ad4932312e7755 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 13 Dec 2022 10:44:26 +0100 Subject: [PATCH 08/39] Reduce code duplication for extrinsic encoding --- service/src/main.rs | 13 ++++--------- service/src/teeracle/mod.rs | 7 +++---- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/service/src/main.rs b/service/src/main.rs index 052ff26db9..c284898c9f 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -63,6 +63,7 @@ use itp_settings::{ files::SIDECHAIN_STORAGE_PATH, worker_mode::{ProvideWorkerMode, WorkerMode, WorkerModeProvider}, }; +use itp_utils::hex::hex_encode; use its_peer_fetch::{ block_fetch_client::BlockFetcher, untrusted_peer_fetch::UntrustedPeerFetcher, }; @@ -422,9 +423,7 @@ fn start_worker( { let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; let uxt = enclave.generate_register_quoting_enclave_extrinsic(fmspc).unwrap(); - - let mut xthex = hex::encode(uxt); - xthex.insert_str(0, "0x"); + let xthex = hex_encode(uxt); // Account funds if let Err(x) = @@ -443,9 +442,7 @@ fn start_worker( { let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; let uxt = enclave.generate_register_tcb_info_extrinsic(fmspc).unwrap(); - - let mut xthex = hex::encode(uxt); - xthex.insert_str(0, "0x"); + let xthex = hex_encode(uxt); // Account funds if let Err(x) = @@ -475,9 +472,7 @@ fn start_worker( let uxt = enclave.generate_ias_ra_extrinsic(&trusted_url, skip_ra).unwrap(); #[cfg(feature = "dcap")] let uxt = enclave.generate_dcap_ra_extrinsic(&trusted_url, skip_ra).unwrap(); - - let mut xthex = hex::encode(uxt); - xthex.insert_str(0, "0x"); + let xthex = hex_encode(uxt); // Account funds if let Err(x) = diff --git a/service/src/teeracle/mod.rs b/service/src/teeracle/mod.rs index 15c3637a4a..2e9e147a0c 100644 --- a/service/src/teeracle/mod.rs +++ b/service/src/teeracle/mod.rs @@ -20,6 +20,7 @@ use codec::{Decode, Encode}; use itp_enclave_api::teeracle_api::TeeracleApi; use itp_node_api::api_client::ParentchainApi; use itp_settings::teeracle::DEFAULT_MARKET_DATA_UPDATE_INTERVAL; +use itp_utils::hex::hex_encode; use log::*; use sp_runtime::OpaqueExtrinsic; use std::time::Duration; @@ -75,8 +76,7 @@ fn execute_weather_update( extrinsics.into_iter().for_each(|call| { let node_api_clone = node_api.clone(); tokio_handle.spawn(async move { - let mut hex_encoded_extrinsic = hex::encode(call.encode()); - hex_encoded_extrinsic.insert_str(0, "0x"); + let hex_encoded_extrinsic = hex_encode(call.encode()); debug!("Hex encoded extrinsic to be sent: {}", hex_encoded_extrinsic); println!("[>] Update oracle (send the extrinsic)"); let extrinsic_hash = @@ -123,8 +123,7 @@ fn execute_update_market( for call in extrinsics.into_iter() { let node_api_clone = node_api.clone(); tokio_handle.spawn(async move { - let mut hex_encoded_extrinsic = hex::encode(call.encode()); - hex_encoded_extrinsic.insert_str(0, "0x"); + let hex_encoded_extrinsic = hex_encode(call.encode()); debug!("Hex encoded extrinsic to be sent: {}", hex_encoded_extrinsic); println!("[>] Update the exchange rate (send the extrinsic)"); From 9f5077de9194db44c2b30b9fbd323261952b4c91 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 13 Dec 2022 13:21:03 +0100 Subject: [PATCH 09/39] Reduce code duplication for extrinsic sending --- .../attestation-handler/src/collateral.rs | 4 +- core-primitives/utils/src/hex.rs | 6 +- service/src/account_funding.rs | 4 +- service/src/main.rs | 57 ++++++++----------- 4 files changed, 33 insertions(+), 38 deletions(-) diff --git a/core-primitives/attestation-handler/src/collateral.rs b/core-primitives/attestation-handler/src/collateral.rs index eab177c589..6e2a9abca1 100644 --- a/core-primitives/attestation-handler/src/collateral.rs +++ b/core-primitives/attestation-handler/src/collateral.rs @@ -36,7 +36,9 @@ pub struct SgxQlQveCollateral { } impl SgxQlQveCollateral { - /// Safety: The caller is in charge of ensuring that `c` is properly initialized and all + /// # Safety + /// + /// The caller is in charge of ensuring that `c` is properly initialized and all /// its members have a value that is not nullptr pub unsafe fn from_c_type(c: &sgx_ql_qve_collateral_t) -> Self { let pck_crl_issuer_chain = std::slice::from_raw_parts( diff --git a/core-primitives/utils/src/hex.rs b/core-primitives/utils/src/hex.rs index c68ce00a29..6f3c63e68c 100644 --- a/core-primitives/utils/src/hex.rs +++ b/core-primitives/utils/src/hex.rs @@ -28,7 +28,7 @@ pub trait ToHexPrefixed { impl ToHexPrefixed for T { fn to_hex(&self) -> String { - hex_encode(self.encode()) + hex_encode(&self.encode()) } } @@ -49,7 +49,7 @@ impl FromHexPrefixed for T { } /// Hex encodes given data and preappends a "0x". -pub fn hex_encode(data: Vec) -> String { +pub fn hex_encode(data: &[u8]) -> String { let mut hex_str = hex::encode(data); hex_str.insert_str(0, "0x"); hex_str @@ -73,7 +73,7 @@ mod tests { fn hex_encode_decode_works() { let data = "Hello World!".to_string(); - let hex_encoded_data = hex_encode(data.encode()); + let hex_encoded_data = hex_encode(&data.encode()); let decoded_data = String::decode(&mut decode_hex(hex_encoded_data).unwrap().as_slice()).unwrap(); diff --git a/service/src/account_funding.rs b/service/src/account_funding.rs index 787e74cbf1..586c4f1ff1 100644 --- a/service/src/account_funding.rs +++ b/service/src/account_funding.rs @@ -54,7 +54,7 @@ impl EnclaveAccountInfoProvider { pub fn setup_account_funding( api: &ParentchainApi, accountid: &AccountId32, - extrinsic_prefix: String, + extrinsic_prefix: &str, is_development_mode: bool, ) -> ServiceResult<()> { // Account funds @@ -63,7 +63,7 @@ pub fn setup_account_funding( ensure_account_has_funds(api, accountid)?; } else { // Production mode, there is no faucet. - let registration_fees = enclave_registration_fees(api, &extrinsic_prefix)?; + let registration_fees = enclave_registration_fees(api, extrinsic_prefix)?; info!("Registration fees = {:?}", registration_fees); let free_balance = api.get_free_balance(accountid)?; info!("TEE's free balance = {:?}", free_balance); diff --git a/service/src/main.rs b/service/src/main.rs index c284898c9f..e8a11201a8 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -423,39 +423,13 @@ fn start_worker( { let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; let uxt = enclave.generate_register_quoting_enclave_extrinsic(fmspc).unwrap(); - let xthex = hex_encode(uxt); - - // Account funds - if let Err(x) = - setup_account_funding(&node_api, &tee_accountid, xthex.clone(), is_development_mode) - { - error!("Starting worker failed: {:?}", x); - // Return without registering the enclave. This will fail and the transaction will be banned for 30min. - return - } - - println!("[>] Register the quoting enclave (send the extrinsic)"); - let register_qe_xt_hash = node_api.send_extrinsic(xthex, XtStatus::Finalized).unwrap(); - println!("[<] Extrinsic got finalized. Hash: {:?}\n", register_qe_xt_hash); + send_extrinsic(&uxt, &node_api, &tee_accountid, is_development_mode); } { let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; let uxt = enclave.generate_register_tcb_info_extrinsic(fmspc).unwrap(); - let xthex = hex_encode(uxt); - - // Account funds - if let Err(x) = - setup_account_funding(&node_api, &tee_accountid, xthex.clone(), is_development_mode) - { - error!("Starting worker failed: {:?}", x); - // Return without registering the enclave. This will fail and the transaction will be banned for 30min. - return - } - - println!("[>] Register the TCB info (send the extrinsic)"); - let register_qe_xt_hash = node_api.send_extrinsic(xthex, XtStatus::Finalized).unwrap(); - println!("[<] Extrinsic got finalized. Hash: {:?}\n", register_qe_xt_hash); + send_extrinsic(&uxt, &node_api, &tee_accountid, is_development_mode); } // ------------------------------------------------------------------------ @@ -472,12 +446,11 @@ fn start_worker( let uxt = enclave.generate_ias_ra_extrinsic(&trusted_url, skip_ra).unwrap(); #[cfg(feature = "dcap")] let uxt = enclave.generate_dcap_ra_extrinsic(&trusted_url, skip_ra).unwrap(); - let xthex = hex_encode(uxt); + send_extrinsic(&uxt, &node_api, &tee_accountid, is_development_mode); + let xthex = hex_encode(&uxt); // Account funds - if let Err(x) = - setup_account_funding(&node_api, &tee_accountid, xthex.clone(), is_development_mode) - { + if let Err(x) = setup_account_funding(&node_api, &tee_accountid, &xthex, is_development_mode) { error!("Starting worker failed: {:?}", x); // Return without registering the enclave. This will fail and the transaction will be banned for 30min. return @@ -738,6 +711,26 @@ fn print_events(events: Events, _sender: Sender) { } } +fn send_extrinsic( + extrinsic: &[u8], + api: &ParentchainApi, + accountid: &AccountId32, + is_development_mode: bool, +) -> Option { + let xthex = hex_encode(extrinsic); + // Account funds + if let Err(x) = setup_account_funding(api, accountid, &xthex, is_development_mode) { + error!("Starting worker failed: {:?}", x); + // Return without registering the enclave. This will fail and the transaction will be banned for 30min. + return None + } + + println!("[>] Register the TCB info (send the extrinsic)"); + let register_qe_xt_hash = api.send_extrinsic(xthex, XtStatus::Finalized).unwrap(); + println!("[<] Extrinsic got finalized. Hash: {:?}\n", register_qe_xt_hash); + register_qe_xt_hash +} + /// Subscribe to the node API finalized heads stream and trigger a parent chain sync /// upon receiving a new header. fn subscribe_to_parentchain_new_headers( From 831090aafd31fbbdc3b8896106049e2e7dc68b16 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 13 Dec 2022 14:28:38 +0100 Subject: [PATCH 10/39] Extract method for collateral --- service/src/main.rs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/service/src/main.rs b/service/src/main.rs index e8a11201a8..34188e7e42 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -420,17 +420,7 @@ fn start_worker( ) .expect("Could not set the node metadata in the enclave"); - { - let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; - let uxt = enclave.generate_register_quoting_enclave_extrinsic(fmspc).unwrap(); - send_extrinsic(&uxt, &node_api, &tee_accountid, is_development_mode); - } - - { - let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; - let uxt = enclave.generate_register_tcb_info_extrinsic(fmspc).unwrap(); - send_extrinsic(&uxt, &node_api, &tee_accountid, is_development_mode); - } + register_collateral(&node_api, &*enclave, &tee_accountid, is_development_mode); // ------------------------------------------------------------------------ // Perform a remote attestation and get an unchecked extrinsic back. @@ -711,6 +701,20 @@ fn print_events(events: Events, _sender: Sender) { } } +fn register_collateral( + api: &ParentchainApi, + enclave: &dyn RemoteAttestation, + accountid: &AccountId32, + is_development_mode: bool, +) { + let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; + let uxt = enclave.generate_register_quoting_enclave_extrinsic(fmspc).unwrap(); + send_extrinsic(&uxt, &api, &accountid, is_development_mode); + + let uxt = enclave.generate_register_tcb_info_extrinsic(fmspc).unwrap(); + send_extrinsic(&uxt, &api, &accountid, is_development_mode); +} + fn send_extrinsic( extrinsic: &[u8], api: &ParentchainApi, From 6fc0edd71919e55fd381cac2984629f8a1203ee9 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Wed, 14 Dec 2022 08:16:38 +0100 Subject: [PATCH 11/39] Remove duplicated code --- service/src/main.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/service/src/main.rs b/service/src/main.rs index 34188e7e42..96164903b9 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -436,19 +436,8 @@ fn start_worker( let uxt = enclave.generate_ias_ra_extrinsic(&trusted_url, skip_ra).unwrap(); #[cfg(feature = "dcap")] let uxt = enclave.generate_dcap_ra_extrinsic(&trusted_url, skip_ra).unwrap(); - send_extrinsic(&uxt, &node_api, &tee_accountid, is_development_mode); - let xthex = hex_encode(&uxt); - - // Account funds - if let Err(x) = setup_account_funding(&node_api, &tee_accountid, &xthex, is_development_mode) { - error!("Starting worker failed: {:?}", x); - // Return without registering the enclave. This will fail and the transaction will be banned for 30min. - return - } - - println!("[>] Register the enclave (send the extrinsic)"); - let register_enclave_xt_hash = node_api.send_extrinsic(xthex, XtStatus::Finalized).unwrap(); - println!("[<] Extrinsic got finalized. Hash: {:?}\n", register_enclave_xt_hash); + let register_enclave_xt_hash = + send_extrinsic(&uxt, &node_api, &tee_accountid, is_development_mode); let register_enclave_xt_header = node_api.get_header(register_enclave_xt_hash).unwrap().unwrap(); From bcbde653d269984adfeb3f72d7d2eb11442653f7 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 3 Jan 2023 10:58:51 +0100 Subject: [PATCH 12/39] Fix clippy issues --- service/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/src/main.rs b/service/src/main.rs index 96164903b9..9e1a441bc4 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -698,10 +698,10 @@ fn register_collateral( ) { let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; let uxt = enclave.generate_register_quoting_enclave_extrinsic(fmspc).unwrap(); - send_extrinsic(&uxt, &api, &accountid, is_development_mode); + send_extrinsic(&uxt, api, accountid, is_development_mode); let uxt = enclave.generate_register_tcb_info_extrinsic(fmspc).unwrap(); - send_extrinsic(&uxt, &api, &accountid, is_development_mode); + send_extrinsic(&uxt, api, accountid, is_development_mode); } fn send_extrinsic( From 13034d73e9146c7a093486354f704a9ee0c9b2ae Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 3 Jan 2023 11:52:36 +0100 Subject: [PATCH 13/39] Fix compilation error in teeracle --- service/src/teeracle/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/service/src/teeracle/mod.rs b/service/src/teeracle/mod.rs index 2e9e147a0c..e39a247985 100644 --- a/service/src/teeracle/mod.rs +++ b/service/src/teeracle/mod.rs @@ -76,7 +76,7 @@ fn execute_weather_update( extrinsics.into_iter().for_each(|call| { let node_api_clone = node_api.clone(); tokio_handle.spawn(async move { - let hex_encoded_extrinsic = hex_encode(call.encode()); + let hex_encoded_extrinsic = hex_encode(&call.encode()); debug!("Hex encoded extrinsic to be sent: {}", hex_encoded_extrinsic); println!("[>] Update oracle (send the extrinsic)"); let extrinsic_hash = @@ -123,7 +123,7 @@ fn execute_update_market( for call in extrinsics.into_iter() { let node_api_clone = node_api.clone(); tokio_handle.spawn(async move { - let hex_encoded_extrinsic = hex_encode(call.encode()); + let hex_encoded_extrinsic = hex_encode(&call.encode()); debug!("Hex encoded extrinsic to be sent: {}", hex_encoded_extrinsic); println!("[>] Update the exchange rate (send the extrinsic)"); From 66ac9a3c3d8895b26da6124e5689098f43755758 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 3 Jan 2023 13:55:51 +0100 Subject: [PATCH 14/39] Return certificate and dcap quote --- .../src/attestation_handler.rs | 20 +++++++++---------- enclave-runtime/src/attestation.rs | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core-primitives/attestation-handler/src/attestation_handler.rs b/core-primitives/attestation-handler/src/attestation_handler.rs index 63c4fa753c..3170dcdfb5 100644 --- a/core-primitives/attestation-handler/src/attestation_handler.rs +++ b/core-primitives/attestation-handler/src/attestation_handler.rs @@ -33,7 +33,6 @@ use crate::sgx_reexport_prelude::*; use crate::{cert, Error as EnclaveError, Error, Result as EnclaveResult}; use codec::Encode; use core::{convert::TryInto, default::Default}; -use hex_literal::hex; use itertools::Itertools; use itp_ocall_api::EnclaveAttestationOCallApi; use itp_settings::{ @@ -79,11 +78,14 @@ pub const REPORT_SUFFIX: &str = "/sgx/dev/attestation/v4/report"; /// Trait to provide an abstraction to the attestation logic pub trait AttestationHandler { - /// Generates an encoded remote attestation certificate. + /// Generates an encoded remote attestation certificate. Returns certificate DER encoded. /// If skip_ra is set, it will not perform a remote attestation via IAS /// but instead generate a mock certificate. fn generate_ias_ra_cert(&self, skip_ra: bool) -> EnclaveResult>; + /// Returns the DER encoded certificate and the raw DCAP quote. + /// If skip_ra is set, it will not perform a remote attestation via IAS + /// but instead generate a mock certificate. fn generate_dcap_ra_cert( &self, quoting_enclave_target_info: &sgx_target_info_t, @@ -171,13 +173,13 @@ where quoting_enclave_target_info: &sgx_target_info_t, quote_size: u32, ) -> EnclaveResult<()> { - let (_key_der, cert_der) = + let (_cert_der, dcap_quote) = match self.generate_dcap_ra_cert(quoting_enclave_target_info, quote_size, false) { Ok(r) => r, Err(e) => return Err(e), }; - if let Err(err) = io::write(&cert_der, RA_DUMP_CERT_DER_FILE) { + if let Err(err) = io::write(&dcap_quote, RA_DUMP_CERT_DER_FILE) { error!( " [Enclave] failed to write RA file ({}), status: {:?}", RA_DUMP_CERT_DER_FILE, err @@ -267,8 +269,6 @@ where return Err(e.into()) }, }; - // Verify the quote via qve enclave - //self.ecdsa_quote_verification(qe_quote)? qe_quote } else { Default::default() @@ -276,18 +276,18 @@ where // generate an ECC certificate debug!("[Enclave] Generate ECC Certificate"); - /*let (key_der, cert_der) = match cert::gen_ecc_cert(&payload, &prv_k, &pub_k, &ecc_handle) { + let (_key_der, cert_der) = match cert::gen_ecc_cert(&qe_quote, &prv_k, &pub_k, &ecc_handle) + { Ok(r) => r, Err(e) => { error!("[Enclave] gen_ecc_cert failed: {:?}", e); return Err(e.into()) }, - };*/ + }; let _ = ecc_handle.close(); - //Ok((key_der, cert_der)) - Ok((vec![], qe_quote)) + Ok((cert_der, qe_quote)) } } diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index d7d2af3e46..2a00642754 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -152,7 +152,7 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic( }, }; - let (_key_der, cert_der) = match attestation_handler.generate_dcap_ra_cert( + let (_cert_der, dcap_quote) = match attestation_handler.generate_dcap_ra_cert( quoting_enclave_target_info, quote_size, skip_ra == 1, @@ -170,7 +170,7 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic( .map_err(MetadataProviderError::MetadataError) .unwrap(); info!(" [Enclave] Compose register enclave call DCAP IDS: {:?}", call_ids); - let call = OpaqueCall::from_tuple(&(call_ids, cert_der, url)); + let call = OpaqueCall::from_tuple(&(call_ids, dcap_quote, url)); let extrinsic = extrinsics_factory.create_extrinsics(&[call], None).unwrap()[0].clone(); if let Err(e) = write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { From 26e2ac3745857c53e78327ecb9dde0b4e512ab1a Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 3 Jan 2023 14:25:48 +0100 Subject: [PATCH 15/39] Cleanup --- .../attestation-handler/Cargo.toml | 2 -- .../enclave-api/src/remote_attestation.rs | 21 +++++++------------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/core-primitives/attestation-handler/Cargo.toml b/core-primitives/attestation-handler/Cargo.toml index 5deff25a11..b5f111e52d 100644 --- a/core-primitives/attestation-handler/Cargo.toml +++ b/core-primitives/attestation-handler/Cargo.toml @@ -10,7 +10,6 @@ arrayvec = { version = "0.7.1", default-features = false } bit-vec = { version = "0.6", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } -hex-literal = { version = "0.3.2" } itertools = { default-features = false, version = "0.10.1" } log = { version = "0.4", default-features = false } @@ -51,7 +50,6 @@ itp-types = { path = "../types", default-features = false } # integritee httparse = { default-features = false, git = "https://github.com/integritee-network/httparse-sgx", branch = "sgx-experimental" } - # substrate deps sp-core = { default-features = false, features = ["full_crypto"], git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.36" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.36" } diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index 2bd220c070..84b4b83df7 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -133,7 +133,6 @@ impl Enclave { collateral_ptr_ptr, ); ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); - println!("Collateral version: {}", (*collateral_ptr).version); Ok(collateral_ptr) } } @@ -214,13 +213,10 @@ impl RemoteAttestation for Enclave { unchecked_extrinsic.len() as u32, ) }; + let free_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); - - let sgx_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; - println!("SGX status: {}", sgx_status); - ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); - ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + ensure!(free_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(free_status)); Ok(unchecked_extrinsic) } @@ -240,13 +236,10 @@ impl RemoteAttestation for Enclave { unchecked_extrinsic.len() as u32, ) }; + let free_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); - - let sgx_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; - println!("SGX status: {}", sgx_status); - ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); - ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(retval)); + ensure!(free_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(free_status)); Ok(unchecked_extrinsic) } @@ -315,11 +308,13 @@ impl RemoteAttestation for Enclave { fn dump_dcap_collateral_to_disk(&self, fmspc: [u8; 6]) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; - let collateral = unsafe { self.get_collateral(fmspc)? }; + let collateral_ptr = unsafe { self.get_collateral(fmspc)? }; let result = - unsafe { ffi::dump_dcap_collateral_to_disk(self.eid, &mut retval, collateral) }; + unsafe { ffi::dump_dcap_collateral_to_disk(self.eid, &mut retval, collateral_ptr) }; + let free_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; ensure!(result == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); ensure!(retval == sgx_status_t::SGX_SUCCESS, Error::Sgx(result)); + ensure!(free_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(free_status)); Ok(()) } } From 4ae6f430c48eacd2f76f46155bbda080344979e5 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Wed, 4 Jan 2023 12:38:17 +0100 Subject: [PATCH 16/39] Switch to updated docker image --- .github/workflows/build_and_test.yml | 2 +- Dockerfile | 2 +- build.Dockerfile | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 4a57697c19..44e5e71d4b 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -94,7 +94,7 @@ jobs: clippy: runs-on: ubuntu-latest - container: "integritee/integritee-dev:0.1.10" + container: "integritee/integritee-dev:0.1.11" steps: - uses: actions/checkout@v3 - name: init rust diff --git a/Dockerfile b/Dockerfile index e82301687e..b32444efac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM integritee/integritee-dev:0.1.10 +FROM integritee/integritee-dev:0.1.11 LABEL maintainer="zoltan@integritee.network" # By default we warp the service diff --git a/build.Dockerfile b/build.Dockerfile index 26ba8c2402..b8523c4c49 100644 --- a/build.Dockerfile +++ b/build.Dockerfile @@ -17,7 +17,7 @@ ### Builder Stage ################################################## -FROM integritee/integritee-dev:0.1.10 AS builder +FROM integritee/integritee-dev:0.1.11 AS builder LABEL maintainer="zoltan@integritee.network" # set environment variables @@ -49,7 +49,7 @@ RUN cargo test --release # A builder stage that uses sccache to speed up local builds with docker # Installation and setup of sccache should be moved to the integritee-dev image, so we don't # always need to compile and install sccache on CI (where we have no caching so far). -FROM integritee/integritee-dev:0.1.10 AS cached-builder +FROM integritee/integritee-dev:0.1.11 AS cached-builder LABEL maintainer="zoltan@integritee.network" # set environment variables From 2b1667c5a02dcd274fc8289d349eb4e676105655 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Wed, 4 Jan 2023 14:18:53 +0100 Subject: [PATCH 17/39] Disable DCAP for now --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e39dce0633..3679f66dc2 100755 --- a/Makefile +++ b/Makefile @@ -77,12 +77,12 @@ ifeq ($(SGX_PRODUCTION), 1) SGX_ENCLAVE_MODE = "Production Mode" SGX_ENCLAVE_CONFIG = "enclave-runtime/Enclave.config.production.xml" SGX_SIGN_KEY = $(SGX_COMMERCIAL_KEY) - WORKER_FEATURES = --features=production,dcap,$(WORKER_MODE),$(ADDITIONAL_FEATURES) + WORKER_FEATURES = --features=production,$(WORKER_MODE),$(ADDITIONAL_FEATURES) else SGX_ENCLAVE_MODE = "Development Mode" SGX_ENCLAVE_CONFIG = "enclave-runtime/Enclave.config.xml" SGX_SIGN_KEY = "enclave-runtime/Enclave_private.pem" - WORKER_FEATURES = --features=default,dcap,$(WORKER_MODE),$(ADDITIONAL_FEATURES) + WORKER_FEATURES = --features=default,$(WORKER_MODE),$(ADDITIONAL_FEATURES) endif CLIENT_FEATURES = --features=$(WORKER_MODE),$(ADDITIONAL_FEATURES) From 4f1ac0be838df2ec0ffd6e8705ca225852bee988 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Thu, 5 Jan 2023 09:02:16 +0100 Subject: [PATCH 18/39] Register collateral only for DCAP --- service/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/service/src/main.rs b/service/src/main.rs index 9e1a441bc4..d711fb1c83 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -420,6 +420,7 @@ fn start_worker( ) .expect("Could not set the node metadata in the enclave"); + #[cfg(feature = "dcap")] register_collateral(&node_api, &*enclave, &tee_accountid, is_development_mode); // ------------------------------------------------------------------------ From 4f02a5ad27c0cfc4a80eb643c7bc316ae39bec7b Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Thu, 5 Jan 2023 09:38:21 +0100 Subject: [PATCH 19/39] Register collateral only for DCAP --- service/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/service/src/main.rs b/service/src/main.rs index d711fb1c83..86f65405d9 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -691,6 +691,7 @@ fn print_events(events: Events, _sender: Sender) { } } +#[cfg(feature = "dcap")] fn register_collateral( api: &ParentchainApi, enclave: &dyn RemoteAttestation, From 0e58658bb1d71c8a56550f231dad5111a5e831cd Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Thu, 5 Jan 2023 14:08:55 +0100 Subject: [PATCH 20/39] Cleanup --- Cargo.lock | 1 - .../attestation-handler/src/attestation_handler.rs | 6 +++--- enclave-runtime/Cargo.lock | 7 ------- enclave-runtime/src/tls_ra/authentication.rs | 6 +++--- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e12e09b4f0..b53c02f3fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3132,7 +3132,6 @@ dependencies = [ "chrono 0.4.11", "chrono 0.4.23", "hex", - "hex-literal", "httparse 1.4.1", "itertools", "itp-ocall-api", diff --git a/core-primitives/attestation-handler/src/attestation_handler.rs b/core-primitives/attestation-handler/src/attestation_handler.rs index 3170dcdfb5..2ca4e4a98a 100644 --- a/core-primitives/attestation-handler/src/attestation_handler.rs +++ b/core-primitives/attestation-handler/src/attestation_handler.rs @@ -643,7 +643,8 @@ where .map_err(|e| EnclaveError::Other(e.into())) } - pub fn ecdsa_quote_verification(&self, quote: Vec) -> SgxResult> { + /// Returns Ok if the verification of the quote by the quote verification enclave (QVE) was successful + pub fn ecdsa_quote_verification(&self, quote: Vec) -> SgxResult<()> { let mut app_enclave_target_info: sgx_target_info_t = unsafe { std::mem::zeroed() }; let quote_collateral: sgx_ql_qve_collateral_t = unsafe { std::mem::zeroed() }; let mut qve_report_info: sgx_ql_qe_report_info_t = unsafe { std::mem::zeroed() }; @@ -727,8 +728,7 @@ where return Err(sgx_status_t::SGX_ERROR_UNEXPECTED) } - // TODO. What to send to our teerex pallet? - Ok(vec![]) + Ok(()) } pub fn retrieve_qe_dcap_quote( diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index 7e3f7857d7..098ed74b6b 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -1285,12 +1285,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" - [[package]] name = "hmac" version = "0.12.1" @@ -1731,7 +1725,6 @@ dependencies = [ "bit-vec", "chrono 0.4.11", "hex", - "hex-literal", "httparse", "itertools", "itp-ocall-api", diff --git a/enclave-runtime/src/tls_ra/authentication.rs b/enclave-runtime/src/tls_ra/authentication.rs index 3cae981bac..5df275b539 100644 --- a/enclave-runtime/src/tls_ra/authentication.rs +++ b/enclave-runtime/src/tls_ra/authentication.rs @@ -48,17 +48,17 @@ where fn verify_client_cert( &self, - _certs: &[rustls::Certificate], + certs: &[rustls::Certificate], _sni: Option<&DNSName>, ) -> Result { - debug!("client cert: {:?}", _certs); + debug!("client cert: {:?}", certs); // This call will automatically verify cert is properly signed if self.skip_ra { warn!("Skip verifying ra-report"); return Ok(rustls::ClientCertVerified::assertion()) } - match cert::verify_mra_cert(&_certs[0].0, &self.attestation_ocall) { + match cert::verify_mra_cert(&certs[0].0, &self.attestation_ocall) { Ok(()) => Ok(rustls::ClientCertVerified::assertion()), Err(sgx_status_t::SGX_ERROR_UPDATE_NEEDED) => if self.outdated_ok { From f2aae176e086240af03e1f99ac0aa8ed3bad2627 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger <781000+Niederb@users.noreply.github.com> Date: Mon, 9 Jan 2023 08:24:55 +0100 Subject: [PATCH 21/39] Update core-primitives/attestation-handler/src/attestation_handler.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Szilárd Parrag --- core-primitives/attestation-handler/src/attestation_handler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-primitives/attestation-handler/src/attestation_handler.rs b/core-primitives/attestation-handler/src/attestation_handler.rs index 2ca4e4a98a..7e6023dd8d 100644 --- a/core-primitives/attestation-handler/src/attestation_handler.rs +++ b/core-primitives/attestation-handler/src/attestation_handler.rs @@ -78,7 +78,7 @@ pub const REPORT_SUFFIX: &str = "/sgx/dev/attestation/v4/report"; /// Trait to provide an abstraction to the attestation logic pub trait AttestationHandler { - /// Generates an encoded remote attestation certificate. Returns certificate DER encoded. + /// Generates an encoded remote attestation certificate. Returns DER encoded certificate. /// If skip_ra is set, it will not perform a remote attestation via IAS /// but instead generate a mock certificate. fn generate_ias_ra_cert(&self, skip_ra: bool) -> EnclaveResult>; From 837e4e8728af9beb69184fde28bc8d8af49f0c9a Mon Sep 17 00:00:00 2001 From: Thomas Niederberger <781000+Niederb@users.noreply.github.com> Date: Mon, 9 Jan 2023 08:25:41 +0100 Subject: [PATCH 22/39] Update enclave-runtime/src/attestation.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Szilárd Parrag --- enclave-runtime/src/attestation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index 2a00642754..ae21b0eb2f 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -169,7 +169,7 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic( .unwrap() .map_err(MetadataProviderError::MetadataError) .unwrap(); - info!(" [Enclave] Compose register enclave call DCAP IDS: {:?}", call_ids); + info!(" [Enclave] Compose register enclave call DCAP IDs: {:?}", call_ids); let call = OpaqueCall::from_tuple(&(call_ids, dcap_quote, url)); let extrinsic = extrinsics_factory.create_extrinsics(&[call], None).unwrap()[0].clone(); From 3513c8a75be09c71d9b2d4a84612a16aad9f03f1 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Mon, 9 Jan 2023 13:37:51 +0100 Subject: [PATCH 23/39] Extract shared logic into separate method --- enclave-runtime/src/attestation.rs | 59 ++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index ae21b0eb2f..c1852edfa5 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -213,25 +213,25 @@ pub unsafe extern "C" fn generate_register_quoting_enclave_extrinsic( let extrinsic_slice = slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); let collateral = SgxQlQveCollateral::from_c_type(&*collateral); - let (data, signature) = collateral.get_quoting_enclave_split().unwrap(); + let collateral_data = collateral.get_quoting_enclave_split().unwrap(); - let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain().unwrap(); let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); - let call_ids = node_metadata_repo .get_from_metadata(|m| m.register_quoting_enclave_call_indexes()) .unwrap() .map_err(MetadataProviderError::MetadataError) .unwrap(); - info!(" [Enclave] Compose register quoting enclave call: {:?}", call_ids); - let call = - OpaqueCall::from_tuple(&(call_ids, data, signature, collateral.qe_identity_issuer_chain)); - - let extrinsic = extrinsics_factory.create_extrinsics(&[call], None).unwrap()[0].clone(); - if let Err(e) = write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { - return EnclaveError::Other(Box::new(e)).into() - }; - sgx_status_t::SGX_SUCCESS + let extrinsic = generate_generic_register_collateral_extrinsic( + &call_ids, + extrinsic_slice, + &collateral_data.0, + &collateral_data.1, + &collateral.qe_identity_issuer_chain, + ); + match extrinsic { + Ok(_) => sgx_status_t::SGX_SUCCESS, + Err(e) => return e.into(), + } } #[no_mangle] @@ -246,25 +246,44 @@ pub unsafe extern "C" fn generate_register_tcb_info_extrinsic( let extrinsic_slice = slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); let collateral = SgxQlQveCollateral::from_c_type(&*collateral); - let (data, signature) = collateral.get_tcb_info_split().unwrap(); + let collateral_data = collateral.get_tcb_info_split().unwrap(); - let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain().unwrap(); let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); - let call_ids = node_metadata_repo .get_from_metadata(|m| m.register_tcb_info_call_indexes()) .unwrap() .map_err(MetadataProviderError::MetadataError) .unwrap(); - info!(" [Enclave] Compose register TCB info call: {:?}", call_ids); - let call = - OpaqueCall::from_tuple(&(call_ids, data, signature, collateral.tcb_info_issuer_chain)); + let extrinsic = generate_generic_register_collateral_extrinsic( + &call_ids, + extrinsic_slice, + &collateral_data.0, + &collateral_data.1, + &collateral.tcb_info_issuer_chain, + ); + match extrinsic { + Ok(_) => sgx_status_t::SGX_SUCCESS, + Err(e) => return e.into(), + } +} - let extrinsic = extrinsics_factory.create_extrinsics(&[call], None).unwrap()[0].clone(); +pub fn generate_generic_register_collateral_extrinsic( + call_ids: &[u8; 2], + extrinsic_slice: &mut [u8], + collateral_data: &str, + data_signature: &[u8], + issuer_chain: &[u8], +) -> EnclaveResult<()> { + let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; + + info!(" [Enclave] Compose register collateral call: {:?}", call_ids); + let call = OpaqueCall::from_tuple(&(call_ids, collateral_data, data_signature, issuer_chain)); + + let extrinsic = extrinsics_factory.create_extrinsics(&[call], None)?[0].clone(); if let Err(e) = write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { return EnclaveError::Other(Box::new(e)).into() }; - sgx_status_t::SGX_SUCCESS + Ok(()) } #[no_mangle] From bd57bcd87b6f6b33bc4cb210730c0333f3ba1e5f Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Mon, 9 Jan 2023 13:38:05 +0100 Subject: [PATCH 24/39] Improve documentation --- core-primitives/attestation-handler/src/collateral.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core-primitives/attestation-handler/src/collateral.rs b/core-primitives/attestation-handler/src/collateral.rs index 6e2a9abca1..d3c4d43abb 100644 --- a/core-primitives/attestation-handler/src/collateral.rs +++ b/core-primitives/attestation-handler/src/collateral.rs @@ -21,7 +21,10 @@ use std::{ vec::Vec, }; -// This is a rust-ified version of the type sgx_ql_qve_collateral_t +/// This is a rust-ified version of the type sgx_ql_qve_collateral_t. +/// See Appendix A.3 in the document +/// "Intel® Software Guard Extensions (Intel® SGX) Data Center Attestation Primitives: ECDSA Quote Library API" +/// https://download.01.org/intel-sgx/latest/dcap-latest/linux/docs/Intel_SGX_ECDSA_QuoteLibReference_DCAP_API.pdf pub struct SgxQlQveCollateral { pub version: u32, // version = 1. PCK Cert chain is in the Quote. /* intel DCAP 1.13 */ From 7519e937e34d2e172ca6d30093d968896fa2385b Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Mon, 9 Jan 2023 13:55:33 +0100 Subject: [PATCH 25/39] Extract DCAP logic into separate function --- enclave-runtime/src/attestation.rs | 52 ++++++++++++++++++------------ 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index c1852edfa5..b7fb463507 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -144,39 +144,49 @@ pub unsafe extern "C" fn generate_dcap_ra_extrinsic( let url = String::decode(&mut url_slice).expect("Could not decode url slice to a valid String"); let extrinsic_slice = slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); - let attestation_handler = match GLOBAL_ATTESTATION_HANDLER_COMPONENT.get() { - Ok(r) => r, - Err(e) => { - error!("Component get failure: {:?}", e); - return sgx_status_t::SGX_ERROR_UNEXPECTED - }, - }; - let (_cert_der, dcap_quote) = match attestation_handler.generate_dcap_ra_cert( + let extrinsic = match generate_dcap_ra_extrinsic_internal( + url, + skip_ra == 1, quoting_enclave_target_info, quote_size, - skip_ra == 1, ) { - Ok(r) => r, + Ok(xt) => xt, Err(e) => return e.into(), }; + + if let Err(e) = write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { + return EnclaveError::Other(Box::new(e)).into() + }; + sgx_status_t::SGX_SUCCESS +} + +fn generate_dcap_ra_extrinsic_internal( + url: String, + skip_ra: bool, + quoting_enclave_target_info: &sgx_target_info_t, + quote_size: u32, +) -> EnclaveResult { + let attestation_handler = GLOBAL_ATTESTATION_HANDLER_COMPONENT.get()?; + + let (_cert_der, dcap_quote) = attestation_handler.generate_dcap_ra_cert( + quoting_enclave_target_info, + quote_size, + skip_ra, + )?; + // TODO Need to send this to the teerex pallet (something similar to perform_ra_internal) - let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain().unwrap(); - let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); + let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain()?; let call_ids = node_metadata_repo - .get_from_metadata(|m| m.register_dcap_enclave_call_indexes()) - .unwrap() - .map_err(MetadataProviderError::MetadataError) - .unwrap(); + .get_from_metadata(|m| m.register_dcap_enclave_call_indexes())? + .map_err(MetadataProviderError::MetadataError)?; info!(" [Enclave] Compose register enclave call DCAP IDs: {:?}", call_ids); let call = OpaqueCall::from_tuple(&(call_ids, dcap_quote, url)); - let extrinsic = extrinsics_factory.create_extrinsics(&[call], None).unwrap()[0].clone(); - if let Err(e) = write_slice_and_whitespace_pad(extrinsic_slice, extrinsic.encode()) { - return EnclaveError::Other(Box::new(e)).into() - }; - sgx_status_t::SGX_SUCCESS + let extrinsic = extrinsics_factory.create_extrinsics(&[call], None)?; + Ok(extrinsic[0].clone()) } fn generate_ias_ra_extrinsic_internal( From 2fcdf537409a2f8ab01c8579407b0ce325a81d1d Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Mon, 9 Jan 2023 14:03:16 +0100 Subject: [PATCH 26/39] Get rid of two unwrap() calls --- enclave-runtime/src/attestation.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index b7fb463507..039b63e6c8 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -223,7 +223,10 @@ pub unsafe extern "C" fn generate_register_quoting_enclave_extrinsic( let extrinsic_slice = slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); let collateral = SgxQlQveCollateral::from_c_type(&*collateral); - let collateral_data = collateral.get_quoting_enclave_split().unwrap(); + let collateral_data = match collateral.get_quoting_enclave_split() { + Some(d) => d, + None => return sgx_status_t::SGX_ERROR_INVALID_PARAMETER, + }; let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); let call_ids = node_metadata_repo @@ -256,7 +259,10 @@ pub unsafe extern "C" fn generate_register_tcb_info_extrinsic( let extrinsic_slice = slice::from_raw_parts_mut(unchecked_extrinsic, unchecked_extrinsic_size as usize); let collateral = SgxQlQveCollateral::from_c_type(&*collateral); - let collateral_data = collateral.get_tcb_info_split().unwrap(); + let collateral_data = match collateral.get_tcb_info_split() { + Some(d) => d, + None => return sgx_status_t::SGX_ERROR_INVALID_PARAMETER, + }; let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); let call_ids = node_metadata_repo From cb3d47619a1423b56e2110725a4eaa5ec5133e7c Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Mon, 9 Jan 2023 14:41:56 +0100 Subject: [PATCH 27/39] Move getting the call_ids into the shared function --- enclave-runtime/src/attestation.rs | 36 +++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index 039b63e6c8..86afa8c17d 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -41,8 +41,11 @@ use itp_component_container::ComponentGetter; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::metadata::{ pallet_teerex::TeerexCallIndexes, - provider::{AccessNodeMetadata, Error as MetadataProviderError}, + provider::{ + AccessNodeMetadata, Error as MetadataProviderError, Result as MetadataProviderResult, + }, }; +use itp_node_api_metadata::NodeMetadata; use itp_settings::worker::MR_ENCLAVE_SIZE; use itp_types::OpaqueCall; use itp_utils::write_slice_and_whitespace_pad; @@ -228,14 +231,9 @@ pub unsafe extern "C" fn generate_register_quoting_enclave_extrinsic( None => return sgx_status_t::SGX_ERROR_INVALID_PARAMETER, }; - let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); - let call_ids = node_metadata_repo - .get_from_metadata(|m| m.register_quoting_enclave_call_indexes()) - .unwrap() - .map_err(MetadataProviderError::MetadataError) - .unwrap(); + let call_index_getter = |m: &NodeMetadata| m.register_quoting_enclave_call_indexes(); let extrinsic = generate_generic_register_collateral_extrinsic( - &call_ids, + call_index_getter, extrinsic_slice, &collateral_data.0, &collateral_data.1, @@ -264,14 +262,9 @@ pub unsafe extern "C" fn generate_register_tcb_info_extrinsic( None => return sgx_status_t::SGX_ERROR_INVALID_PARAMETER, }; - let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain().unwrap(); - let call_ids = node_metadata_repo - .get_from_metadata(|m| m.register_tcb_info_call_indexes()) - .unwrap() - .map_err(MetadataProviderError::MetadataError) - .unwrap(); + let call_index_getter = |m: &NodeMetadata| m.register_tcb_info_call_indexes(); let extrinsic = generate_generic_register_collateral_extrinsic( - &call_ids, + call_index_getter, extrinsic_slice, &collateral_data.0, &collateral_data.1, @@ -283,15 +276,22 @@ pub unsafe extern "C" fn generate_register_tcb_info_extrinsic( } } -pub fn generate_generic_register_collateral_extrinsic( - call_ids: &[u8; 2], +pub fn generate_generic_register_collateral_extrinsic( + getter: F, extrinsic_slice: &mut [u8], collateral_data: &str, data_signature: &[u8], issuer_chain: &[u8], -) -> EnclaveResult<()> { +) -> EnclaveResult<()> +where + F: Fn(&NodeMetadata) -> MetadataProviderResult<[u8; 2]>, +{ let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; + let node_metadata_repo = get_node_metadata_repository_from_solo_or_parachain()?; + let call_ids = node_metadata_repo + .get_from_metadata(getter)? + .map_err(MetadataProviderError::MetadataError)?; info!(" [Enclave] Compose register collateral call: {:?}", call_ids); let call = OpaqueCall::from_tuple(&(call_ids, collateral_data, data_signature, issuer_chain)); From b467d5083b4bf80952c8a45167bb6e196245bab8 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Mon, 9 Jan 2023 14:59:35 +0100 Subject: [PATCH 28/39] Use the correct Error for metadata --- enclave-runtime/src/attestation.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index 86afa8c17d..b4cb2907e3 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -41,9 +41,8 @@ use itp_component_container::ComponentGetter; use itp_extrinsics_factory::CreateExtrinsics; use itp_node_api::metadata::{ pallet_teerex::TeerexCallIndexes, - provider::{ - AccessNodeMetadata, Error as MetadataProviderError, Result as MetadataProviderResult, - }, + provider::{AccessNodeMetadata, Error as MetadataProviderError}, + Error as MetadataError, }; use itp_node_api_metadata::NodeMetadata; use itp_settings::worker::MR_ENCLAVE_SIZE; @@ -284,7 +283,7 @@ pub fn generate_generic_register_collateral_extrinsic( issuer_chain: &[u8], ) -> EnclaveResult<()> where - F: Fn(&NodeMetadata) -> MetadataProviderResult<[u8; 2]>, + F: Fn(&NodeMetadata) -> Result<[u8; 2], MetadataError>, { let extrinsics_factory = get_extrinsic_factory_from_solo_or_parachain()?; From 27413f15df345fd79977a3525fa4939755c207c9 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Mon, 9 Jan 2023 15:18:26 +0100 Subject: [PATCH 29/39] Add type alias for Fmspc --- .../enclave-api/src/remote_attestation.rs | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index 84b4b83df7..e07a18c876 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -33,6 +33,8 @@ const ID_ENCLAVE: &str = "libsgx_id_enclave.signed.so.1"; const LIBDCAP_QUOTEPROV: &str = "libdcap_quoteprov.so.1"; const QVE_ENCLAVE: &str = "libsgx_qve.signed.so.1"; +type Fmspc = [u8; 6]; + /// Struct that unites all relevant data reported by the QVE pub struct QveReport { pub supplemental_data: Vec, @@ -47,16 +49,15 @@ pub trait RemoteAttestation { fn generate_dcap_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult>; - fn generate_register_quoting_enclave_extrinsic(&self, fmspc: [u8; 6]) - -> EnclaveResult>; + fn generate_register_quoting_enclave_extrinsic(&self, fmspc: Fmspc) -> EnclaveResult>; - fn generate_register_tcb_info_extrinsic(&self, fmspc: [u8; 6]) -> EnclaveResult>; + fn generate_register_tcb_info_extrinsic(&self, fmspc: Fmspc) -> EnclaveResult>; fn dump_ias_ra_cert_to_disk(&self) -> EnclaveResult<()>; fn dump_dcap_ra_cert_to_disk(&self) -> EnclaveResult<()>; - fn dump_dcap_collateral_to_disk(&self, fmspc: [u8; 6]) -> EnclaveResult<()>; + fn dump_dcap_collateral_to_disk(&self, fmspc: Fmspc) -> EnclaveResult<()>; fn set_ql_qe_enclave_paths(&self) -> EnclaveResult<()>; @@ -118,10 +119,7 @@ pub trait TlsRemoteAttestation { } impl Enclave { - unsafe fn get_collateral( - &self, - fmspc: [u8; 6], - ) -> EnclaveResult<*const sgx_ql_qve_collateral_t> { + unsafe fn get_collateral(&self, fmspc: Fmspc) -> EnclaveResult<*const sgx_ql_qve_collateral_t> { let pck_ra = b"processor\x00"; let mut collateral_ptr: *mut sgx_ql_qve_collateral_t = std::mem::zeroed(); @@ -195,10 +193,7 @@ impl RemoteAttestation for Enclave { Ok(unchecked_extrinsic) } - fn generate_register_quoting_enclave_extrinsic( - &self, - fmspc: [u8; 6], - ) -> EnclaveResult> { + fn generate_register_quoting_enclave_extrinsic(&self, fmspc: Fmspc) -> EnclaveResult> { let mut retval = sgx_status_t::SGX_SUCCESS; let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; @@ -221,7 +216,7 @@ impl RemoteAttestation for Enclave { Ok(unchecked_extrinsic) } - fn generate_register_tcb_info_extrinsic(&self, fmspc: [u8; 6]) -> EnclaveResult> { + fn generate_register_tcb_info_extrinsic(&self, fmspc: Fmspc) -> EnclaveResult> { let mut retval = sgx_status_t::SGX_SUCCESS; let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; @@ -306,7 +301,7 @@ impl RemoteAttestation for Enclave { Ok(quote_size) } - fn dump_dcap_collateral_to_disk(&self, fmspc: [u8; 6]) -> EnclaveResult<()> { + fn dump_dcap_collateral_to_disk(&self, fmspc: Fmspc) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; let collateral_ptr = unsafe { self.get_collateral(fmspc)? }; let result = From 48c508e9a575842a0679d0336a9bbe5413978987 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 10 Jan 2023 08:26:30 +0100 Subject: [PATCH 30/39] Improve separate_json_data_and_signature and add unit test --- .../attestation-handler/src/collateral.rs | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/core-primitives/attestation-handler/src/collateral.rs b/core-primitives/attestation-handler/src/collateral.rs index d3c4d43abb..e5e869133d 100644 --- a/core-primitives/attestation-handler/src/collateral.rs +++ b/core-primitives/attestation-handler/src/collateral.rs @@ -116,7 +116,8 @@ impl SgxQlQveCollateral { /// Returns the data part and signature as a pair fn separate_json_data_and_signature(data_name: &str, data: &[u8]) -> Option<(String, String)> { let json = String::from_utf8_lossy(data); - // search pattern is something like `{"tcbInfo":`. Should be at the very beginning + let json = json.trim(); + // search pattern is something like `{"data_name":`. Should be at the very beginning let search_pattern = format!("{{\"{}\":", data_name); let json = json.replace(&search_pattern, ""); @@ -125,7 +126,7 @@ impl SgxQlQveCollateral { return None } let data = &parts[0]; - let signature = &parts[1][0..parts[1].len() - 3]; // Remove the two last chars that 'close' the json + let signature = &parts[1][0..parts[1].len() - 2]; // Remove the two last chars that 'close' the json Some((data.to_string(), signature.to_string())) } @@ -134,3 +135,29 @@ impl SgxQlQveCollateral { file.write_all(contents).unwrap(); } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn separate_json_data_and_signature_tcb_info() { + let json = br#"{"tcbInfo":{thejsondata},"signature":"thesignature"}"#; + let (data, signature) = + SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).unwrap(); + assert_eq!(data, r#"{thejsondata}"#); + assert_eq!(signature, "thesignature"); + + let json = br#"{"tcbInfo":{thejsondata},"signature":"thesignature"#; + let (data, signature) = + SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).unwrap(); + assert_eq!(data, r#"{thejsondata}"#); + assert_eq!(signature, "thesignatu"); // cut off the last two characters of signature + + let json = br#"{"tcbInfo":{thejsondata},"nosignature":"thesignature"}"#; + assert!(SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).is_none()); + + let json = br#"{"tcbInfo":{thejsondata},"signature":""#; + assert!(SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).is_none()); + } +} From fb4ed849bd082796aa413952d9f78c9cda932a92 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Tue, 10 Jan 2023 09:08:55 +0100 Subject: [PATCH 31/39] Fix clippy issues --- enclave-runtime/src/attestation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/enclave-runtime/src/attestation.rs b/enclave-runtime/src/attestation.rs index b4cb2907e3..116885c9fd 100644 --- a/enclave-runtime/src/attestation.rs +++ b/enclave-runtime/src/attestation.rs @@ -240,7 +240,7 @@ pub unsafe extern "C" fn generate_register_quoting_enclave_extrinsic( ); match extrinsic { Ok(_) => sgx_status_t::SGX_SUCCESS, - Err(e) => return e.into(), + Err(e) => e.into(), } } @@ -271,7 +271,7 @@ pub unsafe extern "C" fn generate_register_tcb_info_extrinsic( ); match extrinsic { Ok(_) => sgx_status_t::SGX_SUCCESS, - Err(e) => return e.into(), + Err(e) => e.into(), } } From fa5a8879db882efb46f54e27a427c11f1ed38404 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Mon, 16 Jan 2023 15:27:45 +0100 Subject: [PATCH 32/39] Incorporate review feedback --- .../enclave-api/src/remote_attestation.rs | 46 +++++++++++-------- service/src/main.rs | 3 ++ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index e07a18c876..d9a1a8ebf5 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -64,6 +64,11 @@ pub trait RemoteAttestation { fn qe_get_target_info(&self) -> EnclaveResult; fn qe_get_quote_size(&self) -> EnclaveResult; + + unsafe fn get_dcap_collateral( + &self, + fmspc: Fmspc, + ) -> EnclaveResult<*const sgx_ql_qve_collateral_t>; } /// call-backs that are made from inside the enclave (using o-call), to e-calls again inside the enclave @@ -118,23 +123,6 @@ pub trait TlsRemoteAttestation { ) -> EnclaveResult<()>; } -impl Enclave { - unsafe fn get_collateral(&self, fmspc: Fmspc) -> EnclaveResult<*const sgx_ql_qve_collateral_t> { - let pck_ra = b"processor\x00"; - - let mut collateral_ptr: *mut sgx_ql_qve_collateral_t = std::mem::zeroed(); - let collateral_ptr_ptr: *mut *mut sgx_ql_qve_collateral_t = &mut collateral_ptr; - let sgx_status = sgx_ql_get_quote_verification_collateral( - fmspc.as_ptr(), - fmspc.len() as uint16_t, //fmspc len is fixed in the function signature - pck_ra.as_ptr() as _, - collateral_ptr_ptr, - ); - ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); - Ok(collateral_ptr) - } -} - impl RemoteAttestation for Enclave { fn generate_ias_ra_extrinsic(&self, w_url: &str, skip_ra: bool) -> EnclaveResult> { let mut retval = sgx_status_t::SGX_SUCCESS; @@ -197,7 +185,7 @@ impl RemoteAttestation for Enclave { let mut retval = sgx_status_t::SGX_SUCCESS; let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; - let collateral_ptr = unsafe { self.get_collateral(fmspc)? }; + let collateral_ptr = unsafe { self.get_dcap_collateral(fmspc)? }; let result = unsafe { ffi::generate_register_quoting_enclave_extrinsic( @@ -220,7 +208,7 @@ impl RemoteAttestation for Enclave { let mut retval = sgx_status_t::SGX_SUCCESS; let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; - let collateral_ptr = unsafe { self.get_collateral(fmspc)? }; + let collateral_ptr = unsafe { self.get_dcap_collateral(fmspc)? }; let result = unsafe { ffi::generate_register_tcb_info_extrinsic( @@ -303,7 +291,7 @@ impl RemoteAttestation for Enclave { fn dump_dcap_collateral_to_disk(&self, fmspc: Fmspc) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; - let collateral_ptr = unsafe { self.get_collateral(fmspc)? }; + let collateral_ptr = unsafe { self.get_dcap_collateral(fmspc)? }; let result = unsafe { ffi::dump_dcap_collateral_to_disk(self.eid, &mut retval, collateral_ptr) }; let free_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; @@ -312,6 +300,24 @@ impl RemoteAttestation for Enclave { ensure!(free_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(free_status)); Ok(()) } + + unsafe fn get_dcap_collateral( + &self, + fmspc: Fmspc, + ) -> EnclaveResult<*const sgx_ql_qve_collateral_t> { + let pck_ra = b"processor\x00"; + + let mut collateral_ptr: *mut sgx_ql_qve_collateral_t = std::mem::zeroed(); + let collateral_ptr_ptr: *mut *mut sgx_ql_qve_collateral_t = &mut collateral_ptr; + let sgx_status = sgx_ql_get_quote_verification_collateral( + fmspc.as_ptr(), + fmspc.len() as uint16_t, //fmspc len is fixed in the function signature + pck_ra.as_ptr() as _, + collateral_ptr_ptr, + ); + ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); + Ok(collateral_ptr) + } } impl RemoteAttestationCallBacks for Enclave { diff --git a/service/src/main.rs b/service/src/main.rs index 86f65405d9..742937344d 100644 --- a/service/src/main.rs +++ b/service/src/main.rs @@ -224,6 +224,9 @@ fn main() { enclave.dump_ias_ra_cert_to_disk().unwrap(); #[cfg(feature = "dcap")] { + // Hard coded 6-byte FMSPC that represents the state of devsgx03 + // TODO: either fetch this value from a list of pre-configured FMSPC values or + // extract the information out of the RA certificate let fmspc = [00u8, 0x90, 0x6E, 0xA1, 00, 00]; enclave.dump_dcap_collateral_to_disk(fmspc).unwrap(); enclave.dump_dcap_ra_cert_to_disk().unwrap(); From c23738ddc1777bcaf62d5a703419fa6a344e9f87 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Wed, 18 Jan 2023 09:25:20 +0100 Subject: [PATCH 33/39] Fix unsafe --- .../enclave-api/src/remote_attestation.rs | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/core-primitives/enclave-api/src/remote_attestation.rs b/core-primitives/enclave-api/src/remote_attestation.rs index d9a1a8ebf5..92cb68a0e0 100644 --- a/core-primitives/enclave-api/src/remote_attestation.rs +++ b/core-primitives/enclave-api/src/remote_attestation.rs @@ -65,10 +65,7 @@ pub trait RemoteAttestation { fn qe_get_quote_size(&self) -> EnclaveResult; - unsafe fn get_dcap_collateral( - &self, - fmspc: Fmspc, - ) -> EnclaveResult<*const sgx_ql_qve_collateral_t>; + fn get_dcap_collateral(&self, fmspc: Fmspc) -> EnclaveResult<*const sgx_ql_qve_collateral_t>; } /// call-backs that are made from inside the enclave (using o-call), to e-calls again inside the enclave @@ -185,7 +182,7 @@ impl RemoteAttestation for Enclave { let mut retval = sgx_status_t::SGX_SUCCESS; let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; - let collateral_ptr = unsafe { self.get_dcap_collateral(fmspc)? }; + let collateral_ptr = self.get_dcap_collateral(fmspc)?; let result = unsafe { ffi::generate_register_quoting_enclave_extrinsic( @@ -208,7 +205,7 @@ impl RemoteAttestation for Enclave { let mut retval = sgx_status_t::SGX_SUCCESS; let mut unchecked_extrinsic: Vec = vec![0u8; EXTRINSIC_MAX_SIZE]; - let collateral_ptr = unsafe { self.get_dcap_collateral(fmspc)? }; + let collateral_ptr = self.get_dcap_collateral(fmspc)?; let result = unsafe { ffi::generate_register_tcb_info_extrinsic( @@ -291,7 +288,7 @@ impl RemoteAttestation for Enclave { fn dump_dcap_collateral_to_disk(&self, fmspc: Fmspc) -> EnclaveResult<()> { let mut retval = sgx_status_t::SGX_SUCCESS; - let collateral_ptr = unsafe { self.get_dcap_collateral(fmspc)? }; + let collateral_ptr = self.get_dcap_collateral(fmspc)?; let result = unsafe { ffi::dump_dcap_collateral_to_disk(self.eid, &mut retval, collateral_ptr) }; let free_status = unsafe { sgx_ql_free_quote_verification_collateral(collateral_ptr) }; @@ -301,20 +298,22 @@ impl RemoteAttestation for Enclave { Ok(()) } - unsafe fn get_dcap_collateral( - &self, - fmspc: Fmspc, - ) -> EnclaveResult<*const sgx_ql_qve_collateral_t> { + fn get_dcap_collateral(&self, fmspc: Fmspc) -> EnclaveResult<*const sgx_ql_qve_collateral_t> { let pck_ra = b"processor\x00"; - let mut collateral_ptr: *mut sgx_ql_qve_collateral_t = std::mem::zeroed(); + // SAFETY: Just get a nullptr for the FFI to overwrite later + let mut collateral_ptr: *mut sgx_ql_qve_collateral_t = unsafe { std::mem::zeroed() }; + let collateral_ptr_ptr: *mut *mut sgx_ql_qve_collateral_t = &mut collateral_ptr; - let sgx_status = sgx_ql_get_quote_verification_collateral( - fmspc.as_ptr(), - fmspc.len() as uint16_t, //fmspc len is fixed in the function signature - pck_ra.as_ptr() as _, - collateral_ptr_ptr, - ); + // SAFETY: All parameters are properly initialized so the FFI call should be fine + let sgx_status = unsafe { + sgx_ql_get_quote_verification_collateral( + fmspc.as_ptr(), + fmspc.len() as uint16_t, //fmspc len is fixed in the function signature + pck_ra.as_ptr() as _, + collateral_ptr_ptr, + ) + }; ensure!(sgx_status == sgx_quote3_error_t::SGX_QL_SUCCESS, Error::SgxQuote(sgx_status)); Ok(collateral_ptr) } From 85ae349c390a8f5b54d97c01f93b6d36449b585f Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Wed, 18 Jan 2023 10:58:39 +0100 Subject: [PATCH 34/39] Switch implementation of separate_json_data_and_signature --- .../attestation-handler/Cargo.toml | 2 +- .../attestation-handler/src/collateral.rs | 43 ++++++++----------- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/core-primitives/attestation-handler/Cargo.toml b/core-primitives/attestation-handler/Cargo.toml index b5f111e52d..edc0fd46f0 100644 --- a/core-primitives/attestation-handler/Cargo.toml +++ b/core-primitives/attestation-handler/Cargo.toml @@ -17,7 +17,7 @@ log = { version = "0.4", default-features = false } base64 = { version = "0.13", features = ["alloc"], optional = true } chrono = { version = "0.4.19", features = ["alloc"], optional = true } rustls = { version = "0.19", optional = true } -serde_json = { version = "1.0", optional = true } +serde_json = { version = "1.0", features = ["preserve_order"], optional = true } thiserror = { version = "1.0", optional = true } webpki = { version = "0.21", optional = true } diff --git a/core-primitives/attestation-handler/src/collateral.rs b/core-primitives/attestation-handler/src/collateral.rs index e5e869133d..05cf46a777 100644 --- a/core-primitives/attestation-handler/src/collateral.rs +++ b/core-primitives/attestation-handler/src/collateral.rs @@ -15,11 +15,7 @@ */ use sgx_types::sgx_ql_qve_collateral_t; -use std::{ - io::Write, - string::{String, ToString}, - vec::Vec, -}; +use std::{io::Write, string::String, vec::Vec}; /// This is a rust-ified version of the type sgx_ql_qve_collateral_t. /// See Appendix A.3 in the document @@ -116,18 +112,15 @@ impl SgxQlQveCollateral { /// Returns the data part and signature as a pair fn separate_json_data_and_signature(data_name: &str, data: &[u8]) -> Option<(String, String)> { let json = String::from_utf8_lossy(data); - let json = json.trim(); - // search pattern is something like `{"data_name":`. Should be at the very beginning - let search_pattern = format!("{{\"{}\":", data_name); - let json = json.replace(&search_pattern, ""); - - let parts = json.split(r#","signature":""#).collect::>(); - if parts.len() != 2 || parts[1].len() < 2 { + let value: serde_json::Value = serde_json::from_str(&json).ok()?; + if value[data_name].is_null() || value["signature"].is_null() { return None } - let data = &parts[0]; - let signature = &parts[1][0..parts[1].len() - 2]; // Remove the two last chars that 'close' the json - Some((data.to_string(), signature.to_string())) + let data_json = serde_json::to_string(&value[data_name]).ok()?; + let signature = serde_json::to_string(&value["signature"]).ok()?; + // We want the signature without leading/ending " + let signature = signature.replace("\"", ""); + return Some((data_json, signature)) } fn write_data_to_disk(filename: &str, contents: &[u8]) { @@ -141,23 +134,21 @@ mod tests { use super::*; #[test] - fn separate_json_data_and_signature_tcb_info() { - let json = br#"{"tcbInfo":{thejsondata},"signature":"thesignature"}"#; + fn separate_json_data_and_signature() { + // A bit more complex json to ensure the ordering stays the same + let json = br#"{"tcbInfo":{"id":"SGX","version":3,"issueDate":"2022-11-17T12:45:32Z"},"signature":"71746f2"}"#; let (data, signature) = SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).unwrap(); - assert_eq!(data, r#"{thejsondata}"#); - assert_eq!(signature, "thesignature"); + assert_eq!(data, r#"{"id":"SGX","version":3,"issueDate":"2022-11-17T12:45:32Z"}"#); + assert_eq!(signature, "71746f2"); - let json = br#"{"tcbInfo":{thejsondata},"signature":"thesignature"#; - let (data, signature) = - SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).unwrap(); - assert_eq!(data, r#"{thejsondata}"#); - assert_eq!(signature, "thesignatu"); // cut off the last two characters of signature + let json = br#"{"tcbInfo":{not_a_valid_json},"nosignature":"thesignature"}"#; + assert!(SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).is_none()); - let json = br#"{"tcbInfo":{thejsondata},"nosignature":"thesignature"}"#; + let json = br#"{"tcbInfo":{"id":"SGX"},"nosignature":"thesignature"}"#; assert!(SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).is_none()); - let json = br#"{"tcbInfo":{thejsondata},"signature":""#; + let json = br#"{"tcbInfo":{"id":"SGX"},"signature":""#; assert!(SgxQlQveCollateral::separate_json_data_and_signature("tcbInfo", json).is_none()); } } From 9beacf8faf7bb802087149a9ddbea526ae7631bc Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Wed, 18 Jan 2023 11:21:37 +0100 Subject: [PATCH 35/39] Make clippy happy --- core-primitives/attestation-handler/src/collateral.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core-primitives/attestation-handler/src/collateral.rs b/core-primitives/attestation-handler/src/collateral.rs index 05cf46a777..503138a2a8 100644 --- a/core-primitives/attestation-handler/src/collateral.rs +++ b/core-primitives/attestation-handler/src/collateral.rs @@ -119,8 +119,8 @@ impl SgxQlQveCollateral { let data_json = serde_json::to_string(&value[data_name]).ok()?; let signature = serde_json::to_string(&value["signature"]).ok()?; // We want the signature without leading/ending " - let signature = signature.replace("\"", ""); - return Some((data_json, signature)) + let signature = signature.replace('\"', ""); + Some((data_json, signature)) } fn write_data_to_disk(filename: &str, contents: &[u8]) { From 2b870ea1e5fef5f549edfd29ce3563cd8608b190 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Thu, 19 Jan 2023 10:17:46 +0100 Subject: [PATCH 36/39] Add missing `use` --- core-primitives/attestation-handler/src/collateral.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/core-primitives/attestation-handler/src/collateral.rs b/core-primitives/attestation-handler/src/collateral.rs index 503138a2a8..acc51280eb 100644 --- a/core-primitives/attestation-handler/src/collateral.rs +++ b/core-primitives/attestation-handler/src/collateral.rs @@ -14,6 +14,7 @@ limitations under the License. */ +use crate::sgx_reexport_prelude::serde_json; use sgx_types::sgx_ql_qve_collateral_t; use std::{io::Write, string::String, vec::Vec}; From 52b452557c70e68ed88d385351520b7840159ddd Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Thu, 19 Jan 2023 10:18:21 +0100 Subject: [PATCH 37/39] Add missing feature `preserve_order` to `serde_json_sgx` --- core-primitives/attestation-handler/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-primitives/attestation-handler/Cargo.toml b/core-primitives/attestation-handler/Cargo.toml index edc0fd46f0..4568cb9304 100644 --- a/core-primitives/attestation-handler/Cargo.toml +++ b/core-primitives/attestation-handler/Cargo.toml @@ -26,7 +26,7 @@ base64_sgx = { package = "base64", rev = "sgx_1.1.3", git = "https://github.com/ chrono_sgx = { package = "chrono", git = "https://github.com/mesalock-linux/chrono-sgx", optional = true } num-bigint = { optional = true, git = "https://github.com/mesalock-linux/num-bigint-sgx" } rustls_sgx = { package = "rustls", rev = "sgx_1.1.3", features = ["dangerous_configuration"], git = "https://github.com/mesalock-linux/rustls", optional = true } -serde_json_sgx = { package = "serde_json", tag = "sgx_1.1.3", git = "https://github.com/mesalock-linux/serde-json-sgx", optional = true } +serde_json_sgx = { package = "serde_json", tag = "sgx_1.1.3", features = ["preserve_order"], git = "https://github.com/mesalock-linux/serde-json-sgx", optional = true } thiserror_sgx = { package = "thiserror", git = "https://github.com/mesalock-linux/thiserror-sgx", tag = "sgx_1.1.3", optional = true } webpki-roots = { git = "https://github.com/mesalock-linux/webpki-roots", branch = "mesalock_sgx" } webpki_sgx = { package = "webpki", git = "https://github.com/mesalock-linux/webpki", branch = "mesalock_sgx", optional = true } From 6cbd2504a874abf578d9df71895746aee19c0278 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Mon, 23 Jan 2023 14:12:17 +0100 Subject: [PATCH 38/39] Add compiler flag for std case --- .../attestation-handler/src/collateral.rs | 1 + enclave-runtime/Cargo.lock | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/core-primitives/attestation-handler/src/collateral.rs b/core-primitives/attestation-handler/src/collateral.rs index acc51280eb..66a91258ba 100644 --- a/core-primitives/attestation-handler/src/collateral.rs +++ b/core-primitives/attestation-handler/src/collateral.rs @@ -14,6 +14,7 @@ limitations under the License. */ +#[cfg(all(not(feature = "std"), feature = "sgx"))] use crate::sgx_reexport_prelude::serde_json; use sgx_types::sgx_ql_qve_collateral_t; use std::{io::Write, string::String, vec::Vec}; diff --git a/enclave-runtime/Cargo.lock b/enclave-runtime/Cargo.lock index 098ed74b6b..e31d754be2 100644 --- a/enclave-runtime/Cargo.lock +++ b/enclave-runtime/Cargo.lock @@ -1265,6 +1265,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29fba9abe4742d586dfd0c06ae4f7e73a1c2d86b856933509b269d82cdf06e18" +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + [[package]] name = "hashbrown" version = "0.12.3" @@ -1384,6 +1390,16 @@ dependencies = [ "syn 1.0.107", ] +[[package]] +name = "indexmap" +version = "1.6.1" +source = "git+https://github.com/mesalock-linux/indexmap-sgx#19f52458ba64dd7349a5d3a62227619a17e4db85" +dependencies = [ + "autocfg 1.1.0", + "hashbrown 0.9.1", + "sgx_tstd", +] + [[package]] name = "integer-sqrt" version = "0.1.5" @@ -3504,6 +3520,7 @@ name = "serde_json" version = "1.0.60" source = "git+https://github.com/mesalock-linux/serde-json-sgx?tag=sgx_1.1.3#380893814ad2a057758d825bab798aa117f7362a" dependencies = [ + "indexmap", "itoa 0.4.5", "ryu", "serde 1.0.118 (git+https://github.com/mesalock-linux/serde-sgx)", From 90c466d33ac9092fa6380f7e3eb6f1f0db023ed5 Mon Sep 17 00:00:00 2001 From: Thomas Niederberger Date: Wed, 25 Jan 2023 08:22:20 +0100 Subject: [PATCH 39/39] Make separate_json_data_and_signature robust to potential C-style null terminators --- core-primitives/attestation-handler/src/collateral.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core-primitives/attestation-handler/src/collateral.rs b/core-primitives/attestation-handler/src/collateral.rs index 66a91258ba..a4713c5c94 100644 --- a/core-primitives/attestation-handler/src/collateral.rs +++ b/core-primitives/attestation-handler/src/collateral.rs @@ -114,7 +114,9 @@ impl SgxQlQveCollateral { /// Returns the data part and signature as a pair fn separate_json_data_and_signature(data_name: &str, data: &[u8]) -> Option<(String, String)> { let json = String::from_utf8_lossy(data); - let value: serde_json::Value = serde_json::from_str(&json).ok()?; + // Remove potential C-style null terminators + let json = json.trim_matches(char::from(0)); + let value: serde_json::Value = serde_json::from_str(json).ok()?; if value[data_name].is_null() || value["signature"].is_null() { return None }