forked from confidential-containers/trustee
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmod.rs
133 lines (109 loc) · 4.33 KB
/
mod.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use anyhow::anyhow;
use log::{debug, error, info, warn};
use crate::tdx::claims::generate_parsed_claim;
use super::*;
use async_trait::async_trait;
use base64::Engine;
use eventlog::{CcEventLog, Rtmr};
use quote::{ecdsa_quote_verification, parse_tdx_quote};
use serde::{Deserialize, Serialize};
pub(crate) mod claims;
mod eventlog;
pub(crate) mod quote;
#[derive(Serialize, Deserialize, Debug)]
struct TdxEvidence {
// Base64 encoded CC Eventlog ACPI table
// refer to https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html#cc-event-log-acpi-table.
cc_eventlog: Option<String>,
// Base64 encoded TD quote.
quote: String,
}
#[derive(Debug, Default)]
pub struct Tdx {}
#[async_trait]
impl Verifier for Tdx {
async fn evaluate(
&self,
evidence: &[u8],
expected_report_data: &ReportData,
expected_init_data_hash: &InitDataHash,
) -> Result<TeeEvidenceParsedClaim> {
let tdx_evidence = serde_json::from_slice::<TdxEvidence>(evidence)
.context("Deserialize TDX Evidence failed.")?;
verify_evidence(expected_report_data, expected_init_data_hash, tdx_evidence)
.await
.map_err(|e| anyhow!("TDX Verifier: {:?}", e))
}
}
async fn verify_evidence(
expected_report_data: &ReportData<'_>,
expected_init_data_hash: &InitDataHash<'_>,
evidence: TdxEvidence,
) -> Result<TeeEvidenceParsedClaim> {
// Verify TD quote ECDSA signature.
let quote_bin = base64::engine::general_purpose::STANDARD.decode(evidence.quote)?;
ecdsa_quote_verification(quote_bin.as_slice()).await?;
info!("Quote DCAP check succeeded.");
// Parse quote and Compare report data
let quote = parse_tdx_quote("e_bin)?;
debug!("{quote}");
if let ReportData::Value(expected_report_data) = expected_report_data {
debug!("Check the binding of REPORT_DATA.");
let expected_report_data = regularize_data(expected_report_data, 64, "REPORT_DATA", "TDX");
if expected_report_data != quote.report_data() {
bail!("REPORT_DATA is different from that in TDX Quote");
}
}
if let InitDataHash::Value(expected_init_data_hash) = expected_init_data_hash {
debug!("Check the binding of MRCONFIGID.");
let expected_init_data_hash =
regularize_data(expected_init_data_hash, 48, "MRCONFIGID", "TDX");
if expected_init_data_hash != quote.mr_config_id() {
error!("MRCONFIGID (Initdata) verification failed.");
bail!("MRCONFIGID is different from that in TDX Quote");
}
}
info!("MRCONFIGID check succeeded.");
// Verify Integrity of CC Eventlog
let mut ccel_option = Option::default();
match &evidence.cc_eventlog {
Some(el) => {
let ccel_data = base64::engine::general_purpose::STANDARD.decode(el)?;
let ccel = CcEventLog::try_from(ccel_data)
.map_err(|e| anyhow!("Parse CC Eventlog failed: {:?}", e))?;
ccel_option = Some(ccel.clone());
log::debug!("Get CC Eventlog. \n{}\n", &ccel.cc_events);
let rtmr_from_quote = Rtmr {
rtmr0: quote.rtmr_0().try_into().expect("must be 48 bytes"),
rtmr1: quote.rtmr_1().try_into().expect("must be 48 bytes"),
rtmr2: quote.rtmr_2().try_into().expect("must be 48 bytes"),
rtmr3: quote.rtmr_3().try_into().expect("must be 48 bytes"),
};
ccel.integrity_check(rtmr_from_quote)?;
info!("CCEL integrity check succeeded.");
}
None => {
warn!("No CC Eventlog included inside the TDX evidence.");
}
}
// Return Evidence parsed claim
generate_parsed_claim(quote, ccel_option)
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn test_generate_parsed_claim() {
let ccel_bin = fs::read("./test_data/CCEL_data").unwrap();
let ccel = CcEventLog::try_from(ccel_bin).unwrap();
let quote_bin = fs::read("./test_data/tdx_quote_4.dat").unwrap();
let quote = parse_tdx_quote("e_bin).unwrap();
let parsed_claim = generate_parsed_claim(quote, Some(ccel));
assert!(parsed_claim.is_ok());
let _ = fs::write(
"./test_data/evidence_claim_output.txt",
format!("{:?}", parsed_claim.unwrap()),
);
}
}