diff --git a/attestation-service/src/lib.rs b/attestation-service/src/lib.rs index a4d1256b3a..b49a7450ba 100644 --- a/attestation-service/src/lib.rs +++ b/attestation-service/src/lib.rs @@ -219,6 +219,7 @@ impl AttestationService { verification_request.tee ); + debug!("Processing {} claims from verifier", claims.len()); for (claims_from_tee_evidence, tee_class) in claims { tee_claims.push(TeeClaims { tee: verification_request.tee, @@ -228,13 +229,18 @@ impl AttestationService { runtime_data_claims: runtime_data_claims.clone(), }); } + debug!("Finished processing claims. Total tee_claims: {}", tee_claims.len()); } + debug!("Finished processing all verification requests. About to call rvps.get_digests()"); let reference_data_map = self .rvps .get_digests() .await - .map_err(|e| anyhow!("Generate reference data failed: {:?}", e))?; + .map_err(|e| { + debug!("rvps.get_digests() failed: {:?}", e); + anyhow!("Generate reference data failed: {:?}", e) + })?; debug!("reference_data_map: {:#?}", reference_data_map); let attestation_results_token = self diff --git a/deps/verifier/src/az_snp_vtpm/mod.rs b/deps/verifier/src/az_snp_vtpm/mod.rs index ab26c537d9..4f69703654 100644 --- a/deps/verifier/src/az_snp_vtpm/mod.rs +++ b/deps/verifier/src/az_snp_vtpm/mod.rs @@ -8,8 +8,9 @@ use crate::snp::{ get_common_name, get_oid_int, get_oid_octets, ProcessorGeneration, CERT_CHAINS, HW_ID_OID, LOADER_SPL_OID, SNP_SPL_OID, TEE_SPL_OID, UCODE_SPL_OID, }; +use strum::IntoEnumIterator; use crate::{InitDataHash, ReportData}; -use anyhow::{bail, Context, Result}; +use anyhow::{anyhow, bail, Context, Result}; use async_trait::async_trait; use az_snp_vtpm::certs::{AmdChain, Vcek}; use az_snp_vtpm::hcl::{HclReport, SNP_REPORT_SIZE}; @@ -29,10 +30,6 @@ const HCL_VMPL_VALUE: u32 = 0; const INITDATA_PCR: usize = 8; const SNP_REPORT_SIGNATURE_OFFSET: usize = 0x2a0; // 672 bytes -struct AzVendorCertificates { - ca_chain: AmdChain, -} - #[derive(Serialize, Deserialize)] struct Evidence { quote: Quote, @@ -40,14 +37,12 @@ struct Evidence { vcek: String, } -pub struct AzSnpVtpm { - vendor_certs: AzVendorCertificates, -} +pub struct AzSnpVtpm {} #[derive(Error, Debug)] pub enum CertError { - #[error("Failed to load Milan cert chain")] - LoadMilanCert, + #[error("Failed to validate VCEK against any known processor generation (Milan, Genoa, Turin)")] + NoMatchingProcessorGeneration, #[error("TPM quote nonce doesn't match expected report_data")] NonceMismatch, #[error("SNP report report_data mismatch")] @@ -62,21 +57,9 @@ pub enum CertError { Anyhow(#[from] anyhow::Error), } -// Azure vTPM still initialized to Milan only certs until az_snp_vtpm crate gets updated. impl AzSnpVtpm { pub fn new() -> Result { - let vendor_certs = CERT_CHAINS - .get(&ProcessorGeneration::Milan) - .ok_or(CertError::LoadMilanCert)? - .clone(); - Ok(Self { - vendor_certs: AzVendorCertificates { - ca_chain: AmdChain { - ask: vendor_certs.ask.into(), - ark: vendor_certs.ark.into(), - }, - }, - }) + Ok(Self {}) } } @@ -137,13 +120,55 @@ impl Verifier for AzSnpVtpm { let vcek = Vcek::from_pem(&evidence.vcek)?; - //Verify certificates - self.vendor_certs - .ca_chain - .validate() - .context("Failed to validate CA chain")?; - vcek.validate(&self.vendor_certs.ca_chain) - .context("Failed to validate VCEK")?; + // Try to validate VCEK against all known processor generations + // Wrap in spawn_blocking since certificate validation is CPU-intensive + let vcek = tokio::task::spawn_blocking(move || { + let mut validation_errors = Vec::new(); + let mut validated = false; + + for proc_gen in ProcessorGeneration::iter() { + let Some(vendor_certs) = CERT_CHAINS.get(&proc_gen) else { + continue; + }; + + let ca_chain = AmdChain { + ask: vendor_certs.ask.clone().into(), + ark: vendor_certs.ark.clone().into(), + }; + + // Try to validate with this processor generation + match ca_chain.validate() { + Ok(_) => match vcek.validate(&ca_chain) { + Ok(_) => { + log::info!("Successfully validated VCEK against {} processor certificates", proc_gen); + validated = true; + break; + } + Err(e) => { + log::debug!("VCEK validation failed for {}: {}", proc_gen, e); + validation_errors.push(format!("{}: {}", proc_gen, e)); + } + }, + Err(e) => { + log::debug!("CA chain validation failed for {}: {}", proc_gen, e); + validation_errors.push(format!("{} CA chain: {}", proc_gen, e)); + } + } + } + + if validated { + Ok(vcek) + } else { + Err(format!( + "{}. Tried: {}", + CertError::NoMatchingProcessorGeneration, + validation_errors.join("; ") + )) + } + }) + .await + .context("VCEK validation task panicked")? + .map_err(|e| anyhow!(e))?; verify_snp_report(&snp_report, &vcek)?; diff --git a/deps/verifier/src/intel_dcap/claims.rs b/deps/verifier/src/intel_dcap/claims.rs index 1ccc251ed9..afdd892fbd 100644 --- a/deps/verifier/src/intel_dcap/claims.rs +++ b/deps/verifier/src/intel_dcap/claims.rs @@ -114,7 +114,7 @@ pub(crate) fn prepare_custom_claims_map( claims_map } -fn get_sa_list(sa_list: &[c_char; 320]) -> Value { +fn get_sa_list(sa_list: &[c_char; 450]) -> Value { let c_str = unsafe { CStr::from_ptr(sa_list.as_ptr()) }; let advisory_ids = c_str.to_string_lossy(); diff --git a/rvps/src/lib.rs b/rvps/src/lib.rs index 35e9480eb2..aca8aa5c50 100644 --- a/rvps/src/lib.rs +++ b/rvps/src/lib.rs @@ -90,8 +90,10 @@ impl Rvps { } pub async fn get_digests(&self) -> Result> { + log::debug!("Rvps::get_digests() - about to call storage.get_values()"); let mut rv_map = HashMap::new(); let reference_values = self.storage.get_values().await?; + log::debug!("Rvps::get_digests() - got {} values", reference_values.len()); for rv in reference_values { if rv.expired() { diff --git a/rvps/src/storage/local_json/mod.rs b/rvps/src/storage/local_json/mod.rs index 9fd686b014..83b85c7a69 100644 --- a/rvps/src/storage/local_json/mod.rs +++ b/rvps/src/storage/local_json/mod.rs @@ -84,8 +84,11 @@ impl ReferenceValueStorage for LocalJson { } async fn get_values(&self) -> Result> { + log::debug!("LocalJson::get_values() - entering, file_path={}", self.file_path); let _ = self.lock.read().await; + log::debug!("LocalJson::get_values() - lock acquired, about to read file"); let file = tokio::fs::read(&self.file_path).await?; + log::debug!("LocalJson::get_values() - file read, {} bytes", file.len()); let rvs: Vec = serde_json::from_slice(&file)?; Ok(rvs) }