Coverage Report

Created: 2026-01-13 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}