use super::{QuoteVerifier, VerifiedQuote, VerifyError};
use dcap_qvl::QuoteCollateralV3;
use dcap_qvl::verify::QuoteVerifier as DcapVerifier;
pub struct DcapQuoteVerifier {
collateral: QuoteCollateralV3,
now_secs: u64,
accepted_tcb: Vec<String>,
allow_debug: bool,
}
impl DcapQuoteVerifier {
pub fn new(collateral: QuoteCollateralV3, now_secs: u64) -> Self {
Self {
collateral,
now_secs,
accepted_tcb: vec!["UpToDate".to_string()],
allow_debug: false,
}
}
pub fn accept_tcb_statuses(mut self, statuses: Vec<String>) -> Self {
self.accepted_tcb = statuses;
self
}
pub fn allow_debug(mut self, allow: bool) -> Self {
self.allow_debug = allow;
self
}
}
impl QuoteVerifier for DcapQuoteVerifier {
fn verify_quote(&self, raw_quote: &[u8]) -> Result<VerifiedQuote, VerifyError> {
let report = DcapVerifier::new_prod()
.allow_debug(self.allow_debug)
.verify(raw_quote, &self.collateral, self.now_secs)
.map_err(|e| VerifyError::QuoteVerification(format!("{e:?}")))?;
if !self.accepted_tcb.iter().any(|s| s == &report.status) {
return Err(VerifyError::QuoteVerification(format!(
"unacceptable TCB status {:?} (advisories: {:?})",
report.status, report.advisory_ids
)));
}
let td = report.report.as_td10().ok_or_else(|| {
VerifyError::QuoteVerification("quote is not a TDX TD report".to_string())
})?;
Ok(VerifiedQuote {
mr_td: td.mr_td,
rt_mr: [td.rt_mr0, td.rt_mr1, td.rt_mr2, td.rt_mr3],
mr_seam: td.mr_seam,
mr_signer_seam: td.mr_signer_seam,
td_attributes: td.td_attributes,
xfam: td.xfam,
report_data: td.report_data,
})
}
}