Skip to content

Commit baab81c

Browse files
committed
feat(tdx-isa): add ioctl-based backend for TDX attestation and enhance error handling
1 parent 9c268d5 commit baab81c

File tree

5 files changed

+249
-108
lines changed

5 files changed

+249
-108
lines changed

Cargo.lock

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

intel-tdx/tdx-isa/Cargo.toml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ edition = "2024"
55
readme = "README.md"
66

77
[dependencies]
8-
tdx_module = { git = "https://github.com/intel/confidential-computing.tee.dcap.git", tag = "DCAP_1.24", package = "tdx-attest-rs" }
8+
tdx_module = { git = "https://github.com/intel/confidential-computing.tee.dcap.git", tag = "DCAP_1.24", package = "tdx-attest-rs", optional = true }
99
thiserror = "2"
10-
memory-layout = { version = "0.1", path = "../../memory-layout" }
10+
memory-layout = { version = "0.1", path = "../../memory-layout" }
11+
nix = { version = "0.30",features = ["ioctl"], optional = true }
12+
13+
[features]
14+
default = ["ioctl"]
15+
large_array_derive = ["memory-layout/large_array_derive"]
16+
serde = ["memory-layout/serde"]
17+
ioctl = ["dep:nix"]
18+
tdx-module = ["dep:tdx_module"]

intel-tdx/tdx-isa/src/lib.rs

Lines changed: 113 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,46 @@ extern crate memory_layout;
99

1010
use memory_layout::impl_default_clone_eq;
1111
use std::slice;
12-
use tdx_module::tdx_rtmr_event_t;
12+
use thiserror::Error;
1313

14+
#[cfg(feature = "tdx-module")]
1415
pub mod tdx_attest;
16+
#[cfg(feature = "ioctl")]
17+
pub mod tdx_ioctl;
1518

16-
use tdx_attest::{TdxAttestError, tdx_report_data_t, tdx_report_t};
19+
#[derive(Error, Debug, PartialEq, Eq)]
20+
pub enum TdxAttestError {
21+
/// Lower bound for error translations.
22+
#[error("Indicate min error to allow better translation, should be unexpected in production")]
23+
Min,
24+
#[error("The parameter is incorrect")]
25+
InvalidParameter,
26+
#[error("Not enough memory is available to complete this operation")]
27+
OutOfMemory,
28+
#[error("vsock related failure")]
29+
VsockFailure,
30+
#[error("Failed to get the TD Report")]
31+
ReportFailure,
32+
#[error("Failed to extend rtmr")]
33+
ExtendFailure,
34+
#[error("Request feature is not supported")]
35+
NotSupported,
36+
#[error("Failed to get the TD Quote")]
37+
QuoteFailure,
38+
#[error("The device driver return busy")]
39+
Busy,
40+
#[error("Failed to acess tdx attest device")]
41+
DeviceFailure,
42+
#[error("Only supported RTMR index is 2 and 3")]
43+
InvalidRtmrIndex,
44+
#[error(
45+
"The platform Quoting infrastructure does not support any of the keys described in att_key_id_list"
46+
)]
47+
UnsupportedAttKeyId,
48+
/// Upper bound for error translations.
49+
#[error("Indicate max error to allow better translation, should be unexpected in production")]
50+
Max,
51+
}
1752

1853
/// SHA384
1954
pub const TEE_HASH_384_SIZE: usize = 48;
@@ -34,8 +69,11 @@ pub const TEE_REPORT2_VERSION: usize = 0x0;
3469
/// VERSION for Report Type2 which mr_servicetd is used
3570
pub const TEE_REPORT2_VERSION_SERVICETD: usize = 0x1;
3671

37-
// Ref: https://github.com/intel/confidential-computing.sgx/blob/main/common/inc/sgx_report2.h
3872
struct_def! {
73+
/// Rust definition of `REPORTTYPE` from `REPORTMACSTRUCT`.
74+
///
75+
/// Ref: Intel TDX Module ABI Specification, section 4.7.4.
76+
/// Link to latest version (Sep 2025): https://cdrdv2.intel.com/v1/dl/getContent/733579
3977
#[repr(C, align(4))]
4078
#[derive(Clone, Debug, Default, Eq, PartialEq)]
4179
pub struct TeeReportType {
@@ -58,17 +96,19 @@ impl TeeReportType {
5896
pub const UNPADDED_SIZE: usize = 4;
5997
}
6098

61-
6299
pub const TDX_REPORT_MAC_STRUCT_SIZE: usize = 256;
63100
pub const TDX_REPORT_MAC_STRUCT_RESERVED1_BYTES: usize = 12;
64101
pub const TDX_REPORT_MAC_STRUCT_RESERVED2_BYTES: usize = 32;
65102

66-
// Ref: https://github.com/intel/confidential-computing.sgx/blob/main/common/inc/sgx_report2.h
67103
struct_def! {
104+
/// Rust definition of `REPORTMACSTRUCT` from `TDREPORT_STRUCT`.
105+
///
106+
/// Ref: Intel TDX Module ABI Specification, section 4.7.3.
107+
/// Link to latest version (Sep 2025): https://cdrdv2.intel.com/v1/dl/getContent/733579
68108
#[repr(C, align(256))]
69109
#[cfg_attr(
70110
feature = "large_array_derive",
71-
derive(Clone, Debug, Default, Eq, PartialEq)
111+
derive(Clone, Debug, Eq, PartialEq)
72112
)]
73113
pub struct TdxReportMac {
74114
/// ( 0) TEE Report type
@@ -78,7 +118,7 @@ struct_def! {
78118
/// ( 16) Security Version of the CPU
79119
pub cpu_svn: [u8; TEE_CPU_SVN_SIZE],
80120
/// ( 32) SHA384 of TEE_TCB_INFO for TEEs
81-
pub tee_tcb_info_hash:[u8; TEE_HASH_384_SIZE],
121+
pub tee_tcb_info_hash: [u8; TEE_HASH_384_SIZE],
82122
/// ( 80) SHA384 of TEE_INFO
83123
pub tee_info_hash: [u8; TEE_HASH_384_SIZE],
84124
/// (128) Data provided by the user
@@ -100,12 +140,16 @@ pub const TEE_TCB_INFO_SIZE: usize = 239;
100140
pub const TDX_REPORT_RESERVED_SIZE: usize = 17;
101141
pub const TEE_INFO_SIZE: usize = 512;
102142

103-
// Ref: https://github.com/intel/confidential-computing.sgx/blob/main/common/inc/sgx_report2.h
104143
struct_def! {
144+
/// Rust definition of `TDREPORT_STRUCT` from the output of the `TDG.MR.REPORT` function.
145+
/// `TDG.MR.REPORT` is one variant of syscall `TDCALL`.
146+
///
147+
/// Ref: Intel TDX Module ABI Specification, section 4.7.2.
148+
/// Link to latest version (Sep 2025): https://cdrdv2.intel.com/v1/dl/getContent/733579
105149
#[repr(C, align(1024))]
106150
#[cfg_attr(
107151
feature = "large_array_derive",
108-
derive(Clone, Debug, Default, Eq, PartialEq)
152+
derive(Clone, Debug, Eq, PartialEq)
109153
)]
110154
pub struct TdxReport {
111155
/// ( 0) Report mac struct for SGX report type 2
@@ -119,19 +163,6 @@ struct_def! {
119163
}
120164
}
121165

122-
impl From<tdx_report_t> for TdxReport {
123-
fn from(report: tdx_report_t) -> Self {
124-
Self::try_copy_from(&report.d).expect("validated size")
125-
}
126-
}
127-
128-
impl From<TdxReport> for tdx_report_t {
129-
fn from(report: TdxReport) -> Self {
130-
let mut d = [0u8; TDX_REPORT_SIZE];
131-
d.copy_from_slice(report.as_ref());
132-
tdx_report_t { d }
133-
}
134-
}
135166

136167
impl TdxReport {
137168
pub const UNPADDED_SIZE: usize = 1024;
@@ -148,35 +179,28 @@ impl TdxReport {
148179
/// # Errors
149180
/// Propagates the underlying TDX attestation error code.
150181
pub fn get_report(report_data: [u8; TDX_REPORT_DATA_SIZE]) -> Result<Self, TdxAttestError> {
151-
let mut tdx_report = tdx_report_t {
152-
d: [0; TDX_REPORT_SIZE],
153-
};
154-
let report_data = tdx_report_data_t { d: report_data };
155-
tdx_attest::parse_tdx_attest_error(tdx_attest::tdx_att_get_report(
156-
Some(&report_data),
157-
&mut tdx_report,
158-
))?;
159-
Ok(tdx_report.into())
182+
#[cfg(feature = "ioctl")]
183+
{
184+
return tdx_ioctl::get_report(report_data);
185+
}
186+
#[cfg(all(not(feature = "ioctl"), feature = "tdx-module"))]
187+
{
188+
return tdx_attest::get_report(report_data);
189+
}
190+
#[cfg(not(any(feature = "ioctl", feature = "tdx-module")))]
191+
{
192+
Err(TdxAttestError::NotSupported)
193+
}
160194
}
161195
}
162196

163197
pub const TDX_RTMR_EVENT_HEADER_SIZE: usize = 68;
164198
/// Size of the RTMR extend data field in bytes.
165199
pub const TDX_RTMR_EXTEND_DATA_SIZE: usize = 48;
166200

167-
#[repr(u8)]
168-
pub enum TdxStatus {
169-
Success = 0,
170-
InvalidParameter = 1,
171-
AccessDenied = 2,
172-
InternalError = 255,
173-
}
174-
175-
pub const REMR_EXTEND_DATA_SIZE: usize = 48;
176-
177201
/// Extend one of the TDX runtime measurement registers (RTMRs).
178202
///
179-
/// RTMR[rtmr_index] = SHA384(RTMR[rtmr_index] || extend_data)
203+
/// `RTMR[rtmr_index] = SHA384(RTMR[rtmr_index] || extend_data)`
180204
/// - `rtmr_index`: only supported RTMR index is 2 and 3.
181205
/// - `event_data`: field is currently expected to be empty by the platform
182206
/// quoting infrastructure.
@@ -193,48 +217,66 @@ pub const REMR_EXTEND_DATA_SIZE: usize = 48;
193217
/// not supported.
194218
pub fn extend_rtmr(
195219
rtmr_index: u64,
196-
extend_data: [u8; REMR_EXTEND_DATA_SIZE],
220+
extend_data: [u8; TDX_RTMR_EXTEND_DATA_SIZE],
197221
) -> Result<(), TdxAttestError> {
198-
match rtmr_index {
199-
2..=3 => (),
200-
_ => return Err(TdxAttestError::InvalidRtmrIndex),
201-
};
202-
// From: `tdx_attest_sys` crate generated binding code
203-
// ```C
204-
// typedef struct _tdx_rtmr_event_t {
205-
// uint32_t version;
206-
// uint64_t rtmr_index;
207-
// uint8_t extend_data[48];
208-
// uint32_t event_type;
209-
// uint32_t event_data_size;
210-
// uint8_t event_data[];
211-
// } tdx_rtmr_event_t;
212-
// ```
213-
let mut rtmr_event = [0u8; std::mem::size_of::<tdx_rtmr_event_t>()];
214-
rtmr_event[0..0 + 4].copy_from_slice(&1u32.to_ne_bytes());
215-
rtmr_event[4..4 + 8].copy_from_slice(&rtmr_index.to_ne_bytes());
216-
rtmr_event[12..12 + REMR_EXTEND_DATA_SIZE].copy_from_slice(&extend_data);
217-
218-
tdx_attest::parse_tdx_attest_error(tdx_attest::tdx_att_extend(&rtmr_event))
222+
#[cfg(feature = "ioctl")]
223+
{
224+
return tdx_ioctl::extend_rtmr(rtmr_index, extend_data);
225+
}
226+
#[cfg(all(not(feature = "ioctl"), feature = "tdx-module"))]
227+
{
228+
return tdx_attest::extend_rtmr(rtmr_index, extend_data);
229+
}
230+
#[cfg(not(any(feature = "ioctl", feature = "tdx-module")))]
231+
{
232+
Err(TdxAttestError::NotSupported)
233+
}
219234
}
220235

221236
#[cfg(test)]
222237
mod tests {
223238
use super::*;
224239

225240
#[test]
226-
fn test_tdx_att_get_report() {
241+
fn test_tdx_att_get_report_invalid_device() {
242+
let expected_err = if cfg!(any(feature = "ioctl", feature = "tdx-module")) {
243+
TdxAttestError::DeviceFailure
244+
} else {
245+
TdxAttestError::NotSupported
246+
};
227247
let result = TdxReport::get_report([0; TDX_REPORT_DATA_SIZE]);
228-
assert!(matches!(result, Err(TdxAttestError::DeviceFailure)));
248+
match result {
249+
Ok(_) => panic!("expecting error"),
250+
Err(err) => assert_eq!(err, expected_err),
251+
}
252+
}
253+
254+
#[test]
255+
fn test_tdx_att_extend_invalid_device() {
256+
let expected_err = if cfg!(any(feature = "ioctl", feature = "tdx-module")) {
257+
TdxAttestError::DeviceFailure
258+
} else {
259+
TdxAttestError::NotSupported
260+
};
261+
262+
let mut extend_data = [0u8; TDX_RTMR_EXTEND_DATA_SIZE];
263+
extend_data[0] = 123;
264+
let err = extend_rtmr(2, extend_data).expect_err("expecting err");
265+
assert_eq!(err, expected_err);
229266
}
230267

231268
#[test]
232-
fn test_tdx_att_extend() {
269+
fn test_tdx_att_extend_invalid_index() {
270+
let expected_err = if cfg!(any(feature = "ioctl", feature = "tdx-module")) {
271+
TdxAttestError::InvalidRtmrIndex
272+
} else {
273+
TdxAttestError::NotSupported
274+
};
275+
233276
let mut extend_data = [0u8; TDX_RTMR_EXTEND_DATA_SIZE];
234277
extend_data[0] = 123;
235-
let result = extend_rtmr(2, extend_data);
236-
assert!(matches!(result, Err(TdxAttestError::DeviceFailure)));
237-
let result = extend_rtmr(77, extend_data);
238-
assert!(matches!(result, Err(TdxAttestError::InvalidRtmrIndex)));
278+
279+
let err = extend_rtmr(77, extend_data).expect_err("expecting err");
280+
assert_eq!(err, expected_err);
239281
}
240282
}

0 commit comments

Comments
 (0)