Skip to content

Commit

Permalink
verifier: Fetch VCEK cert from KDS instead of bailing
Browse files Browse the repository at this point in the history
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 <[email protected]>
Co-Authored-By: Xynnn_ <[email protected]>
  • Loading branch information
AdithyaKrishnan and Xynnn007 committed Nov 15, 2024
1 parent aec9296 commit 770fd0c
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 9 deletions.
14 changes: 8 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions deps/verifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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.workspace = true

[build-dependencies]
shadow-rs.workspace = true
Expand Down
48 changes: 46 additions & 2 deletions deps/verifier/src/snp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ use openssl::{
sha::sha384,
x509::{self, X509},
};
use reqwest::{
blocking::{get, Response as ReqwestResponse},
StatusCode,
};
use serde_json::json;
use sev::firmware::guest::AttestationReport;
use sev::firmware::host::{CertTableEntry, CertType};
Expand All @@ -32,6 +36,10 @@ const SNP_SPL_OID: Oid<'static> = oid!(1.3.6 .1 .4 .1 .3704 .1 .3 .3);
const TEE_SPL_OID: Oid<'static> = oid!(1.3.6 .1 .4 .1 .3704 .1 .3 .2);
const LOADER_SPL_OID: Oid<'static> = oid!(1.3.6 .1 .4 .1 .3704 .1 .3 .1);

// KDS URL parameters
const KDS_CERT_SITE: &str = "https://kdsintf.amd.com";
const KDS_VCEK: &str = "/vcek/v1";

#[derive(Debug)]
pub struct Snp {
vendor_certs: VendorCertificates,
Expand Down Expand Up @@ -84,8 +92,14 @@ 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 {
if chain.is_empty() {
fetch_vcek_from_kds(report)?
} else {
chain
}
} else {
fetch_vcek_from_kds(report)?
};

verify_report_signature(&report, &cert_chain, &self.vendor_certs)?;
Expand Down Expand Up @@ -307,6 +321,36 @@ fn get_common_name(cert: &x509::X509) -> Result<String> {
Ok(e.data().as_utf8()?.to_string())
}

// Function to request vcek from KDS. Return vcek in der format.
fn fetch_vcek_from_kds(att_report: AttestationReport) -> Result<Vec<CertTableEntry>> {
// 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<u8> =
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!("Unable to fetch VCEK from URL: {status:?}")),
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 770fd0c

Please sign in to comment.