Coverage Report

Created: 2025-12-31 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/MigTD/deps/td-shim/tdx-tdcall/src/tdreport.rs
Line
Count
Source
1
// Copyright (c) 2021 Intel Corporation
2
//
3
// SPDX-License-Identifier: BSD-2-Clause-Patent
4
5
use core::fmt;
6
use core::mem::{size_of, zeroed};
7
use core::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
8
use scroll::{Pread, Pwrite};
9
10
use crate::{
11
    td_call, TdCallError, TdcallArgs, TDCALL_STATUS_SUCCESS, TDCALL_TDREPORT, TDCALL_VERIFYREPORT,
12
};
13
14
pub const TD_REPORT_SIZE: usize = 0x400;
15
pub const TD_REPORT_ADDITIONAL_DATA_SIZE: usize = 64;
16
17
#[repr(C)]
18
#[derive(Debug, Pread, Pwrite, Clone, Copy)]
19
pub struct ReportType {
20
    /// Trusted Execution Environment (TEE) type
21
    /// 0x81 - TDX
22
    pub r#type: u8,
23
    /// Type-specific subtype
24
    pub subtype: u8,
25
    /// Type-specific version
26
    pub version: u8,
27
    pub reserved: u8,
28
}
29
30
#[repr(C)]
31
#[derive(Debug, Pread, Pwrite, Clone, Copy)]
32
pub struct ReportMac {
33
    /// Type header structure
34
    pub report_type: ReportType,
35
    pub reserved0: [u8; 12],
36
    /// CPU SVN
37
    pub cpu_svn: [u8; 16],
38
    /// SHA384 of the TEE_TCB_INFO
39
    pub tee_tcb_info_hash: [u8; 48],
40
    /// SHA384 of the TEE_INFO (TDG.VP.INFO)
41
    pub tee_info_hash: [u8; 48],
42
    /// A set of data used for communication between the caller and the target
43
    pub report_data: [u8; 64],
44
    pub reserved1: [u8; 32],
45
    /// The MAC over the REPORTMACSTRUCT with model-specific MAC
46
    pub mac: [u8; 32],
47
}
48
49
impl fmt::Display for ReportMac {
50
    // This trait requires `fmt` with this exact signature.
51
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52
0
        write!(
53
0
            f,
54
0
            "Report MAC:\n\tReport Type:\n\ttype: {:x?}\tsubtype: {:x?}\
55
0
                        \tversion: {:x?}\n\tCPU SVN:\n\t{:x?}\n\
56
0
                        \tTEE TCB Info Hash:\n\t{:x?}\n\tTEE Info Hash:\n\t{:x?}\n\
57
0
                        \tReport Data:\n\t{:x?}\n\tMAC:\n\t{:x?}\n",
58
            self.report_type.r#type,
59
            self.report_type.subtype,
60
            self.report_type.version,
61
            self.cpu_svn,
62
            self.tee_tcb_info_hash,
63
            self.tee_info_hash,
64
            self.report_data,
65
            self.mac
66
        )
67
0
    }
68
}
69
70
#[repr(C)]
71
#[derive(Debug, Pread, Pwrite, Clone, Copy)]
72
pub struct TeeTcbInfo {
73
    pub valid: [u8; 8],
74
    pub tee_tcb_svn: [u8; 16],
75
    pub mrseam: [u8; 48],
76
    pub mrsigner_seam: [u8; 48],
77
    pub attributes: [u8; 8],
78
    /// Reserved. Must be zero
79
    pub reserved: [u8; 111],
80
}
81
82
impl fmt::Display for TeeTcbInfo {
83
    // This trait requires `fmt` with this exact signature.
84
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85
0
        write!(
86
0
            f,
87
0
            "TEE TCB Info:\n\tValid:\n\t{:x?}\n\tTEE TCB SVN:\n\t{:x?}\n\
88
0
                        \tMR SEAM:\n\t{:x?}\n\tMR Signer SEAM:\n\t{:x?}\n\
89
0
                        \tAttributes:\n\t{:x?}\n",
90
            self.valid, self.tee_tcb_svn, self.mrseam, self.mrsigner_seam, self.attributes
91
        )
92
0
    }
93
}
94
95
/// Defined as the TDX-specific TEE_INFO part of the TDG.MR.REPORT.
96
/// Contains the measurements and initial configuration of the TD that
97
/// The output of the TDG.MR.REPORT function
98
#[repr(C)]
99
#[derive(Debug, Pread, Pwrite, Clone, Copy)]
100
pub struct TdInfo {
101
    /// TD's attributes
102
    pub attributes: [u8; 8],
103
    /// TD's XFAM
104
    pub xfam: [u8; 8],
105
    /// Measurement of the initial contents of the TD
106
    pub mrtd: [u8; 48],
107
    /// Software-defined ID for non-owner-defined configuration of
108
    /// the guest TD
109
    pub mrconfig_id: [u8; 48],
110
    /// Software-defined ID for the guest TD's owner
111
    pub mrowner: [u8; 48],
112
    /// Software-defined ID for owner-defined configuration of
113
    /// the guest TD
114
    pub mrownerconfig: [u8; 48],
115
    /// Runtime extendable measurement registers
116
    pub rtmr0: [u8; 48],
117
    pub rtmr1: [u8; 48],
118
    pub rtmr2: [u8; 48],
119
    pub rtmr3: [u8; 48],
120
    /// SHA384 hash of the TDINFO_STRUCTs of bound Service TDs
121
    pub servtd_hash: [u8; 48],
122
    /// Reserved. Must be zero
123
    pub reserved: [u8; 64],
124
}
125
126
impl fmt::Display for TdInfo {
127
    // This trait requires `fmt` with this exact signature.
128
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
129
0
        write!(
130
0
            f,
131
0
            "TdInfo:\n\tAttributes:\n\t{:x?}\n\txfam:\n\t{:x?}\n\
132
0
                        \tMR TD:\n\t{:x?}\n\tMR Config ID:\n\t{:x?}\n\
133
0
                        \tMR Owner:\n\t{:x?}\n\tMR Owner Config:\n\t{:x?}\n\
134
0
                        \tRTMR[0]:\n\t{:x?}\n\tRTMR[1]:\n\t{:x?}\n\
135
0
                        \tRTMR[2]:\n\t{:x?}\n\tRTMR[3]:\n\t{:x?}\n\
136
0
                        \tServTD Hash:\n\t{:x?}\n",
137
            self.attributes,
138
            self.xfam,
139
            self.mrtd,
140
            self.mrconfig_id,
141
            self.mrowner,
142
            self.mrownerconfig,
143
            self.rtmr0,
144
            self.rtmr1,
145
            self.rtmr2,
146
            self.rtmr3,
147
            self.servtd_hash
148
        )
149
0
    }
150
}
151
152
/// Known as the TDREPORT_STRUCT defined in TDX Module Spec.
153
/// The output of the TDG.MR.REPORT function
154
///
155
/// Detailed information can be found in TDX Module Spec section 'TDREPORT_STRUCT'
156
#[repr(C, packed)]
157
#[derive(Debug, Pread, Pwrite)]
158
pub struct TdxReport {
159
    pub report_mac: ReportMac,
160
    pub tee_tcb_info: TeeTcbInfo,
161
    pub reserved: [u8; 17],
162
    pub td_info: TdInfo,
163
}
164
165
impl fmt::Display for TdxReport {
166
    // This trait requires `fmt` with this exact signature.
167
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
168
0
        write!(
169
0
            f,
170
0
            "TDX Report:\n{}\n{}\n{}\n",
171
            self.report_mac, self.tee_tcb_info, self.td_info
172
        )
173
0
    }
174
}
175
176
impl TdxReport {
177
0
    pub fn as_bytes(&self) -> &[u8] {
178
0
        unsafe { &*slice_from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
179
0
    }
180
181
0
    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
182
0
        unsafe { &mut *slice_from_raw_parts_mut(self as *mut Self as *mut u8, size_of::<Self>()) }
183
0
    }
184
}
185
186
impl Default for TdxReport {
187
0
    fn default() -> Self {
188
0
        unsafe { zeroed() }
189
0
    }
190
}
191
192
#[repr(C, align(1024))]
193
struct TdxReportBuf(TdxReport);
194
195
#[repr(C, align(256))]
196
struct ReportMacBuf([u8; size_of::<ReportMac>()]);
197
198
#[repr(C, align(64))]
199
struct AdditionalDataBuf([u8; TD_REPORT_ADDITIONAL_DATA_SIZE]);
200
201
/// Create a TDREPORT_STRUCT structure that contains the measurements/configuration
202
/// information of the guest TD, measurements/configuration information of the Intel
203
/// TDX module and a REPORTMACSTRUCT
204
///
205
/// Details can be found in TDX module ABI spec section 'TDG.MR.REPORT'
206
0
pub fn tdcall_report(
207
0
    additional_data: &[u8; TD_REPORT_ADDITIONAL_DATA_SIZE],
208
0
) -> Result<TdxReport, TdCallError> {
209
0
    let mut report_buf = TdxReportBuf(TdxReport::default());
210
0
    let additional_data_buf = AdditionalDataBuf(*additional_data);
211
212
0
    let mut args = TdcallArgs {
213
0
        rax: TDCALL_TDREPORT,
214
0
        rcx: &mut report_buf as *mut _ as u64,
215
0
        rdx: &additional_data_buf as *const _ as u64,
216
0
        ..Default::default()
217
0
    };
218
219
0
    let ret = td_call(&mut args);
220
0
    if ret != TDCALL_STATUS_SUCCESS {
221
0
        return Err(args.r10.into());
222
0
    }
223
224
0
    Ok(report_buf.0)
225
0
}
226
227
/// Verify a cryptographic REPORTMACSTRUCT that describes the contents of a TD,
228
/// to determine that it was created on the current TEE on the current platform
229
///
230
/// Details can be found in TDX module ABI spec section 'TDG.MR.VERIFYREPORT'
231
0
pub fn tdcall_verify_report(report_mac: &[u8]) -> Result<(), TdCallError> {
232
0
    if report_mac.len() != size_of::<ReportMac>() {
233
0
        return Err(TdCallError::TdxExitInvalidParameters);
234
0
    }
235
236
0
    let mut report_mac_buf = ReportMacBuf([0u8; size_of::<ReportMac>()]);
237
0
    report_mac_buf.0.copy_from_slice(report_mac);
238
239
0
    let mut args = TdcallArgs {
240
0
        rax: TDCALL_VERIFYREPORT,
241
0
        rcx: &mut report_mac_buf as *mut _ as u64,
242
0
        ..Default::default()
243
0
    };
244
245
0
    let ret = td_call(&mut args);
246
0
    if ret != TDCALL_STATUS_SUCCESS {
247
0
        return Err(ret.into());
248
0
    }
249
250
0
    Ok(())
251
0
}
252
253
#[cfg(test)]
254
mod tests {
255
    use super::*;
256
257
    #[test]
258
    fn test_tdx_report_size() {
259
        assert_eq!(size_of::<TdxReport>(), 0x400);
260
    }
261
}