dcap_rs/types/quotes/mod.rs
1use super::cert::Certificates;
2
3pub mod version_3;
4pub mod version_4;
5pub mod body;
6
7use body::EnclaveReport;
8
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct QuoteHeader {
11 pub version: u16, // [2 bytes]
12 // Version of the quote data structure - 4, 5
13 pub att_key_type: u16, // [2 bytes]
14 // Type of the Attestation Key used by the Quoting Enclave -
15 // 2 (ECDSA-256-with-P-256 curve)
16 // 3 (ECDSA-384-with-P-384 curve)
17 pub tee_type: u32, // [4 bytes]
18 // TEE for this Attestation
19 // 0x00000000: SGX
20 // 0x00000081: TDX
21 pub qe_svn: [u8; 2], // [2 bytes]
22 // Security Version of the Quoting Enclave - 1 (only applicable for SGX Quotes)
23 pub pce_svn: [u8; 2], // [2 bytes]
24 // Security Version of the PCE - 0 (only applicable for SGX Quotes)
25 pub qe_vendor_id: [u8; 16], // [16 bytes]
26 // Unique identifier of the QE Vendor.
27 // Value: 939A7233F79C4CA9940A0DB3957F0607 (IntelĀ® SGX QE Vendor)
28 // Note: Each vendor that decides to provide a customized Quote data structure should have
29 // unique ID.
30 pub user_data: [u8; 20], // [20 bytes]
31 // Custom user-defined data. For the IntelĀ® SGX and TDX DCAP Quote Generation Libraries,
32 // the first 16 bytes contain a Platform Identifier that is used to link a PCK Certificate to an Enc(PPID).
33}
34
35impl QuoteHeader {
36 pub fn from_bytes(raw_bytes: &[u8]) -> Self {
37 let version = u16::from_le_bytes([raw_bytes[0], raw_bytes[1]]);
38 let att_key_type = u16::from_le_bytes([raw_bytes[2], raw_bytes[3]]);
39 let tee_type = u32::from_le_bytes([raw_bytes[4], raw_bytes[5], raw_bytes[6], raw_bytes[7]]);
40 let mut qe_svn = [0; 2];
41 qe_svn.copy_from_slice(&raw_bytes[8..10]);
42 let mut pce_svn = [0; 2];
43 pce_svn.copy_from_slice(&raw_bytes[10..12]);
44 let mut qe_vendor_id = [0; 16];
45 qe_vendor_id.copy_from_slice(&raw_bytes[12..28]);
46 let mut user_data = [0; 20];
47 user_data.copy_from_slice(&raw_bytes[28..48]);
48
49 QuoteHeader {
50 version,
51 att_key_type,
52 tee_type,
53 qe_svn,
54 pce_svn,
55 qe_vendor_id,
56 user_data,
57 }
58 }
59
60 pub fn to_bytes(&self) -> [u8; 48] {
61 let mut raw_bytes = [0; 48];
62 raw_bytes[0..2].copy_from_slice(&self.version.to_le_bytes());
63 raw_bytes[2..4].copy_from_slice(&self.att_key_type.to_le_bytes());
64 raw_bytes[4..8].copy_from_slice(&self.tee_type.to_le_bytes());
65 raw_bytes[8..10].copy_from_slice(&self.qe_svn);
66 raw_bytes[10..12].copy_from_slice(&self.pce_svn);
67 raw_bytes[12..28].copy_from_slice(&self.qe_vendor_id);
68 raw_bytes[28..48].copy_from_slice(&self.user_data);
69
70 raw_bytes
71 }
72}
73
74#[derive(Clone, Debug, PartialEq, Eq)]
75pub struct QeAuthData {
76 pub size: u16,
77 pub data: Vec<u8>,
78}
79
80impl QeAuthData {
81 pub fn from_bytes(raw_bytes: &[u8]) -> QeAuthData {
82 let size = u16::from_le_bytes([raw_bytes[0], raw_bytes[1]]);
83 let data = raw_bytes[2..2+size as usize].to_vec();
84 QeAuthData {
85 size,
86 data,
87 }
88 }
89}
90
91#[derive(Clone, Debug, PartialEq, Eq)]
92pub struct CertData {
93 pub cert_data_type: u16, // [2 bytes]
94 // Determines type of data required to verify the QE Report Signature in the Quote Signature Data structure.
95 // 1 - (PCK identifier: PPID in plain text, CPUSVN, and PCESVN)
96 // 2 - (PCK identifier: PPID encrypted using RSA-2048-OAEP, CPUSVN, and PCESVN)
97 // 3 - (PCK identifier: PPID encrypted using RSA-2048-OAEP, CPUSVN, PCESVN, and QEID)
98 // 4 - (PCK Leaf Certificate in plain text; currently not supported)
99 // 5 - (Concatenated PCK Cert Chain)
100 // 6 - (QE Report Certification Data)
101 // 7 - (PLATFORM_MANIFEST; currently not supported)
102 pub cert_data_size: u32, // [4 bytes]
103 // Size of Certification Data field.
104 pub cert_data: Vec<u8>, // [variable bytes]
105 // Data required to verify the QE Report Signature depending on the value of the Certification Data Type:
106 // 1: Byte array that contains concatenation of PPID, CPUSVN, PCESVN (LE), PCEID (LE).
107 // 2: Byte array that contains concatenation of PPID encrypted using RSA-2048-OAEP, CPUSVN, PCESVN (LE), PCEID (LE).
108 // 3: Byte array that contains concatenation of PPID encrypted using RSA-3072-OAEP, CPUSVN, PCESVN (LE), PCEID (LE).
109 // 4: PCK Leaf Certificate
110 // 5: Concatenated PCK Cert Chain (PEM formatted). PCK Leaf Cert || Intermediate CA Cert || Root CA Cert
111 // 6: QE Report Certification Data
112 // 7: PLATFORM_MANIFEST
113}
114
115impl CertData {
116 pub fn from_bytes(raw_bytes: &[u8]) -> Self {
117 let cert_data_type = u16::from_le_bytes([raw_bytes[0], raw_bytes[1]]);
118 let cert_data_size = u32::from_le_bytes([raw_bytes[2], raw_bytes[3], raw_bytes[4], raw_bytes[5]]);
119 let cert_data = raw_bytes[6..6+cert_data_size as usize].to_vec();
120
121 CertData {
122 cert_data_type,
123 cert_data_size,
124 cert_data,
125 }
126 }
127
128 pub fn get_cert_data(&self) -> CertDataType {
129 match self.cert_data_type {
130 1 => CertDataType::Type1(self.cert_data.clone()),
131 2 => CertDataType::Type2(self.cert_data.clone()),
132 3 => CertDataType::Type3(self.cert_data.clone()),
133 4 => CertDataType::Type4(self.cert_data.clone()),
134 5 => CertDataType::CertChain(Certificates::from_pem(&self.cert_data)),
135 6 => CertDataType::QeReportCertData(QeReportCertData::from_bytes(&self.cert_data)),
136 7 => CertDataType::Type7(self.cert_data.clone()),
137 _ => CertDataType::Unused,
138 }
139 }
140}
141
142pub enum CertDataType {
143 Unused,
144 Type1(Vec<u8>),
145 Type2(Vec<u8>),
146 Type3(Vec<u8>),
147 Type4(Vec<u8>),
148 CertChain(Certificates),
149 QeReportCertData(QeReportCertData),
150 Type7(Vec<u8>),
151}
152
153#[derive(Clone, Debug)]
154pub struct QeReportCertData {
155 pub qe_report: EnclaveReport,
156 pub qe_report_signature: [u8; 64],
157 pub qe_auth_data: QeAuthData,
158 pub qe_cert_data: CertData,
159}
160
161impl QeReportCertData {
162 pub fn from_bytes(raw_bytes: &[u8]) -> Self {
163 // 384 bytes for qe_report
164 let qe_report = EnclaveReport::from_bytes(&raw_bytes[0..384]);
165 // 64 bytes for qe_report_signature
166 let mut qe_report_signature = [0; 64];
167 qe_report_signature.copy_from_slice(&raw_bytes[384..448]);
168 // qe auth data is variable length, we'll pass remaining bytes to the from_bytes method
169 let qe_auth_data = QeAuthData::from_bytes(&raw_bytes[448..]);
170 // get the length of qe_auth_data
171 let qe_auth_data_size = 2 + qe_auth_data.size as usize;
172 // finish off with the parsing of qe_cert_data
173 let qe_cert_data_start = 448 + qe_auth_data_size;
174 let qe_cert_data = CertData::from_bytes(&raw_bytes[qe_cert_data_start..]);
175
176 QeReportCertData {
177 qe_report,
178 qe_report_signature,
179 qe_auth_data,
180 qe_cert_data,
181 }
182 }
183}