From 40eae687a39cc16506aad072133cf8b06cd7f4a1 Mon Sep 17 00:00:00 2001 From: Jernej Kos Date: Wed, 26 Jun 2024 22:25:22 +0200 Subject: [PATCH 1/2] runtime: Add SGXConstraints::enclaves method --- runtime/src/consensus/registry.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/runtime/src/consensus/registry.rs b/runtime/src/consensus/registry.rs index de80d2a3dd9..a413efc9b99 100644 --- a/runtime/src/consensus/registry.rs +++ b/runtime/src/consensus/registry.rs @@ -701,13 +701,17 @@ pub enum SGXConstraints { } impl SGXConstraints { - /// Checks whether the given enclave identity is whitelisted. - pub fn contains_enclave(&self, eid: &sgx::EnclaveIdentity) -> bool { - let enclaves = match self { + /// Identities of allowed enclaves. + pub fn enclaves(&self) -> &Vec { + match self { Self::V0 { ref enclaves, .. } => enclaves, Self::V1 { ref enclaves, .. } => enclaves, - }; - enclaves.contains(eid) + } + } + + /// Checks whether the given enclave identity is whitelisted. + pub fn contains_enclave(&self, eid: &sgx::EnclaveIdentity) -> bool { + self.enclaves().contains(eid) } /// SGX quote policy. From 32385fdd48d44239ca7edb258152622269d0c4f8 Mon Sep 17 00:00:00 2001 From: Jernej Kos Date: Wed, 26 Jun 2024 22:27:35 +0200 Subject: [PATCH 2/2] runtime: Add VerifiedAttestation with more metadata Since verified attestations generated from TEE capabilities can include additional metadata like the enclave's view of consensus layer height at time of attestation, this allows such data to be used by callers. --- .changelog/5728.internal.md | 5 ++++ keymanager/src/churp/handler.rs | 2 +- keymanager/src/runtime/secrets.rs | 2 +- runtime/src/consensus/registry.rs | 48 ++++++++++++++++++++++++------ runtime/src/enclave_rpc/session.rs | 14 ++++----- 5 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 .changelog/5728.internal.md diff --git a/.changelog/5728.internal.md b/.changelog/5728.internal.md new file mode 100644 index 00000000000..2095071b277 --- /dev/null +++ b/.changelog/5728.internal.md @@ -0,0 +1,5 @@ +runtime: Add VerifiedAttestation with more metadata + +Since verified attestations generated from TEE capabilities can include +additional metadata like the enclave's view of consensus layer height at +time of attestation, this allows such data to be used by callers. diff --git a/keymanager/src/churp/handler.rs b/keymanager/src/churp/handler.rs index d73bed4b022..a611def8831 100644 --- a/keymanager/src/churp/handler.rs +++ b/keymanager/src/churp/handler.rs @@ -1272,7 +1272,7 @@ impl Churp { fn remote_enclave(ctx: &RpcContext) -> Result<&EnclaveIdentity> { let si = ctx.session_info.as_ref(); let si = si.ok_or(Error::NotAuthenticated)?; - Ok(&si.verified_quote.identity) + Ok(&si.verified_attestation.quote.identity) } /// Returns true if key manager policies should be ignored. diff --git a/keymanager/src/runtime/secrets.rs b/keymanager/src/runtime/secrets.rs index 10b2b326829..b5210c1836c 100644 --- a/keymanager/src/runtime/secrets.rs +++ b/keymanager/src/runtime/secrets.rs @@ -513,7 +513,7 @@ impl Secrets { fn authenticate(ctx: &RpcContext) -> Result<&EnclaveIdentity> { let si = ctx.session_info.as_ref(); let si = si.ok_or(KeyManagerError::NotAuthenticated)?; - Ok(&si.verified_quote.identity) + Ok(&si.verified_attestation.quote.identity) } /// Fetch current epoch from the consensus layer. diff --git a/runtime/src/consensus/registry.rs b/runtime/src/consensus/registry.rs index a413efc9b99..939939a2bc8 100644 --- a/runtime/src/consensus/registry.rs +++ b/runtime/src/consensus/registry.rs @@ -161,7 +161,7 @@ impl CapabilityTEE { &self, policy: &sgx::QuotePolicy, node_id: &signature::PublicKey, - ) -> anyhow::Result { + ) -> anyhow::Result { match self.hardware { TEEHardware::TEEHardwareInvalid => bail!("invalid TEE hardware"), TEEHardware::TEEHardwareIntelSGX => { @@ -216,12 +216,12 @@ impl EndorsedCapabilityTEE { self.verify_endorsement()?; // Verify TEE capability. - let verified_quote = self + let verified_attestation = self .capability_tee .verify(policy, &self.node_endorsement.public_key)?; Ok(VerifiedEndorsedCapabilityTEE { - verified_quote, + verified_attestation, node_id: Some(self.node_endorsement.public_key), }) } @@ -230,16 +230,25 @@ impl EndorsedCapabilityTEE { /// A verified endorsed CapabilityTEE structure. #[derive(Clone, Debug, Default)] pub struct VerifiedEndorsedCapabilityTEE { - /// Verified TEE quote. - pub verified_quote: sgx::VerifiedQuote, + /// Verified TEE remote attestation. + pub verified_attestation: VerifiedAttestation, /// Optional identifier of the node that endorsed the TEE capability. pub node_id: Option, } +impl From for VerifiedEndorsedCapabilityTEE { + fn from(verified_attestation: VerifiedAttestation) -> Self { + Self { + verified_attestation, + node_id: None, + } + } +} + impl From for VerifiedEndorsedCapabilityTEE { fn from(verified_quote: sgx::VerifiedQuote) -> Self { Self { - verified_quote, + verified_attestation: verified_quote.into(), node_id: None, } } @@ -734,6 +743,24 @@ impl SGXConstraints { } } +/// Verified remote attestation. +#[derive(Clone, Debug, Default)] +pub struct VerifiedAttestation { + /// Verified enclave quote. + pub quote: sgx::VerifiedQuote, + /// Enclave's view of the consensus layer height at the time of attestation. + pub height: Option, +} + +impl From for VerifiedAttestation { + fn from(quote: sgx::VerifiedQuote) -> Self { + Self { + quote, + height: None, + } + } +} + /// Intel SGX remote attestation. #[derive(Clone, Debug, cbor::Encode, cbor::Decode)] #[cbor(tag = "v")] @@ -787,7 +814,7 @@ impl SGXAttestation { node_id: &signature::PublicKey, rak: &signature::PublicKey, rek: &x25519::PublicKey, - ) -> anyhow::Result { + ) -> anyhow::Result { // Verify the quote. let verified_quote = self.quote().verify(policy)?; @@ -801,11 +828,14 @@ impl SGXAttestation { } => { let h = Self::hash(&verified_quote.report_data, node_id, *height, rek); signature.verify(rak, ATTESTATION_SIGNATURE_CONTEXT, &h)?; + + Ok(VerifiedAttestation { + quote: verified_quote, + height: Some(*height), + }) } _ => bail!("V0 attestation not supported"), } - - Ok(verified_quote) } } diff --git a/runtime/src/enclave_rpc/session.rs b/runtime/src/enclave_rpc/session.rs index 27cf5a14a33..6f406a2215c 100644 --- a/runtime/src/enclave_rpc/session.rs +++ b/runtime/src/enclave_rpc/session.rs @@ -9,10 +9,10 @@ use crate::{ common::{ crypto::signature::{self, PublicKey, Signature, Signer}, namespace::Namespace, - sgx::{ias, EnclaveIdentity, Quote, QuotePolicy, VerifiedQuote}, + sgx::{ias, EnclaveIdentity, Quote, QuotePolicy}, }, consensus::{ - registry::{EndorsedCapabilityTEE, VerifiedEndorsedCapabilityTEE}, + registry::{EndorsedCapabilityTEE, VerifiedAttestation, VerifiedEndorsedCapabilityTEE}, state::registry::ImmutableState as RegistryState, verifier::Verifier, }, @@ -53,8 +53,8 @@ enum SessionError { pub struct SessionInfo { /// RAK binding. pub rak_binding: RAKBinding, - /// Verified TEE quote. - pub verified_quote: VerifiedQuote, + /// Verified TEE remote attestation. + pub verified_attestation: VerifiedAttestation, /// Identifier of the node that endorsed the TEE. pub endorsed_by: Option, } @@ -281,7 +281,7 @@ impl Session { Ok(Some(Arc::new(SessionInfo { rak_binding, - verified_quote: vect.verified_quote, + verified_attestation: vect.verified_attestation, endorsed_by: vect.node_id, }))) } @@ -428,11 +428,11 @@ impl RAKBinding { // Ensure that the report data includes the hash of the node's RAK. // NOTE: For V2 this check is part of verify_inner so it is not really needed. - Identity::verify_binding(&vect.verified_quote, &self.rak_pub())?; + Identity::verify_binding(&vect.verified_attestation.quote, &self.rak_pub())?; // Verify MRENCLAVE/MRSIGNER. if let Some(ref remote_enclaves) = remote_enclaves { - if !remote_enclaves.contains(&vect.verified_quote.identity) { + if !remote_enclaves.contains(&vect.verified_attestation.quote.identity) { return Err(SessionError::MismatchedEnclaveIdentity.into()); } }