/src/MigTD/deps/td-shim/cc-measurement/src/log.rs
Line | Count | Source |
1 | | // Copyright (c) 2022 Intel Corporation |
2 | | // |
3 | | // SPDX-License-Identifier: BSD-2-Clause-Patent |
4 | | |
5 | | use super::*; |
6 | | use alloc::boxed::Box; |
7 | | use core::mem::size_of; |
8 | | |
9 | | type Result<T> = core::result::Result<T, CcEventLogError>; |
10 | | |
11 | | #[derive(Debug)] |
12 | | pub enum CcEventLogError { |
13 | | InvalidParameter, |
14 | | OutOfResource, |
15 | | InvalidMrIndex(u32), |
16 | | ExtendMr, |
17 | | } |
18 | | |
19 | | #[allow(unused)] |
20 | | pub struct CcEventLogWriter<'a> { |
21 | | area: &'a mut [u8], |
22 | | offset: usize, |
23 | | last: usize, |
24 | | extender: Box<dyn Fn(&[u8; SHA384_DIGEST_SIZE], u32) -> Result<()>>, |
25 | | } |
26 | | |
27 | | impl CcEventLogWriter<'_> { |
28 | 0 | pub fn new( |
29 | 0 | area: &mut [u8], |
30 | 0 | extender: Box<dyn Fn(&[u8; SHA384_DIGEST_SIZE], u32) -> Result<()>>, |
31 | 0 | ) -> Result<CcEventLogWriter> { |
32 | 0 | let mut cc_event_log = CcEventLogWriter { |
33 | 0 | area, |
34 | 0 | offset: 0, |
35 | 0 | last: 0, |
36 | 0 | extender, |
37 | 0 | }; |
38 | | |
39 | | // Create the TCG_EfiSpecIDEvent as the first event |
40 | 0 | let first = TcgEfiSpecIdevent::default(); |
41 | 0 | cc_event_log.log_pcr_event(0, EV_NO_ACTION, first.as_bytes())?; |
42 | | |
43 | 0 | Ok(cc_event_log) |
44 | 0 | } |
45 | | |
46 | 0 | pub fn create_event_log( |
47 | 0 | &mut self, |
48 | 0 | mr_index: u32, |
49 | 0 | event_type: u32, |
50 | 0 | event_data: &[&[u8]], |
51 | 0 | hash_data: &[u8], |
52 | 0 | ) -> Result<()> { |
53 | 0 | let sha384 = self.calculate_digest_and_extend(hash_data, mr_index)?; |
54 | | |
55 | 0 | self.log_cc_event(mr_index, event_type, event_data, &sha384) |
56 | 0 | } |
57 | | |
58 | 0 | pub fn create_seperator(&mut self) -> Result<()> { |
59 | 0 | let separator = u32::to_le_bytes(0); |
60 | | |
61 | | // Measure 0x0000_0000 into RTMR[0] and RTMR[1] |
62 | 0 | let _ = self.calculate_digest_and_extend(&separator, 1)?; |
63 | 0 | let sha384 = self.calculate_digest_and_extend(&separator, 2)?; |
64 | | |
65 | 0 | self.log_cc_event(1, EV_SEPARATOR, &[&separator], &sha384)?; |
66 | 0 | self.log_cc_event(2, EV_SEPARATOR, &[&separator], &sha384) |
67 | 0 | } |
68 | | |
69 | 0 | pub fn as_slice(&self) -> &[u8] { |
70 | 0 | &self.area[..self.offset] |
71 | 0 | } |
72 | | |
73 | 0 | fn log_pcr_event( |
74 | 0 | &mut self, |
75 | 0 | mr_index: u32, |
76 | 0 | event_type: u32, |
77 | 0 | event_data: &[u8], |
78 | 0 | ) -> Result<usize> { |
79 | 0 | let event_size = size_of::<TcgPcrEventHeader>() |
80 | 0 | .checked_add(event_data.len()) |
81 | 0 | .ok_or(CcEventLogError::InvalidParameter)?; |
82 | | |
83 | 0 | if self |
84 | 0 | .offset |
85 | 0 | .checked_add(event_size) |
86 | 0 | .ok_or(CcEventLogError::InvalidParameter)? |
87 | 0 | > self.area.len() |
88 | | { |
89 | 0 | return Err(CcEventLogError::OutOfResource); |
90 | 0 | } |
91 | | |
92 | 0 | let pcr_header = TcgPcrEventHeader { |
93 | 0 | mr_index, |
94 | 0 | event_type, |
95 | 0 | digest: [0u8; 20], |
96 | 0 | event_size: event_data.len() as u32, |
97 | 0 | }; |
98 | | |
99 | 0 | let data_offset = self.offset + size_of::<TcgPcrEventHeader>(); |
100 | 0 | self.area[self.offset..data_offset].copy_from_slice(pcr_header.as_bytes()); |
101 | 0 | self.write_data(event_data, data_offset); |
102 | 0 | self.update_offset(size_of::<TcgPcrEventHeader>() + event_data.len()); |
103 | | |
104 | 0 | Ok(self.offset) |
105 | 0 | } |
106 | | |
107 | 0 | fn log_cc_event( |
108 | 0 | &mut self, |
109 | 0 | mr_index: u32, |
110 | 0 | event_type: u32, |
111 | 0 | event_data: &[&[u8]], |
112 | 0 | sha384: &[u8; 48], |
113 | 0 | ) -> Result<()> { |
114 | 0 | let event_data_size: usize = event_data.iter().map(|&data| data.len()).sum(); |
115 | 0 | let event_size = size_of::<CcEventHeader>() |
116 | 0 | .checked_add(event_data_size) |
117 | 0 | .ok_or(CcEventLogError::InvalidParameter)?; |
118 | | |
119 | 0 | if self |
120 | 0 | .offset |
121 | 0 | .checked_add(event_size) |
122 | 0 | .ok_or(CcEventLogError::InvalidParameter)? |
123 | 0 | > self.area.len() |
124 | | { |
125 | 0 | return Err(CcEventLogError::OutOfResource); |
126 | 0 | } |
127 | | |
128 | | // Write the event header into event log memory and update the 'size' and 'last' |
129 | 0 | let event_offset = self |
130 | 0 | .log_cc_event_header(mr_index, event_type, sha384, event_data_size as u32) |
131 | 0 | .ok_or(CcEventLogError::OutOfResource)?; |
132 | | |
133 | 0 | let mut data_offset = size_of::<CcEventHeader>(); |
134 | | // Fill the event data into event log |
135 | 0 | for &data in event_data { |
136 | 0 | self.write_data( |
137 | 0 | data, |
138 | 0 | event_offset |
139 | 0 | .checked_add(data_offset) |
140 | 0 | .ok_or(CcEventLogError::OutOfResource)?, |
141 | | ); |
142 | 0 | data_offset += data.len() |
143 | | } |
144 | | |
145 | 0 | self.update_offset(event_size); |
146 | | |
147 | 0 | Ok(()) |
148 | 0 | } |
149 | | |
150 | 0 | fn log_cc_event_header( |
151 | 0 | &mut self, |
152 | 0 | mr_index: u32, |
153 | 0 | event_type: u32, |
154 | 0 | digest: &[u8; SHA384_DIGEST_SIZE], |
155 | 0 | event_size: u32, |
156 | 0 | ) -> Option<usize> { |
157 | 0 | let event_header = CcEventHeader { |
158 | 0 | mr_index, |
159 | 0 | event_type, |
160 | 0 | digest: TpmlDigestValues { |
161 | 0 | count: 1, |
162 | 0 | digests: [TpmtHa { |
163 | 0 | hash_alg: TPML_ALG_SHA384, |
164 | 0 | digest: TpmuHa { sha384: *digest }, |
165 | 0 | }], |
166 | 0 | }, |
167 | 0 | event_size, |
168 | 0 | }; |
169 | | |
170 | 0 | self.area[self.offset..self.offset + size_of::<CcEventHeader>()] |
171 | 0 | .copy_from_slice(event_header.as_bytes()); |
172 | | |
173 | 0 | Some(self.offset) |
174 | 0 | } |
175 | | |
176 | 0 | fn write_data(&mut self, data: &[u8], offset: usize) { |
177 | 0 | self.area[offset..offset + data.len()].copy_from_slice(data); |
178 | 0 | } |
179 | | |
180 | 0 | fn update_offset(&mut self, new_log_size: usize) { |
181 | 0 | self.last = self.offset; |
182 | 0 | self.offset += new_log_size; |
183 | 0 | } |
184 | | |
185 | 0 | fn calculate_digest_and_extend( |
186 | 0 | &self, |
187 | 0 | hash_data: &[u8], |
188 | 0 | mr_index: u32, |
189 | 0 | ) -> Result<[u8; SHA384_DIGEST_SIZE]> { |
190 | 0 | let mut digest_sha384 = [0u8; SHA384_DIGEST_SIZE]; |
191 | | |
192 | 0 | Self::hash_sha384(hash_data, &mut digest_sha384); |
193 | | |
194 | | // Extend the digest to the RTMR |
195 | 0 | (self.extender)(&digest_sha384, mr_index)?; |
196 | | |
197 | 0 | Ok(digest_sha384) |
198 | 0 | } |
199 | | |
200 | | #[cfg(feature = "ring")] |
201 | | fn hash_sha384(hash_data: &[u8], digest_sha384: &mut [u8; SHA384_DIGEST_SIZE]) { |
202 | | let digest = ring::digest::digest(&ring::digest::SHA384, hash_data); |
203 | | let digest = digest.as_ref(); |
204 | | assert_eq!(digest.len(), SHA384_DIGEST_SIZE); |
205 | | |
206 | | digest_sha384.clone_from_slice(digest); |
207 | | } |
208 | | |
209 | | #[cfg(all(not(feature = "ring"), feature = "sha2"))] |
210 | 0 | fn hash_sha384(hash_data: &[u8], digest_sha384: &mut [u8; SHA384_DIGEST_SIZE]) { |
211 | | use sha2::{Digest, Sha384}; |
212 | | |
213 | 0 | let mut digest = Sha384::new(); |
214 | 0 | digest.update(hash_data); |
215 | 0 | let digest = digest.finalize(); |
216 | 0 | assert_eq!(digest.as_slice().len(), SHA384_DIGEST_SIZE); |
217 | | |
218 | 0 | digest_sha384.clone_from_slice(digest.as_slice()); |
219 | 0 | } |
220 | | } |
221 | | |
222 | | #[derive(Clone, Copy)] |
223 | | pub struct CcEvents<'a> { |
224 | | pub bytes: &'a [u8], |
225 | | } |
226 | | |
227 | | type EventData<'a> = &'a [u8]; |
228 | | |
229 | | impl<'a> Iterator for CcEvents<'a> { |
230 | | type Item = (CcEventHeader, EventData<'a>); |
231 | 0 | fn next(&mut self) -> Option<Self::Item> { |
232 | 0 | if self.bytes.len() < size_of::<CcEventHeader>() { |
233 | 0 | return None; |
234 | 0 | } |
235 | | |
236 | 0 | let event_header = CcEventHeader::read_from(&self.bytes[..size_of::<CcEventHeader>()])?; |
237 | 0 | if event_header.event_size == 0 { |
238 | 0 | return None; |
239 | 0 | } |
240 | | |
241 | 0 | let end_of_event = size_of::<CcEventHeader>() + event_header.event_size as usize; |
242 | 0 | if end_of_event < self.bytes.len() { |
243 | 0 | let event_data = &self.bytes[size_of::<CcEventHeader>()..end_of_event]; |
244 | 0 | self.bytes = &self.bytes[end_of_event..]; |
245 | 0 | Some((event_header, event_data)) |
246 | | } else { |
247 | 0 | None |
248 | | } |
249 | 0 | } |
250 | | } |
251 | | |
252 | | pub struct CcEventLogReader<'a> { |
253 | | pub pcr_event_header: TcgPcrEventHeader, |
254 | | pub specific_id_event: TcgEfiSpecIdevent, |
255 | | pub cc_events: CcEvents<'a>, |
256 | | } |
257 | | |
258 | | impl CcEventLogReader<'_> { |
259 | 0 | pub fn new(bytes: &[u8]) -> Option<CcEventLogReader> { |
260 | 0 | let specific_id_event_size = |
261 | 0 | size_of::<TcgPcrEventHeader>() + size_of::<TcgEfiSpecIdevent>(); |
262 | 0 | if bytes.len() < specific_id_event_size { |
263 | 0 | return None; |
264 | 0 | } |
265 | | |
266 | | // TCG_EfiSpecIDEvent should be the first event |
267 | 0 | let pcr_event_header = |
268 | 0 | TcgPcrEventHeader::read_from(&bytes[..size_of::<TcgPcrEventHeader>()])?; |
269 | 0 | let specific_id_event = TcgEfiSpecIdevent::read_from( |
270 | 0 | &bytes[size_of::<TcgPcrEventHeader>()..specific_id_event_size], |
271 | 0 | )?; |
272 | 0 | let cc_event_log = CcEventLogReader { |
273 | 0 | cc_events: CcEvents { |
274 | 0 | bytes: &bytes[specific_id_event_size..], |
275 | 0 | }, |
276 | 0 | pcr_event_header, |
277 | 0 | specific_id_event, |
278 | 0 | }; |
279 | | |
280 | 0 | Some(cc_event_log) |
281 | 0 | } |
282 | | |
283 | 0 | pub fn query(&self, key: &[u8]) -> Option<CcEventHeader> { |
284 | 0 | for (header, data) in self.cc_events { |
285 | 0 | if data.len() < key.len() { |
286 | 0 | return None; |
287 | 0 | } |
288 | 0 | if &data[..key.len()] == key { |
289 | 0 | return Some(header); |
290 | 0 | } |
291 | | } |
292 | 0 | None |
293 | 0 | } |
294 | | } |
295 | | |
296 | | #[cfg(test)] |
297 | | mod tests { |
298 | | use core::mem::size_of; |
299 | | |
300 | | use alloc::{boxed::Box, vec}; |
301 | | |
302 | | use crate::{ |
303 | | log::CcEventLogReader, CcEventHeader, TcgEfiSpecIdevent, TcgPcrEventHeader, EV_SEPARATOR, |
304 | | SHA384_DIGEST_SIZE, |
305 | | }; |
306 | | |
307 | | use super::{CcEventLogWriter, Result}; |
308 | | |
309 | | fn extender(_digest: &[u8; SHA384_DIGEST_SIZE], _mr_index: u32) -> Result<()> { |
310 | | // Do nothing |
311 | | Ok(()) |
312 | | } |
313 | | |
314 | | #[test] |
315 | | fn test_cc_eventlog_writter_new() { |
316 | | let mut event_log = |
317 | | vec![0u8; size_of::<TcgPcrEventHeader>() + size_of::<TcgEfiSpecIdevent>()]; |
318 | | let _ = CcEventLogWriter::new(&mut event_log, Box::new(extender)).unwrap(); |
319 | | } |
320 | | |
321 | | #[test] |
322 | | #[should_panic] |
323 | | fn test_cc_eventlog_writter_new_with_small_buf() { |
324 | | let mut event_log = |
325 | | vec![0u8; size_of::<TcgPcrEventHeader>() + size_of::<TcgEfiSpecIdevent>() - 1]; |
326 | | let _ = CcEventLogWriter::new(&mut event_log, Box::new(extender)).unwrap(); |
327 | | } |
328 | | |
329 | | #[test] |
330 | | fn test_cc_eventlog_writter() { |
331 | | let mut event_log = vec![0u8; 0x1000]; |
332 | | |
333 | | let mut writter = CcEventLogWriter::new(&mut event_log, Box::new(extender)).unwrap(); |
334 | | let first_event_size = size_of::<TcgPcrEventHeader>() + size_of::<TcgEfiSpecIdevent>(); |
335 | | assert_eq!(writter.as_slice().len(), first_event_size); |
336 | | |
337 | | writter |
338 | | .create_event_log(2, 3, &[b"event1:", b"012"], &[0, 1, 2]) |
339 | | .unwrap(); |
340 | | let second_event_size = size_of::<CcEventHeader>() + 10; |
341 | | assert_eq!( |
342 | | writter.as_slice().len(), |
343 | | first_event_size + second_event_size |
344 | | ); |
345 | | |
346 | | writter.create_seperator().unwrap(); |
347 | | let seperator_size = (size_of::<CcEventHeader>() + size_of::<u32>()) * 2; |
348 | | assert_eq!( |
349 | | writter.as_slice().len(), |
350 | | first_event_size + second_event_size + seperator_size |
351 | | ); |
352 | | |
353 | | assert_eq!( |
354 | | &event_log[first_event_size..first_event_size + second_event_size], |
355 | | &[ |
356 | | 0x2, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x4f, 0x89, |
357 | | 0x58, 0x54, 0xc1, 0xa4, 0xfc, 0x5a, 0xa2, 0xe0, 0x45, 0x6e, 0xaf, 0x8d, 0xe, 0xca, |
358 | | 0xa7, 0xc, 0x19, 0x6b, 0xd9, 0x1, 0x15, 0x38, 0x61, 0xd7, 0x6b, 0x8f, 0xa3, 0xcd, |
359 | | 0x95, 0xce, 0xea, 0x29, 0xea, 0xb6, 0xa2, 0x79, 0xf8, 0xb0, 0x84, 0x37, 0x70, 0x3c, |
360 | | 0xe0, 0xb4, 0xb9, 0x1a, 0xa, 0x0, 0x0, 0x0, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x31, |
361 | | 0x3a, 0x30, 0x31, 0x32 |
362 | | ] |
363 | | ); |
364 | | } |
365 | | |
366 | | #[test] |
367 | | fn test_eventlog_reader_new() { |
368 | | let mut event_log = |
369 | | vec![0u8; size_of::<TcgPcrEventHeader>() + size_of::<TcgEfiSpecIdevent>()]; |
370 | | let reader = CcEventLogReader::new(&mut event_log).unwrap(); |
371 | | assert_eq!(reader.cc_events.bytes.len(), 0) |
372 | | } |
373 | | |
374 | | #[test] |
375 | | #[should_panic] |
376 | | fn test_eventlog_reader_new_with_small_buf() { |
377 | | let mut event_log = |
378 | | vec![0u8; size_of::<TcgPcrEventHeader>() + size_of::<TcgEfiSpecIdevent>() - 1]; |
379 | | let _ = CcEventLogReader::new(&mut event_log).unwrap(); |
380 | | } |
381 | | |
382 | | #[test] |
383 | | fn test_cc_events_iterator() { |
384 | | let mut event_log = vec![0u8; 0x1000]; |
385 | | |
386 | | let mut writter = CcEventLogWriter::new(&mut event_log, Box::new(extender)).unwrap(); |
387 | | |
388 | | writter |
389 | | .create_event_log(2, 3, &[b"event1:", b"012"], &[0, 1, 2]) |
390 | | .unwrap(); |
391 | | |
392 | | writter.create_seperator().unwrap(); |
393 | | |
394 | | let reader = CcEventLogReader::new(&mut event_log).unwrap(); |
395 | | |
396 | | for (idx, (event_header, event_data)) in reader.cc_events.enumerate() { |
397 | | let event_type = event_header.event_type; |
398 | | if idx == 0 { |
399 | | assert_eq!(event_type, 3); |
400 | | assert_eq!(event_data, b"event1:012"); |
401 | | } else if idx == 1 { |
402 | | assert_eq!(event_type, EV_SEPARATOR); |
403 | | assert_eq!(event_data, &[0u8; 4]); |
404 | | } |
405 | | } |
406 | | } |
407 | | |
408 | | #[test] |
409 | | fn test_cc_event_log_reader_query() { |
410 | | let mut event_log = vec![0u8; 0x1000]; |
411 | | |
412 | | let mut writter = CcEventLogWriter::new(&mut event_log, Box::new(extender)).unwrap(); |
413 | | |
414 | | writter |
415 | | .create_event_log(2, 3, &[b"event1:", b"012"], &[0, 1, 2]) |
416 | | .unwrap(); |
417 | | |
418 | | writter.create_seperator().unwrap(); |
419 | | |
420 | | let reader = CcEventLogReader::new(&mut event_log).unwrap(); |
421 | | |
422 | | assert!(reader.query(b"event1:012").is_some()); |
423 | | } |
424 | | } |