dcap_rs/types/
collaterals.rs

1use x509_parser::{certificate::X509Certificate, revocation_list::CertificateRevocationList};
2
3use super::enclave_identity::EnclaveIdentityV2;
4use super::tcbinfo::{TcbInfoV2, TcbInfoV3};
5
6use crate::utils::cert::{parse_crl_der, parse_x509_der, parse_x509_der_multi, pem_to_der};
7
8#[derive(Clone, Debug)]
9pub struct IntelCollateral {
10    pub tcbinfo_bytes: Option<Vec<u8>>,
11    pub qeidentity_bytes: Option<Vec<u8>>,
12    pub sgx_intel_root_ca_der: Option<Vec<u8>>,
13    pub sgx_tcb_signing_der: Option<Vec<u8>>,
14    pub sgx_pck_certchain_der: Option<Vec<u8>>,
15    pub sgx_intel_root_ca_crl_der: Option<Vec<u8>>,
16    pub sgx_pck_processor_crl_der: Option<Vec<u8>>,
17    pub sgx_pck_platform_crl_der: Option<Vec<u8>>,
18}
19
20// builder pattern for IntelCollateralV3
21impl IntelCollateral {
22    pub fn new() -> IntelCollateral {
23        IntelCollateral {
24            tcbinfo_bytes: None,
25            qeidentity_bytes: None,
26            sgx_intel_root_ca_der: None,
27            sgx_tcb_signing_der: None,
28            sgx_pck_certchain_der: None,
29            sgx_intel_root_ca_crl_der: None,
30            sgx_pck_processor_crl_der: None,
31            sgx_pck_platform_crl_der: None,
32        }
33    }
34
35    pub fn to_bytes(&self) -> Vec<u8> {
36        // serialization scheme is simple: the bytestream is made of 2 parts 
37        // the first contains a u32 length for each of the members
38        // the second contains the actual data
39        // [lengths of each of the member][data segment]
40
41        let tcbinfo_bytes = match self.tcbinfo_bytes {
42            Some(ref tcbinfo) => tcbinfo.as_slice(),
43            None => &[],
44        };
45
46        let qeidentity_bytes = match self.qeidentity_bytes {
47            Some(ref qeidentity) => qeidentity.as_slice(),
48            None => &[],
49        };
50
51        let sgx_intel_root_ca_der_bytes = match &self.sgx_intel_root_ca_der {
52            Some(der) => der.as_slice(),
53            None => &[],
54        };
55
56        let sgx_tcb_signing_der_bytes = match &self.sgx_tcb_signing_der {
57            Some(der) => der.as_slice(),
58            None => &[],
59        };
60
61        let sgx_pck_certchain_der_bytes = match &self.sgx_pck_certchain_der {
62            Some(der) => der.as_slice(),
63            None => &[],
64        };
65
66        let sgx_intel_root_ca_crl_der_bytes = match &self.sgx_intel_root_ca_crl_der {
67            Some(der) => der.as_slice(),
68            None => &[],
69        };
70
71        let sgx_pck_processor_crl_der_bytes = match &self.sgx_pck_processor_crl_der {
72            Some(der) => der.as_slice(),
73            None => &[],
74        };
75
76        let sgx_pck_platform_crl_der_bytes = match &self.sgx_pck_platform_crl_der {
77            Some(der) => der.as_slice(),
78            None => &[],
79        };
80
81        // get the total length
82        let total_length = 4 * 8 + tcbinfo_bytes.len() + qeidentity_bytes.len() + sgx_intel_root_ca_der_bytes.len() + sgx_tcb_signing_der_bytes.len() + sgx_pck_certchain_der_bytes.len() + sgx_intel_root_ca_crl_der_bytes.len() + sgx_pck_processor_crl_der_bytes.len() + sgx_pck_platform_crl_der_bytes.len();
83
84        // create the vec and copy the data
85        let mut data = Vec::with_capacity(total_length);
86        data.extend_from_slice(&(tcbinfo_bytes.len() as u32).to_le_bytes());
87        data.extend_from_slice(&(qeidentity_bytes.len() as u32).to_le_bytes());
88        data.extend_from_slice(&(sgx_intel_root_ca_der_bytes.len() as u32).to_le_bytes());
89        data.extend_from_slice(&(sgx_tcb_signing_der_bytes.len() as u32).to_le_bytes());
90        data.extend_from_slice(&(sgx_pck_certchain_der_bytes.len() as u32).to_le_bytes());
91        data.extend_from_slice(&(sgx_intel_root_ca_crl_der_bytes.len() as u32).to_le_bytes());
92        data.extend_from_slice(&(sgx_pck_processor_crl_der_bytes.len() as u32).to_le_bytes());
93        data.extend_from_slice(&(sgx_pck_platform_crl_der_bytes.len() as u32).to_le_bytes());
94
95        data.extend_from_slice(&tcbinfo_bytes);
96        data.extend_from_slice(&qeidentity_bytes);
97        data.extend_from_slice(&sgx_intel_root_ca_der_bytes);
98        data.extend_from_slice(&sgx_tcb_signing_der_bytes);
99        data.extend_from_slice(&sgx_pck_certchain_der_bytes);
100        data.extend_from_slice(&sgx_intel_root_ca_crl_der_bytes);
101        data.extend_from_slice(&sgx_pck_processor_crl_der_bytes);
102        data.extend_from_slice(&sgx_pck_platform_crl_der_bytes);
103
104        data
105    }
106
107    pub fn from_bytes(slice: &[u8]) -> Self {
108        // reverse the serialization process
109        // each length is 4 bytes long, we have a total of 8 members
110        let tcbinfo_bytes_len = u32::from_le_bytes(slice[0..4].try_into().unwrap()) as usize;
111        let qeidentity_bytes_len = u32::from_le_bytes(slice[4..8].try_into().unwrap()) as usize;
112        let sgx_intel_root_ca_der_len = u32::from_le_bytes(slice[8..12].try_into().unwrap()) as usize;
113        let sgx_tcb_signing_der_len = u32::from_le_bytes(slice[12..16].try_into().unwrap()) as usize;
114        let sgx_pck_certchain_der_len = u32::from_le_bytes(slice[16..20].try_into().unwrap()) as usize;
115        let sgx_intel_root_ca_crl_der_len = u32::from_le_bytes(slice[20..24].try_into().unwrap()) as usize;
116        let sgx_pck_processor_crl_der_len = u32::from_le_bytes(slice[24..28].try_into().unwrap()) as usize;
117        let sgx_pck_platform_crl_der_len = u32::from_le_bytes(slice[28..32].try_into().unwrap()) as usize;
118
119        let mut offset = 4 * 8 as usize;
120        let tcbinfo_bytes: Option<Vec<u8>> = match tcbinfo_bytes_len {
121            0 => None,
122            len => Some(slice[offset..offset + len].to_vec())
123        };
124        offset += tcbinfo_bytes_len;
125
126        let qeidentity_bytes: Option<Vec<u8>> = match qeidentity_bytes_len {
127            0 => None,
128            len => Some(slice[offset..offset + len].to_vec())
129        };
130        offset += qeidentity_bytes_len;
131
132        let sgx_intel_root_ca_der: Option<Vec<u8>> = match sgx_intel_root_ca_der_len {
133            0 => None,
134            len => Some(slice[offset..offset + len].to_vec())
135        };
136        offset += sgx_intel_root_ca_der_len;
137
138        let sgx_tcb_signing_der: Option<Vec<u8>> = match sgx_tcb_signing_der_len {
139            0 => None,
140            len => Some(slice[offset..offset + len].to_vec())
141        };
142        offset += sgx_tcb_signing_der_len;
143
144        let sgx_pck_certchain_der: Option<Vec<u8>> = match sgx_pck_certchain_der_len {
145            0 => None,
146            len => Some(slice[offset..offset + len].to_vec())
147        };
148        offset += sgx_pck_certchain_der_len;
149
150        let sgx_intel_root_ca_crl_der: Option<Vec<u8>> = match sgx_intel_root_ca_crl_der_len {
151            0 => None,
152            len => Some(slice[offset..offset + len].to_vec())
153        };
154        offset += sgx_intel_root_ca_crl_der_len;
155
156        let sgx_pck_processor_crl_der: Option<Vec<u8>> = match sgx_pck_processor_crl_der_len {
157            0 => None,
158            len => Some(slice[offset..offset + len].to_vec())
159        };
160        offset += sgx_pck_processor_crl_der_len;
161
162        let sgx_pck_platform_crl_der: Option<Vec<u8>> = match sgx_pck_platform_crl_der_len {
163            0 => None,
164            len => Some(slice[offset..offset + len].to_vec())
165        };
166        offset += sgx_pck_platform_crl_der_len;
167
168        assert!(offset == slice.len());
169
170        IntelCollateral {
171            tcbinfo_bytes: tcbinfo_bytes,
172            qeidentity_bytes: qeidentity_bytes,
173            sgx_intel_root_ca_der,
174            sgx_tcb_signing_der,
175            sgx_pck_certchain_der,
176            sgx_intel_root_ca_crl_der,
177            sgx_pck_processor_crl_der,
178            sgx_pck_platform_crl_der,
179        }
180    }
181
182    pub fn get_tcbinfov2(&self) -> TcbInfoV2 {
183        match &self.tcbinfo_bytes {
184            Some(tcbinfov2) => {
185                let tcbinfo: TcbInfoV2 = serde_json::from_slice(tcbinfov2).unwrap();
186                assert_eq!(tcbinfo.tcb_info.version, 2);
187                tcbinfo
188            },
189            None => panic!("TCB Info V2 not set"),
190        }
191    }
192
193    pub fn get_tcbinfov3(&self) -> TcbInfoV3 {
194        match &self.tcbinfo_bytes {
195            Some(tcbinfov3) => {
196                let tcbinfo: TcbInfoV3 = serde_json::from_slice(tcbinfov3).unwrap();
197                assert_eq!(tcbinfo.tcb_info.version, 3);
198                tcbinfo
199            },
200            None => panic!("TCB Info V3 not set"),
201        }
202    }
203
204    pub fn set_tcbinfo_bytes(&mut self, tcbinfo_slice: &[u8]) {
205        self.tcbinfo_bytes = Some(tcbinfo_slice.to_vec());
206    }
207
208    pub fn get_qeidentityv2(&self) -> EnclaveIdentityV2 {
209        match &self.qeidentity_bytes {
210            Some(qeidentityv2) => {
211                let qeidentity = serde_json::from_slice(qeidentityv2).unwrap();
212                qeidentity
213            },
214            None => panic!("QE Identity V2 not set"),
215        }
216    }
217
218    pub fn set_qeidentity_bytes(&mut self, qeidentity_slice: &[u8]) {
219        self.qeidentity_bytes = Some(qeidentity_slice.to_vec());
220    }
221
222    pub fn get_sgx_intel_root_ca<'a>(&'a self) -> X509Certificate<'a> {
223        match self.sgx_intel_root_ca_der {
224            Some(ref der) => {
225                let cert = parse_x509_der(der);
226                cert
227            },
228            None => panic!("Intel Root CA not set"),
229        }
230    }
231
232    pub fn set_intel_root_ca_der(&mut self, intel_root_ca_der: &[u8]) {
233        self.sgx_intel_root_ca_der = Some(intel_root_ca_der.to_vec());
234    }
235
236    pub fn get_sgx_tcb_signing<'a>(&'a self) -> X509Certificate<'a> {
237        match self.sgx_tcb_signing_der {
238            Some(ref der) => {
239                let cert = parse_x509_der(der);
240                cert
241            },
242            None => panic!("SGX TCB Signing Cert not set"),
243        }
244    }
245
246    pub fn set_sgx_tcb_signing_der(&mut self, sgx_tcb_signing_der: &[u8]) {
247        self.sgx_tcb_signing_der = Some(sgx_tcb_signing_der.to_vec());
248    }
249
250    pub fn set_sgx_tcb_signing_pem(&mut self, sgx_tcb_signing_pem: &[u8]) {
251        // convert pem to der
252        let sgx_tcb_signing_der = pem_to_der(sgx_tcb_signing_pem);
253        self.sgx_tcb_signing_der = Some(sgx_tcb_signing_der);
254    }
255
256    pub fn get_sgx_pck_certchain<'a>(&'a self) -> Option<Vec<X509Certificate<'a>>> {
257        match &self.sgx_pck_certchain_der {
258            Some(certchain_der) => {
259                let certchain = parse_x509_der_multi(certchain_der);
260                Some(certchain)
261            },
262            None => None,
263        }
264    }
265
266    pub fn set_sgx_pck_certchain_der(&mut self, sgx_pck_certchain_der: Option<&[u8]>) {
267        match sgx_pck_certchain_der {
268            Some(certchain_der) => {
269                self.sgx_pck_certchain_der = Some(certchain_der.to_vec());
270            },
271            None => {
272                self.sgx_pck_certchain_der = None;
273            },
274        }
275    }
276
277    pub fn set_sgx_pck_certchain_pem(&mut self, sgx_pck_certchain_pem: Option<&[u8]>) {
278        match sgx_pck_certchain_pem {
279            Some(certchain_pem) => {
280                // convert pem to der
281                let sgx_pck_certchain_der = pem_to_der(certchain_pem);
282                self.sgx_pck_certchain_der = Some(sgx_pck_certchain_der);
283            },
284            None => {
285                self.sgx_pck_certchain_der = None;
286            },
287        }
288    }
289
290    pub fn get_sgx_intel_root_ca_crl<'a>(&'a self) -> Option<CertificateRevocationList<'a>> {
291        match &self.sgx_intel_root_ca_crl_der {
292            Some(crl_der) => {
293                let crl = parse_crl_der(crl_der);
294                Some(crl)
295            },
296            None => None,
297        }
298    }
299
300    pub fn set_sgx_intel_root_ca_crl_der(&mut self, sgx_intel_root_ca_crl_der: &[u8]) {
301        self.sgx_intel_root_ca_crl_der = Some(sgx_intel_root_ca_crl_der.to_vec());
302    }
303
304    pub fn set_sgx_intel_root_ca_crl_pem(&mut self, sgx_intel_root_ca_crl_pem: &[u8]) {
305        // convert pem to der
306        let sgx_intel_root_ca_crl_der = pem_to_der(sgx_intel_root_ca_crl_pem);
307        self.sgx_intel_root_ca_crl_der = Some(sgx_intel_root_ca_crl_der);
308    }
309
310    pub fn get_sgx_pck_processor_crl<'a>(&'a self) -> Option<CertificateRevocationList<'a>> {
311        match &self.sgx_pck_processor_crl_der {
312            Some(crl_der) => {
313                let crl = parse_crl_der(crl_der);
314                Some(crl)
315            },
316            None => None,
317        }
318    }
319
320    pub fn set_sgx_processor_crl_der(&mut self, sgx_pck_processor_crl_der: &[u8]) {
321        self.sgx_pck_processor_crl_der = Some(sgx_pck_processor_crl_der.to_vec());
322    }
323
324    pub fn set_sgx_processor_crl_der_pem(&mut self, sgx_pck_processor_crl_pem: &[u8]) {
325        // convert pem to der
326        let sgx_pck_processor_crl_der = pem_to_der(sgx_pck_processor_crl_pem);
327        self.sgx_pck_processor_crl_der = Some(sgx_pck_processor_crl_der);
328    }
329
330    pub fn get_sgx_pck_platform_crl<'a>(&'a self) -> Option<CertificateRevocationList<'a>> {
331        match &self.sgx_pck_platform_crl_der {
332            Some(crl_der) => {
333                let crl = parse_crl_der(crl_der);
334                Some(crl)
335            },
336            None => None, 
337        }
338    }
339
340    pub fn set_sgx_platform_crl_der(&mut self, sgx_pck_platform_crl_der: &[u8]) {
341        self.sgx_pck_platform_crl_der = Some(sgx_pck_platform_crl_der.to_vec());
342    }
343
344    pub fn set_sgx_platform_crl_der_pem(&mut self, sgx_pck_platform_crl_pem: &[u8]) {
345        // convert pem to der
346        let sgx_pck_platform_crl_der = pem_to_der(sgx_pck_platform_crl_pem);
347        self.sgx_pck_platform_crl_der = Some(sgx_pck_platform_crl_der);
348    }
349}