From 557b9ab2d05b94689fee1af6fb1eb47e417fffb5 Mon Sep 17 00:00:00 2001 From: Adithya Krishnan Kannan Date: Mon, 4 Nov 2024 09:56:59 -0600 Subject: [PATCH] verifier: Fetch VCEK cert from KDS instead of bailing Fetch the VCEK cert from the KDS if it is absent in the cert chain instead of just printing a bail statement stating that the VCEK is not found. Signed-off-by: Adithya Krishnan Kannan --- Cargo.lock | 78 ++++++++++++++++++++++++++++++------ Cargo.toml | 2 +- deps/verifier/Cargo.toml | 1 + deps/verifier/src/snp/mod.rs | 41 +++++++++++++++++-- 4 files changed, 105 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce84e44e5..149562eca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,7 +40,7 @@ dependencies = [ "encoding_rs", "flate2", "futures-core", - "h2", + "h2 0.3.26", "http 0.2.12", "httparse", "httpdate", @@ -494,6 +494,12 @@ dependencies = [ "syn 2.0.60", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "attestation-agent" version = "0.1.0" @@ -2022,6 +2028,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "2.4.1" @@ -2227,7 +2252,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -2250,6 +2275,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.0", "httparse", @@ -2677,7 +2703,7 @@ dependencies = [ "prost 0.12.6", "rand", "regorus", - "reqwest 0.12.8", + "reqwest 0.12.9", "rsa 0.9.6", "rstest", "scc", @@ -2705,7 +2731,7 @@ dependencies = [ "jwt-simple 0.11.9", "kbs_protocol", "log", - "reqwest 0.12.8", + "reqwest 0.12.9", "serde", "serde_json", "tokio", @@ -2734,7 +2760,7 @@ dependencies = [ "jwt-simple 0.12.9", "kbs-types", "log", - "reqwest 0.12.8", + "reqwest 0.12.9", "resource_uri", "serde", "serde_json", @@ -2762,7 +2788,7 @@ dependencies = [ "p12", "prost 0.11.9", "rand", - "reqwest 0.12.8", + "reqwest 0.12.9", "resource_uri", "ring", "serde", @@ -4137,7 +4163,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", @@ -4157,7 +4183,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration", + "system-configuration 0.5.1", "tokio", "tokio-native-tls", "tokio-rustls 0.24.1", @@ -4172,16 +4198,19 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" dependencies = [ "base64 0.22.1", "bytes", "cookie 0.18.1", "cookie_store", + "encoding_rs", + "futures-channel", "futures-core", "futures-util", + "h2 0.4.6", "http 1.1.0", "http-body 1.0.0", "http-body-util", @@ -4205,6 +4234,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", + "system-configuration 0.6.1", "tokio", "tokio-native-tls", "tokio-rustls 0.26.0", @@ -5162,7 +5192,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] @@ -5175,6 +5216,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "target-lexicon" version = "0.12.14" @@ -5477,7 +5528,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", @@ -5504,7 +5555,7 @@ dependencies = [ "axum", "base64 0.21.7", "bytes", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", @@ -5879,6 +5930,7 @@ dependencies = [ "kbs-types", "log", "openssl", + "reqwest 0.12.9", "rstest", "s390_pv", "scroll 0.11.0", diff --git a/Cargo.toml b/Cargo.toml index 73a7bc4df..f16cf94fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ jsonwebtoken = { version = "9", default-features = false } log = "0.4.17" prost = "0.12" regorus = { version = "0.1.5", default-features = false, features = ["regex", "base64", "time"] } -reqwest = { version = "0.12", default-features = false, features = ["default-tls"] } +reqwest = { version = "0.12", default-features = false, features = ["default-tls", "blocking"] } rstest = "0.18.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.89" diff --git a/deps/verifier/Cargo.toml b/deps/verifier/Cargo.toml index e65188a51..234325186 100644 --- a/deps/verifier/Cargo.toml +++ b/deps/verifier/Cargo.toml @@ -49,6 +49,7 @@ strum.workspace = true veraison-apiclient = { git = "https://github.com/chendave/rust-apiclient", branch = "token", optional = true } ear = { git = "https://github.com/veraison/rust-ear", rev = "43f7f480d09ea2ebc03137af8fbcd70fe3df3468", optional = true } x509-parser = { version = "0.14.0", optional = true } +reqwest = { version="0.12.9", features = ["blocking"] } [build-dependencies] shadow-rs.workspace = true diff --git a/deps/verifier/src/snp/mod.rs b/deps/verifier/src/snp/mod.rs index b5e4276b7..a6cf2f20f 100644 --- a/deps/verifier/src/snp/mod.rs +++ b/deps/verifier/src/snp/mod.rs @@ -19,6 +19,7 @@ use sev::firmware::guest::AttestationReport; use sev::firmware::host::{CertTableEntry, CertType}; use std::sync::OnceLock; use x509_parser::prelude::*; +use reqwest::{blocking::{get, Response as ReqwestResponse}, StatusCode}; #[derive(Serialize, Deserialize)] pub struct SnpEvidence { @@ -84,8 +85,10 @@ impl Verifier for Snp { cert_chain, } = serde_json::from_slice(evidence).context("Deserialize Quote failed.")?; - let Some(cert_chain) = cert_chain else { - bail!("Cert chain is unset"); + let cert_chain = if let Some(chain) = cert_chain{ + chain + } else { + request_endorsement_key_kds(report)? }; verify_report_signature(&report, &cert_chain, &self.vendor_certs)?; @@ -307,6 +310,38 @@ fn get_common_name(cert: &x509::X509) -> Result { Ok(e.data().as_utf8()?.to_string()) } +// Function to request vcek from KDS. Return vcek in der format. +fn request_endorsement_key_kds( + att_report: AttestationReport, +) -> Result, anyhow::Error> { + // KDS URL parameters + const KDS_CERT_SITE: &str = "https://kdsintf.amd.com"; + const KDS_VCEK: &str = "/vcek/v1"; + // Use attestation report to get data for URL + let hw_id: String = hex::encode(att_report.chip_id); + + let vcek_url: String = format!( + "{KDS_CERT_SITE}{KDS_VCEK}/Milan/\ + {hw_id}?blSPL={:02}&teeSPL={:02}&snpSPL={:02}&ucodeSPL={:02}", + att_report.reported_tcb.bootloader, + att_report.reported_tcb.tee, + att_report.reported_tcb.snp, + att_report.reported_tcb.microcode + ); + // VCEK in DER format + let vcek_rsp: ReqwestResponse = get(vcek_url).context("Unable to send request for VCEK")?; + + match vcek_rsp.status() { + StatusCode::OK => { + let vcek_rsp_bytes: Vec = + vcek_rsp.bytes().context("Unable to parse VCEK")?.to_vec(); + let key= CertTableEntry{cert_type: CertType::VCEK, data: vcek_rsp_bytes}; + Ok(vec![key]) + } + status => Err(anyhow::anyhow!("Unable to fetch VCEK from URL: {status:?}")), + } +} + #[cfg(test)] mod tests { use super::*; @@ -482,4 +517,4 @@ mod tests { let vendor_certs = load_milan_cert_chain().as_ref().unwrap(); verify_report_signature(&attestation_report, &cert_chain, vendor_certs).unwrap_err(); } -} +} \ No newline at end of file