From f440290657e6d79dfdb8ef5d551eb5e1ec26eec3 Mon Sep 17 00:00:00 2001 From: Jun Kimura Date: Mon, 16 Dec 2024 23:56:57 +0900 Subject: [PATCH] OK Signed-off-by: Jun Kimura --- Cargo.lock | 1 + app/Cargo.toml | 1 + app/src/commands/enclave.rs | 74 +++--- modules/attestation-report/src/errors.rs | 8 + modules/attestation-report/src/ias.rs | 8 - modules/attestation-report/src/lib.rs | 2 +- modules/attestation-report/src/report.rs | 54 +++- modules/enclave-api/src/api/command.rs | 13 +- modules/keymanager/src/lib.rs | 238 +++++++++--------- modules/remote-attestation/src/dcap.rs | 2 +- modules/remote-attestation/src/ias.rs | 2 +- .../remote-attestation/src/ias_simulation.rs | 2 +- .../lcp/service/enclave/v1/query.proto | 18 +- proto/src/descriptor.bin | Bin 100384 -> 100949 bytes proto/src/prost/lcp.service.enclave.v1.rs | 38 ++- tests/integration/src/lib.rs | 33 ++- 16 files changed, 301 insertions(+), 193 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b0a11cfe..fde40d95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3431,6 +3431,7 @@ name = "lcp" version = "0.0.1" dependencies = [ "anyhow", + "attestation-report", "clap 4.5.21", "crypto", "dirs", diff --git a/app/Cargo.toml b/app/Cargo.toml index ba9ff87a..be758db2 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -26,6 +26,7 @@ ecall-commands = { path = "../modules/ecall-commands" } crypto = { path = "../modules/crypto" } keymanager = { path = "../modules/keymanager" } remote-attestation = { path = "../modules/remote-attestation" } +attestation-report = { path = "../modules/attestation-report" } [build-dependencies] git2 = "0.19" diff --git a/app/src/commands/enclave.rs b/app/src/commands/enclave.rs index 77d90982..dbe1c7df 100644 --- a/app/src/commands/enclave.rs +++ b/app/src/commands/enclave.rs @@ -3,6 +3,7 @@ use crate::{ opts::{EnclaveOpts, Opts}, }; use anyhow::{anyhow, Result}; +use attestation_report::RAQuote; use clap::Parser; use crypto::Address; use ecall_commands::GenerateEnclaveKeyInput; @@ -87,10 +88,13 @@ fn run_generate_key, S: CommitStore>( ) -> Result<()> { let (target_info, _) = remote_attestation::init_quote(input.target_qe3)?; let res = enclave - .generate_enclave_key(GenerateEnclaveKeyInput { - target_info, - operator: input.get_operator()?, - }) + .generate_enclave_key( + GenerateEnclaveKeyInput { + target_info, + operator: input.get_operator()?, + }, + input.target_qe3, + ) .map_err(|e| anyhow!("failed to generate an enclave key: {:?}", e))?; println!("{}", res.pub_key.as_address()); Ok(()) @@ -121,37 +125,37 @@ fn run_list_keys, S: CommitStore>( }; let mut list_json = Vec::new(); for eki in list { - let ias_attested = eki.ias_report.is_some(); - let dcap_attested = eki.dcap_quote.is_some(); - - if ias_attested { - let avr = eki.ias_report.as_ref().unwrap().get_avr()?; - let report_data = avr.parse_quote()?.report_data(); - list_json.push(json! {{ - "type": "ias", - "address": eki.address.to_hex_string(), - "attested": true, - "report_data": report_data.to_string(), - "isv_enclave_quote_status": avr.isv_enclave_quote_status, - "advisory_ids": avr.advisory_ids, - "attested_at": avr.timestamp - }}); - } else if dcap_attested { - let dcap_quote = eki.dcap_quote.as_ref().unwrap(); - list_json.push(json! {{ - "type": "dcap", - "address": eki.address.to_hex_string(), - "attested": true, - "report_data": dcap_quote.report_data()?.to_string(), - "isv_enclave_quote_status": dcap_quote.tcb_status, - "advisory_ids": dcap_quote.advisory_ids, - "attested_at": dcap_quote.attested_at.to_string(), - }}); - } else { - list_json.push(json! {{ - "address": eki.address.to_hex_string(), - "attested": false, - }}); + match eki.ra_quote { + Some(RAQuote::IAS(report)) => { + let avr = report.get_avr()?; + let report_data = avr.parse_quote()?.report_data(); + list_json.push(json! {{ + "type": "ias", + "address": eki.address.to_hex_string(), + "attested": true, + "report_data": report_data.to_string(), + "isv_enclave_quote_status": avr.isv_enclave_quote_status, + "advisory_ids": avr.advisory_ids, + "attested_at": avr.timestamp + }}); + } + Some(RAQuote::DCAP(quote)) => { + list_json.push(json! {{ + "type": "dcap", + "address": eki.address.to_hex_string(), + "attested": true, + "report_data": quote.report_data()?.to_string(), + "isv_enclave_quote_status": quote.tcb_status, + "advisory_ids": quote.advisory_ids, + "attested_at": quote.attested_at.to_string(), + }}); + } + None => { + list_json.push(json! {{ + "address": eki.address.to_hex_string(), + "attested": false, + }}); + } } } println!("{}", serde_json::to_string(&list_json).unwrap()); diff --git a/modules/attestation-report/src/errors.rs b/modules/attestation-report/src/errors.rs index 72f75342..dfa05e4b 100644 --- a/modules/attestation-report/src/errors.rs +++ b/modules/attestation-report/src/errors.rs @@ -23,6 +23,14 @@ define_error! { format_args!("unexpected report data version: expected={} actual={}", e.expected, e.actual) }, + InvalidRaType + { + ra_type: u32 + } + |e| { + format_args!("Invalid RA type: ra_type={}", e.ra_type) + }, + MrenclaveMismatch { expected: Mrenclave, diff --git a/modules/attestation-report/src/ias.rs b/modules/attestation-report/src/ias.rs index b0f2a0a6..d36a9a9a 100644 --- a/modules/attestation-report/src/ias.rs +++ b/modules/attestation-report/src/ias.rs @@ -42,14 +42,6 @@ impl IASSignedReport { pub fn get_avr(&self) -> Result { serde_json::from_slice(self.avr.as_ref()).map_err(Error::serde_json) } - - pub fn to_json(&self) -> Result { - serde_json::to_string(self).map_err(Error::serde_json) - } - - pub fn from_json(json: &str) -> Result { - serde_json::from_str(json).map_err(Error::serde_json) - } } // IASAttestationVerificationReport represents Intel's Attestation Verification Report diff --git a/modules/attestation-report/src/lib.rs b/modules/attestation-report/src/lib.rs index 67503339..fa84a7c3 100644 --- a/modules/attestation-report/src/lib.rs +++ b/modules/attestation-report/src/lib.rs @@ -23,7 +23,7 @@ mod prelude { pub use dcap::DCAPQuote; pub use errors::Error; pub use ias::{verify_ias_report, IASAttestationVerificationReport, IASSignedReport}; -pub use report::{Quote, ReportData, VerifiableQuote}; +pub use report::{Quote, RAQuote, RAType, ReportData}; pub(crate) mod serde_base64 { use crate::prelude::*; diff --git a/modules/attestation-report/src/report.rs b/modules/attestation-report/src/report.rs index e963b3f8..091008cf 100644 --- a/modules/attestation-report/src/report.rs +++ b/modules/attestation-report/src/report.rs @@ -9,29 +9,67 @@ use sgx_types::{metadata::metadata_t, sgx_measurement_t, sgx_quote_t, sgx_report pub const REPORT_DATA_V1: u8 = 1; #[derive(Debug, Serialize, Deserialize)] -pub enum VerifiableQuote { +pub enum RAType { + IAS, + DCAP, +} + +impl RAType { + pub fn as_u32(&self) -> u32 { + match self { + Self::IAS => 1, + Self::DCAP => 2, + } + } + pub fn from_u32(v: u32) -> Result { + match v { + 1 => Ok(Self::IAS), + 2 => Ok(Self::DCAP), + _ => Err(Error::invalid_ra_type(v)), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum RAQuote { IAS(IASSignedReport), DCAP(DCAPQuote), } -impl VerifiableQuote { +impl RAQuote { + pub fn ra_type(&self) -> RAType { + match self { + RAQuote::IAS(_) => RAType::IAS, + RAQuote::DCAP(_) => RAType::DCAP, + } + } + pub fn attested_at(&self) -> Result { match self { - VerifiableQuote::IAS(report) => report.get_avr()?.attestation_time(), - VerifiableQuote::DCAP(quote) => Ok(quote.attested_at), + RAQuote::IAS(report) => report.get_avr()?.attestation_time(), + RAQuote::DCAP(quote) => Ok(quote.attested_at), } } + + pub fn from_json(json: &str) -> Result { + serde_json::from_str(json).map_err(Error::serde_json) + } + + pub fn to_json(&self) -> Result { + serde_json::to_string(self).map_err(Error::serde_json) + } } -impl From for VerifiableQuote { +impl From for RAQuote { fn from(report: IASSignedReport) -> Self { - VerifiableQuote::IAS(report) + RAQuote::IAS(report) } } -impl From for VerifiableQuote { +impl From for RAQuote { fn from(quote: DCAPQuote) -> Self { - VerifiableQuote::DCAP(quote) + RAQuote::DCAP(quote) } } diff --git a/modules/enclave-api/src/api/command.rs b/modules/enclave-api/src/api/command.rs index bd1ed1b0..d678b438 100644 --- a/modules/enclave-api/src/api/command.rs +++ b/modules/enclave-api/src/api/command.rs @@ -1,4 +1,5 @@ use crate::{EnclavePrimitiveAPI, Result}; +use attestation_report::RAType; use ecall_commands::{ AggregateMessagesInput, AggregateMessagesResponse, Command, CommandResponse, EnclaveManageCommand, EnclaveManageResponse, GenerateEnclaveKeyInput, @@ -14,6 +15,7 @@ pub trait EnclaveCommandAPI: EnclavePrimitiveAPI { fn generate_enclave_key( &self, input: GenerateEnclaveKeyInput, + is_target_qe3: bool, ) -> Result { let res = match self.execute_command( Command::EnclaveManage(EnclaveManageCommand::GenerateEnclaveKey(input)), @@ -22,8 +24,15 @@ pub trait EnclaveCommandAPI: EnclavePrimitiveAPI { CommandResponse::EnclaveManage(EnclaveManageResponse::GenerateEnclaveKey(res)) => res, _ => unreachable!(), }; - self.get_key_manager() - .save(res.sealed_ek.clone(), res.report)?; + self.get_key_manager().save( + res.sealed_ek.clone(), + res.report, + if is_target_qe3 { + RAType::DCAP + } else { + RAType::IAS + }, + )?; Ok(res) } diff --git a/modules/keymanager/src/lib.rs b/modules/keymanager/src/lib.rs index 988c82d5..f857900c 100644 --- a/modules/keymanager/src/lib.rs +++ b/modules/keymanager/src/lib.rs @@ -1,10 +1,14 @@ pub mod errors; pub use crate::errors::Error; use anyhow::anyhow; -use attestation_report::{DCAPQuote, IASSignedReport, ReportData, VerifiableQuote}; +use attestation_report::{RAQuote, RAType, ReportData}; use crypto::{Address, SealedEnclaveKey}; use lcp_types::{ - deserialize_bytes, proto::lcp::service::enclave::v1::EnclaveKeyInfo as ProtoEnclaveKeyInfo, + deserialize_bytes, + proto::lcp::service::enclave::v1::{ + enclave_key_info, DcapEnclaveKeyInfo, EnclaveKeyInfo as ProtoEnclaveKeyInfo, + IasEnclaveKeyInfo, + }, serialize_bytes, BytesTransmuter, Mrenclave, Time, }; use log::*; @@ -55,8 +59,8 @@ impl EnclaveKeyManager { ek_sealed BLOB NOT NULL, mrenclave TEXT NOT NULL, report BLOB NOT NULL, - ias_report TEXT, - dcap_quote TEXT, + ra_type INTEGER NOT NULL, + ra_quote TEXT, attested_at TEXT, created_at TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')), updated_at TEXT NOT NULL DEFAULT (DATETIME('now', 'localtime')) @@ -76,7 +80,7 @@ impl EnclaveKeyManager { .map_err(|e| Error::mutex_lock(e.to_string()))?; let mut stmt = conn.prepare( r#" - SELECT ek_sealed, mrenclave, report, ias_report, dcap_quote + SELECT ek_sealed, mrenclave, report, ra_type, ra_quote FROM enclave_keys WHERE ek_address = ?1 "#, @@ -106,24 +110,20 @@ impl EnclaveKeyManager { anyhow!("report: {:?}", e).into(), ) })?, - ias_report: match row.get::<_, Option>(3) { - Ok(None) => None, - Ok(Some(avr)) => Some(IASSignedReport::from_json(&avr).map_err(|e| { - rusqlite::Error::FromSqlConversionFailure( - 3, - Type::Text, - anyhow!("ias_report: {:?}", e).into(), - ) - })?), - Err(e) => return Err(e), - }, - dcap_quote: match row.get::<_, Option>(4) { + ra_type: RAType::from_u32(row.get::<_, i64>(3)? as u32).map_err(|e| { + rusqlite::Error::FromSqlConversionFailure( + 3, + Type::Integer, + anyhow!("ra_type: {:?}", e).into(), + ) + })?, + ra_quote: match row.get::<_, Option>(4) { Ok(None) => None, - Ok(Some(dq)) => Some(DCAPQuote::from_json(&dq).map_err(|e| { + Ok(Some(ra_quote)) => Some(RAQuote::from_json(&ra_quote).map_err(|e| { rusqlite::Error::FromSqlConversionFailure( 4, Type::Text, - anyhow!("dcap_quote: {:?}", e).into(), + anyhow!("ra_quote: {:?}", e).into(), ) })?), Err(e) => return Err(e), @@ -134,15 +134,20 @@ impl EnclaveKeyManager { } /// Save a sealed enclave key - pub fn save(&self, sealed_ek: SealedEnclaveKey, report: sgx_report_t) -> Result<(), Error> { + pub fn save( + &self, + sealed_ek: SealedEnclaveKey, + report: sgx_report_t, + ra_type: RAType, + ) -> Result<(), Error> { let conn = self .conn .lock() .map_err(|e| Error::mutex_lock(e.to_string()))?; let mut stmt = conn.prepare( r#" - INSERT INTO enclave_keys(ek_address, ek_sealed, mrenclave, report) - VALUES (?1, ?2, ?3, ?4) + INSERT INTO enclave_keys(ek_address, ek_sealed, mrenclave, report, ra_type) + VALUES (?1, ?2, ?3, ?4, ?5) "#, )?; let rd = ReportData::from(report.body.report_data); @@ -151,54 +156,29 @@ impl EnclaveKeyManager { sealed_ek.to_vec(), Mrenclave::from(report.body.mr_enclave).to_hex_string(), serialize_bytes(&report), + ra_type.as_u32() ])?; Ok(()) } /// Update the attestation verification report for the enclave key - pub fn save_verifiable_quote( - &self, - address: Address, - vquote: VerifiableQuote, - ) -> Result<(), Error> { + pub fn save_ra_quote(&self, address: Address, vquote: RAQuote) -> Result<(), Error> { let conn = self .conn .lock() .map_err(|e| Error::mutex_lock(e.to_string()))?; - - match vquote { - VerifiableQuote::IAS(ias_report) => { - let mut stmt = conn.prepare( - r#" - UPDATE enclave_keys - SET ias_report = ?1, attested_at = ?2 - WHERE ek_address = ?3 - "#, - )?; - stmt.execute(params![ - ias_report.to_json()?, - ias_report - .get_avr()? - .attestation_time()? - .as_unix_timestamp_secs(), - address.to_hex_string() - ])?; - } - VerifiableQuote::DCAP(dcap_quote) => { - let mut stmt = conn.prepare( - r#" - UPDATE enclave_keys - SET dcap_quote = ?1, attested_at = ?2 - WHERE ek_address = ?3 - "#, - )?; - stmt.execute(params![ - dcap_quote.to_json()?, - dcap_quote.attested_at.as_unix_timestamp_secs(), - address.to_hex_string() - ])?; - } - } + let mut stmt = conn.prepare( + r#" + UPDATE enclave_keys + SET ra_quote = ?1, attested_at = ?2 + WHERE ek_address = ?3 + "#, + )?; + stmt.execute(params![ + vquote.to_json()?, + vquote.attested_at()?.as_unix_timestamp_secs(), + address.to_hex_string() + ])?; Ok(()) } @@ -210,7 +190,7 @@ impl EnclaveKeyManager { .map_err(|e| Error::mutex_lock(e.to_string()))?; let mut stmt = conn.prepare( r#" - SELECT ek_address, ek_sealed, mrenclave, report, ias_report, dcap_quote + SELECT ek_address, ek_sealed, mrenclave, report, ra_type, ra_quote FROM enclave_keys WHERE attested_at IS NOT NULL AND mrenclave = ?1 ORDER BY attested_at DESC @@ -252,24 +232,20 @@ impl EnclaveKeyManager { anyhow!("report: {:?}", e).into(), ) })?, - ias_report: match row.get::<_, Option>(4) { - Ok(None) => None, - Ok(Some(avr)) => Some(IASSignedReport::from_json(&avr).map_err(|e| { - rusqlite::Error::FromSqlConversionFailure( - 4, - Type::Text, - anyhow!("ias_report: {:?}", e).into(), - ) - })?), - Err(e) => return Err(e), - }, - dcap_quote: match row.get::<_, Option>(5) { + ra_type: RAType::from_u32(row.get::<_, i64>(4)? as u32).map_err(|e| { + rusqlite::Error::FromSqlConversionFailure( + 4, + Type::Integer, + anyhow!("ra_type: {:?}", e).into(), + ) + })?, + ra_quote: match row.get::<_, Option>(5) { Ok(None) => None, - Ok(Some(dq)) => Some(DCAPQuote::from_json(&dq).map_err(|e| { + Ok(Some(ra_quote)) => Some(RAQuote::from_json(&ra_quote).map_err(|e| { rusqlite::Error::FromSqlConversionFailure( 5, Type::Text, - anyhow!("dcap_quote: {:?}", e).into(), + anyhow!("ra_quote: {:?}", e).into(), ) })?), Err(e) => return Err(e), @@ -288,7 +264,7 @@ impl EnclaveKeyManager { .map_err(|e| Error::mutex_lock(e.to_string()))?; let mut stmt = conn.prepare( r#" - SELECT ek_address, ek_sealed, mrenclave, report, ias_report, dcap_quote + SELECT ek_address, ek_sealed, mrenclave, report, ra_type, ra_quote FROM enclave_keys ORDER BY updated_at DESC "#, @@ -329,24 +305,20 @@ impl EnclaveKeyManager { anyhow!("report: {:?}", e).into(), ) })?, - ias_report: match row.get::<_, Option>(4) { - Ok(None) => None, - Ok(Some(avr)) => Some(IASSignedReport::from_json(&avr).map_err(|e| { - rusqlite::Error::FromSqlConversionFailure( - 4, - Type::Text, - anyhow!("ias_report: {:?}", e).into(), - ) - })?), - Err(e) => return Err(e), - }, - dcap_quote: match row.get::<_, Option>(5) { + ra_type: RAType::from_u32(row.get::<_, i64>(4)? as u32).map_err(|e| { + rusqlite::Error::FromSqlConversionFailure( + 4, + Type::Integer, + anyhow!("ra_type: {:?}", e).into(), + ) + })?, + ra_quote: match row.get::<_, Option>(5) { Ok(None) => None, - Ok(Some(dq)) => Some(DCAPQuote::from_json(&dq).map_err(|e| { + Ok(Some(avr)) => Some(RAQuote::from_json(&avr).map_err(|e| { rusqlite::Error::FromSqlConversionFailure( 5, Type::Text, - anyhow!("dcap_quote: {:?}", e).into(), + anyhow!("ra_quote: {:?}", e).into(), ) })?), Err(e) => return Err(e), @@ -378,32 +350,51 @@ pub struct SealedEnclaveKeyInfo { pub mrenclave: Mrenclave, #[serde_as(as = "BytesTransmuter")] pub report: sgx_report_t, - pub ias_report: Option, - pub dcap_quote: Option, + pub ra_type: RAType, + pub ra_quote: Option, } impl TryFrom for ProtoEnclaveKeyInfo { type Error = Error; fn try_from(value: SealedEnclaveKeyInfo) -> Result { - let ias_report = value - .ias_report - .ok_or_else(|| Error::unattested_enclave_key(format!("address={}", value.address)))?; - let attestation_time = ias_report.get_avr()?.parse_quote()?.attestation_time; - Ok(Self { - enclave_key_address: value.address.into(), - attestation_time: attestation_time.as_unix_timestamp_secs(), - report: ias_report.avr, - signature: ias_report.signature, - signing_cert: ias_report.signing_cert, - extension: Default::default(), - }) + match value.ra_quote { + Some(RAQuote::IAS(report)) => { + let attestation_time = report + .get_avr()? + .attestation_time()? + .as_unix_timestamp_secs(); + Ok(ProtoEnclaveKeyInfo { + key_info: Some(enclave_key_info::KeyInfo::Ias(IasEnclaveKeyInfo { + enclave_key_address: value.address.into(), + attestation_time, + report: report.avr, + signature: report.signature, + signing_cert: report.signing_cert, + })), + }) + } + Some(RAQuote::DCAP(dcap)) => { + let attestation_time = dcap.attested_at.as_unix_timestamp_secs(); + Ok(ProtoEnclaveKeyInfo { + key_info: Some(enclave_key_info::KeyInfo::Dcap(DcapEnclaveKeyInfo { + enclave_key_address: value.address.into(), + quote: dcap.raw, + attestation_time, + })), + }) + } + None => Err(Error::unattested_enclave_key(format!( + "address={}", + value.address + ))), + } } } #[cfg(test)] mod tests { use super::*; - use attestation_report::IASAttestationVerificationReport; + use attestation_report::{IASAttestationVerificationReport, IASSignedReport}; use chrono::{DateTime, Duration, Utc}; use rand::RngCore; @@ -416,14 +407,13 @@ mod tests { let report = create_report(mrenclave, address); let sealed_ek = create_sealed_sk(); assert_eq!(km.all_keys().unwrap().len(), 0); - km.save(sealed_ek, report).unwrap(); - assert!(km.load(address).unwrap().ias_report.is_none()); + km.save(sealed_ek, report, RAType::IAS).unwrap(); + assert!(km.load(address).unwrap().ra_quote.is_none()); assert_eq!(km.all_keys().unwrap().len(), 1); assert_eq!(km.available_keys(mrenclave).unwrap().len(), 0); let ias_report = create_ias_report(get_time(Duration::zero())); - km.save_verifiable_quote(address, ias_report.into()) - .unwrap(); - assert!(km.load(address).unwrap().ias_report.is_some()); + km.save_ra_quote(address, ias_report.into()).unwrap(); + assert!(km.load(address).unwrap().ra_quote.is_some()); assert_eq!(km.all_keys().unwrap().len(), 1); assert_eq!(km.available_keys(mrenclave).unwrap().len(), 1); address @@ -433,14 +423,13 @@ mod tests { let report = create_report(mrenclave, address); let sealed_ek = create_sealed_sk(); assert_eq!(km.all_keys().unwrap().len(), 1); - km.save(sealed_ek, report).unwrap(); - assert!(km.load(address).unwrap().ias_report.is_none()); + km.save(sealed_ek, report, RAType::IAS).unwrap(); + assert!(km.load(address).unwrap().ra_quote.is_none()); assert_eq!(km.all_keys().unwrap().len(), 2); assert_eq!(km.available_keys(mrenclave).unwrap().len(), 1); let ias_report = create_ias_report(get_time(Duration::minutes(1))); - km.save_verifiable_quote(address, ias_report.into()) - .unwrap(); - assert!(km.load(address).unwrap().ias_report.is_some()); + km.save_ra_quote(address, ias_report.into()).unwrap(); + assert!(km.load(address).unwrap().ra_quote.is_some()); assert_eq!(km.all_keys().unwrap().len(), 2); assert_eq!(km.available_keys(mrenclave).unwrap().len(), 2); } @@ -458,6 +447,23 @@ mod tests { ); } + #[test] + fn test_key_info_conversion() { + let km = EnclaveKeyManager::new_in_memory().unwrap(); + let mrenclave = create_mrenclave(); + let sealed_ek = create_sealed_sk(); + let address = create_address(); + let report = create_report(mrenclave, address); + km.save(sealed_ek, report, RAType::IAS).unwrap(); + let key_info = km.load(address).unwrap(); + assert!(ProtoEnclaveKeyInfo::try_from(key_info).is_err()); + let ias_report = create_ias_report(get_time(Duration::minutes(1))); + km.save_ra_quote(address, ias_report.into()).unwrap(); + let key_info = km.load(address).unwrap(); + let res = ProtoEnclaveKeyInfo::try_from(key_info); + assert!(res.is_ok(), "{:?}", res); + } + fn get_time(d: Duration) -> DateTime { Utc::now().checked_sub_signed(d).unwrap() } diff --git a/modules/remote-attestation/src/dcap.rs b/modules/remote-attestation/src/dcap.rs index a99b7119..69ec1f62 100644 --- a/modules/remote-attestation/src/dcap.rs +++ b/modules/remote-attestation/src/dcap.rs @@ -47,7 +47,7 @@ pub fn run_dcap_ra( let current_time = Time::now(); key_manager - .save_verifiable_quote( + .save_ra_quote( target_enclave_key, DCAPQuote::new( raw_quote, diff --git a/modules/remote-attestation/src/ias.rs b/modules/remote-attestation/src/ias.rs index 9f9f6027..644abaea 100644 --- a/modules/remote-attestation/src/ias.rs +++ b/modules/remote-attestation/src/ias.rs @@ -36,7 +36,7 @@ pub fn run_ias_ra( signed_report.get_avr()?.parse_quote()?.report_data() ); key_manager - .save_verifiable_quote(target_enclave_key, signed_report.clone().into()) + .save_ra_quote(target_enclave_key, signed_report.clone().into()) .map_err(|e| { Error::key_manager(format!("cannot save IAS AVR: {}", target_enclave_key), e) })?; diff --git a/modules/remote-attestation/src/ias_simulation.rs b/modules/remote-attestation/src/ias_simulation.rs index 45c571d0..d61125f7 100644 --- a/modules/remote-attestation/src/ias_simulation.rs +++ b/modules/remote-attestation/src/ias_simulation.rs @@ -43,7 +43,7 @@ pub fn run_ias_ra_simulation( signed_report.get_avr()?.parse_quote()?.report_data() ); key_manager - .save_verifiable_quote(target_enclave_key, signed_report.clone().into()) + .save_ra_quote(target_enclave_key, signed_report.clone().into()) .map_err(|e| { Error::key_manager( format!("cannot save IAS Simulation AVR: {}", target_enclave_key), diff --git a/proto/definitions/lcp/service/enclave/v1/query.proto b/proto/definitions/lcp/service/enclave/v1/query.proto index 092ecdc0..6274d4f2 100644 --- a/proto/definitions/lcp/service/enclave/v1/query.proto +++ b/proto/definitions/lcp/service/enclave/v1/query.proto @@ -20,12 +20,24 @@ message QueryAvailableEnclaveKeysResponse { } message EnclaveKeyInfo { + oneof key_info { + IASEnclaveKeyInfo ias = 1; + DCAPEnclaveKeyInfo dcap = 2; + } +} + +message IASEnclaveKeyInfo { bytes enclave_key_address = 1; - uint64 attestation_time = 2; - string report = 3; + string report = 2; + uint64 attestation_time = 3; bytes signature = 4; bytes signing_cert = 5; - bytes extension = 6; +} + +message DCAPEnclaveKeyInfo { + bytes enclave_key_address = 1; + bytes quote = 2; + uint64 attestation_time = 3; } message QueryEnclaveKeyRequest { diff --git a/proto/src/descriptor.bin b/proto/src/descriptor.bin index cf8cc6293b7b6675c19bf344fca160c12eaf50b7..8301150dee4eb2076e56f4b7a544aec56e1f0969 100644 GIT binary patch delta 1144 zcmb7Cy>1gh7`*+t^WG*Q_Try&h<_D3iH+ij9uWtSh-kp1p^B_xO0#Q-UeKYgTH@6q>yl?NlH=oICkN#A%*dsq0ABenk zdwl$K_%gg3P7lV9C+fOnqv3f#>SSx_+VTn`X$3{i5{F!qdrFWUTywMQU4Shfx%sN5g0| z86QQXXJNpwj1N}-_2whOEAr|FK@pY$}L}XyCi?Z=! zI!1*iegLjU8DjthVnrl&K(MR8PN!%3%qq=WB5_p=C{n10{%VS#tE$UZM-{8l!eUVb1Qx|bA9cpU6VApZQ8Z@=!&@~o14qZc} zC!itLCB+S32pRlMU|P2#(tbwt(pxjKH= z#s`33*Tw(>v1`)o%@gj?tT_ZTFnhVAT_E`N L=3iFGlUKh12_1$3 delta 657 zcmYL_J5Iwu5Qe=EFY8SN$wKVS13OAmz$p+d9b6y^l95tCP~rk1A=4mHQXsiP;t)u= z09T-*;}F#Ro9vqM+nMj5+4*`E?=Rx(vz)4T~E-G!6CHLj-#3xdf;jlo~b>%mx=a#4W7~aZXBRXV^?C(y7iU}T35Dx z&2}DioW?clQNKya;q_{d!|O@E3WwKAjPuagug8TO@<$1w_3LpVv_8fuMUlYMV7R@p zT`HC7CXU$~XLML@Rs, +} +/// Nested message and enum types in `EnclaveKeyInfo`. +pub mod enclave_key_info { + #[derive(::serde::Serialize, ::serde::Deserialize)] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum KeyInfo { + #[prost(message, tag = "1")] + Ias(super::IasEnclaveKeyInfo), + #[prost(message, tag = "2")] + Dcap(super::DcapEnclaveKeyInfo), + } +} +#[derive(::serde::Serialize, ::serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct IasEnclaveKeyInfo { #[prost(bytes = "vec", tag = "1")] pub enclave_key_address: ::prost::alloc::vec::Vec, - #[prost(uint64, tag = "2")] - pub attestation_time: u64, - #[prost(string, tag = "3")] + #[prost(string, tag = "2")] pub report: ::prost::alloc::string::String, + #[prost(uint64, tag = "3")] + pub attestation_time: u64, #[prost(bytes = "vec", tag = "4")] pub signature: ::prost::alloc::vec::Vec, #[prost(bytes = "vec", tag = "5")] pub signing_cert: ::prost::alloc::vec::Vec, - #[prost(bytes = "vec", tag = "6")] - pub extension: ::prost::alloc::vec::Vec, +} +#[derive(::serde::Serialize, ::serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DcapEnclaveKeyInfo { + #[prost(bytes = "vec", tag = "1")] + pub enclave_key_address: ::prost::alloc::vec::Vec, + #[prost(bytes = "vec", tag = "2")] + pub quote: ::prost::alloc::vec::Vec, + #[prost(uint64, tag = "3")] + pub attestation_time: u64, } #[derive(::serde::Serialize, ::serde::Deserialize)] #[allow(clippy::derive_partial_eq_without_eq)] diff --git a/tests/integration/src/lib.rs b/tests/integration/src/lib.rs index beb60615..8addd7c3 100644 --- a/tests/integration/src/lib.rs +++ b/tests/integration/src/lib.rs @@ -81,19 +81,25 @@ mod tests { let (target_info, _) = remote_attestation::init_quote(false)?; let operator = Address::from_hex_string("0x396e1ccc2f11cd6d2114c2449dad7751357e413e")?; - let op_ek_addr = match enclave.generate_enclave_key(GenerateEnclaveKeyInput { - operator: Some(operator), - target_info, - }) { + let op_ek_addr = match enclave.generate_enclave_key( + GenerateEnclaveKeyInput { + operator: Some(operator), + target_info, + }, + false, + ) { Ok(res) => res.pub_key.as_address(), Err(e) => { bail!("failed to generate an enclave key: {:?}!", e); } }; - let ek_addr = match enclave.generate_enclave_key(GenerateEnclaveKeyInput { - operator: None, - target_info, - }) { + let ek_addr = match enclave.generate_enclave_key( + GenerateEnclaveKeyInput { + operator: None, + target_info, + }, + false, + ) { Ok(res) => res.pub_key.as_address(), Err(e) => { bail!("failed to generate an enclave key: {:?}!", e); @@ -214,10 +220,13 @@ mod tests { ) -> Result<(), anyhow::Error> { let operator = Address::from_hex_string("0x396e1ccc2f11cd6d2114c2449dad7751357e413e")?; let (target_info, _) = remote_attestation::init_quote(false)?; - let signer = match enclave.generate_enclave_key(GenerateEnclaveKeyInput { - operator: Some(operator), - target_info, - }) { + let signer = match enclave.generate_enclave_key( + GenerateEnclaveKeyInput { + operator: Some(operator), + target_info, + }, + false, + ) { Ok(res) => res.pub_key.as_address(), Err(e) => { bail!("failed to generate an enclave key: {:?}!", e);