Skip to content

Commit d56a2cf

Browse files
Xynnn007jialez0
authored andcommitted
AA/attester: add check_init_data support for TDX and SNP
In TDX, we use tdx_attest crate to get a raw hardware tdx report to parse the MRCONFIGID field. In SNP, we use sev crate to get a hardware report to parse HOSTDATA field. The input one should be resize as the evidence field inside the TEE evidence to compare. Signed-off-by: Magnus Kulke <magnuskulke@microsoft.com> Signed-off-by: Dan Mihai <dmihai@microsoft.com> Signed-off-by: Xynnn007 <xynnn@linux.alibaba.com>
1 parent 6f716c9 commit d56a2cf

File tree

8 files changed

+212
-2
lines changed

8 files changed

+212
-2
lines changed

Cargo.lock

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

attestation-agent/attester/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ kbs-types.workspace = true
1919
log.workspace = true
2020
nix = { version = "0.26.2", optional = true }
2121
occlum_dcap = { git = "https://github.com/occlum/occlum", tag = "v0.29.7", optional = true }
22+
scroll = { version = "0.11.0", default-features = false, features = ["derive"], optional = true }
2223
serde.workspace = true
2324
serde_json.workspace = true
2425
sev = { version = "1.2.0", default-features = false, features = [
2526
"snp",
2627
], optional = true }
2728
strum.workspace = true
2829
tdx-attest-rs = { git = "https://github.com/intel/SGXDataCenterAttestationPrimitives", tag = "DCAP_1.16", optional = true }
30+
thiserror.workspace = true
2931
# TODO: change it to "0.1", once released.
3032
csv-rs = { git = "https://github.com/openanolis/csv-rs", rev = "b74aa8c", optional = true }
3133
codicon = { version = "3.0", optional = true }
@@ -52,7 +54,7 @@ all-attesters = [
5254
"cca-attester",
5355
]
5456

55-
tdx-attester = ["tdx-attest-rs"]
57+
tdx-attester = ["scroll", "tdx-attest-rs"]
5658
sgx-attester = ["occlum_dcap"]
5759
az-snp-vtpm-attester = ["az-snp-vtpm"]
5860
az-tdx-vtpm-attester = ["az-tdx-vtpm"]

attestation-agent/attester/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use anyhow::*;
77
use kbs_types::Tee;
88

99
pub mod sample;
10+
pub mod utils;
1011

1112
#[cfg(feature = "az-snp-vtpm-attester")]
1213
pub mod az_snp_vtpm;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2024 Microsoft Corporation
2+
// Copyright (c) 2024 Alibaba Cloud
3+
//
4+
// SPDX-License-Identifier: Apache-2.0
5+
//
6+
7+
use thiserror::Error;
8+
9+
#[derive(Error, Debug)]
10+
pub enum GetHostDataError {
11+
#[error("Open Sev guest firmware failed: {0}")]
12+
OpenSevGuestFirmware(#[from] std::io::Error),
13+
14+
#[error("Get report failed: {0}")]
15+
GetReportError(#[from] sev::error::UserApiError),
16+
}
17+
18+
pub fn get_snp_host_data() -> Result<[u8; 32], GetHostDataError> {
19+
let mut firmware = sev::firmware::guest::Firmware::open()?;
20+
let report_data: [u8; 64] = [0; 64];
21+
let report = firmware.get_report(None, Some(report_data), Some(0))?;
22+
23+
Ok(report.host_data)
24+
}

attestation-agent/attester/src/snp/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// SPDX-License-Identifier: Apache-2.0
44
//
55

6+
use crate::utils::pad;
7+
68
use super::Attester;
79
use anyhow::*;
810
use serde::{Deserialize, Serialize};
@@ -11,6 +13,8 @@ use sev::firmware::guest::Firmware;
1113
use sev::firmware::host::CertTableEntry;
1214
use std::path::Path;
1315

16+
mod hostdata;
17+
1418
pub fn detect_platform() -> bool {
1519
Path::new("/sys/devices/platform/sev-guest").exists()
1620
}
@@ -47,4 +51,14 @@ impl Attester for SnpAttester {
4751

4852
serde_json::to_string(&evidence).context("Serialize SNP evidence failed")
4953
}
54+
55+
async fn check_init_data(&self, init_data: &[u8]) -> Result<()> {
56+
let hostdata = hostdata::get_snp_host_data().context("Get HOSTDATA failed")?;
57+
let init_data: [u8; 32] = pad(init_data);
58+
if init_data != hostdata {
59+
bail!("HOSTDATA does not match.");
60+
}
61+
62+
Ok(())
63+
}
5064
}

attestation-agent/attester/src/tdx/mod.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@
33
// SPDX-License-Identifier: Apache-2.0
44
//
55

6+
use crate::utils::pad;
7+
68
use super::Attester;
79
use anyhow::*;
810
use base64::Engine;
11+
use log::debug;
12+
use scroll::Pread;
913
use serde::{Deserialize, Serialize};
1014
use std::path::Path;
11-
use tdx_attest_rs;
15+
use tdx_attest_rs::{self, tdx_report_t};
16+
17+
mod report;
1218

1319
const TDX_REPORT_DATA_SIZE: usize = 64;
1420
const CCEL_PATH: &str = "/sys/firmware/acpi/tables/data/CCEL";
@@ -90,6 +96,33 @@ impl Attester for TdxAttester {
9096

9197
Ok(())
9298
}
99+
100+
async fn check_init_data(&self, init_data: &[u8]) -> Result<()> {
101+
let mut report = tdx_report_t { d: [0; 1024] };
102+
match tdx_attest_rs::tdx_att_get_report(None, &mut report) {
103+
tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS => {
104+
debug!("Successfully get report")
105+
}
106+
error_code => {
107+
bail!(
108+
"TDX Attester: Failed to get TD report. Error code: {:?}",
109+
error_code
110+
);
111+
}
112+
};
113+
114+
let td_report = report
115+
.d
116+
.pread::<report::TdReport>(0)
117+
.map_err(|e| anyhow!("Parse TD report failed: {:?}", e))?;
118+
119+
let init_data: [u8; 48] = pad(init_data);
120+
if init_data != td_report.tdinfo.mrconfigid {
121+
bail!("Init data does not match!");
122+
}
123+
124+
Ok(())
125+
}
93126
}
94127

95128
#[cfg(test)]
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright (c) 2024 Microsoft Corporation
2+
// Copyright (c) 2024 Alibaba Cloud
3+
//
4+
// SPDX-License-Identifier: Apache-2.0
5+
//
6+
7+
use scroll::Pread;
8+
9+
#[repr(C)]
10+
#[derive(Pread)]
11+
/// Type header of TDREPORT_STRUCT.
12+
pub struct TdTransportType {
13+
/// Type of the TDREPORT (0 - SGX, 81 - TDX, rest are reserved).
14+
pub type_: u8,
15+
16+
/// Subtype of the TDREPORT (Default value is 0).
17+
pub sub_type: u8,
18+
19+
/// TDREPORT version (Default value is 0).
20+
pub version: u8,
21+
22+
/// Added for future extension.
23+
pub reserved: u8,
24+
}
25+
26+
#[repr(C)]
27+
#[derive(Pread)]
28+
/// TDX guest report data, MAC and TEE hashes.
29+
pub struct ReportMac {
30+
/// TDREPORT type header.
31+
pub type_: TdTransportType,
32+
33+
/// Reserved for future extension.
34+
pub reserved1: [u8; 12],
35+
36+
/// CPU security version.
37+
pub cpu_svn: [u8; 16],
38+
39+
/// SHA384 hash of TEE TCB INFO.
40+
pub tee_tcb_info_hash: [u8; 48],
41+
42+
/// SHA384 hash of TDINFO_STRUCT.
43+
pub tee_td_info_hash: [u8; 48],
44+
45+
/// User defined unique data passed in TDG.MR.REPORT request.
46+
pub reportdata: [u8; 64],
47+
48+
/// Reserved for future extension.
49+
pub reserved2: [u8; 32],
50+
51+
/// CPU MAC ID.
52+
pub mac: [u8; 32],
53+
}
54+
55+
#[repr(C)]
56+
#[derive(Pread)]
57+
/// TDX guest measurements and configuration.
58+
pub struct TdInfo {
59+
/// TDX Guest attributes (like debug, spet_disable, etc).
60+
pub attr: [u8; 8],
61+
62+
/// Extended features allowed mask.
63+
pub xfam: u64,
64+
65+
/// Build time measurement register.
66+
pub mrtd: [u64; 6],
67+
68+
/// Software-defined ID for non-owner-defined configuration of the guest - e.g., run-time or OS configuration.
69+
pub mrconfigid: [u8; 48],
70+
71+
/// Software-defined ID for the guest owner.
72+
pub mrowner: [u64; 6],
73+
74+
/// Software-defined ID for owner-defined configuration of the guest - e.g., specific to the workload.
75+
pub mrownerconfig: [u64; 6],
76+
77+
/// Run time measurement registers.
78+
pub rtmr: [u64; 24],
79+
80+
/// For future extension.
81+
pub reserved: [u64; 14],
82+
}
83+
84+
#[repr(C)]
85+
#[derive(Pread)]
86+
/// Output of TDCALL[TDG.MR.REPORT].
87+
pub struct TdReport {
88+
/// Mac protected header of size 256 bytes.
89+
pub report_mac: ReportMac,
90+
91+
/// Additional attestable elements in the TCB are not reflected in the report_mac.
92+
pub tee_tcb_info: [u8; 239],
93+
94+
/// Added for future extension.
95+
pub reserved: [u8; 17],
96+
97+
/// Measurements and configuration data of size 512 bytes.
98+
pub tdinfo: TdInfo,
99+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) 2024 Microsoft Corporation
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
6+
pub fn pad<const T: usize>(input: &[u8]) -> [u8; T] {
7+
let mut output = [0; T];
8+
let len = input.len();
9+
if len > T {
10+
output.copy_from_slice(&input[..T]);
11+
} else {
12+
output[..len].copy_from_slice(input);
13+
}
14+
output
15+
}

0 commit comments

Comments
 (0)