eventlog_rs/
bios_eventlog.rs

1// TCG Eventlog for Conventional BIOS
2// Spec: https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClientImplementation_1-21_1_00.pdf
3
4use crate::enums::EVENTLOG_TYPES;
5use anyhow::*;
6use byteorder::{LittleEndian, ReadBytesExt};
7use core::fmt;
8use std::convert::TryFrom;
9
10const SHA1_DIGEST_SIZE: usize = 20;
11
12#[derive(Clone)]
13pub struct BiosEventlog {
14    pub log: Vec<BiosEventlogEntry>,
15}
16
17impl fmt::Display for BiosEventlog {
18    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19        let mut parsed_el = String::default();
20        for event_entry in self.log.clone() {
21            parsed_el = format!(
22                "{}\nEvent Entry:\n\tPCR: {}\n\tEvent Type: {}\n\tDigest: {}\n\tEvent Data: {}\n",
23                parsed_el,
24                event_entry.pcr_index,
25                event_entry.event_type,
26                hex::encode(event_entry.digest.clone()),
27                String::from_utf8(event_entry.event_data.clone())
28                    .unwrap_or_else(|_| hex::encode(event_entry.event_data.clone())),
29            );
30        }
31
32        write!(f, "{parsed_el}")
33    }
34}
35
36#[derive(Clone)]
37pub struct BiosEventlogEntry {
38    pub pcr_index: u32,
39    pub event_type: String,
40    pub digest: Vec<u8>,
41    pub event_data: Vec<u8>,
42}
43
44impl TryFrom<Vec<u8>> for BiosEventlog {
45    type Error = anyhow::Error;
46
47    fn try_from(data: Vec<u8>) -> Result<Self, Self::Error> {
48        let mut index = 0;
49        let mut event_log: Vec<BiosEventlogEntry> = Vec::new();
50
51        while index < data.len() as usize {
52            let stop_flag = (&data[index..(index + 8)]).read_u64::<LittleEndian>()?;
53            let pcr_index = (&data[index..(index + 4)]).read_u32::<LittleEndian>()?;
54            index += 4;
55
56            let event_type_num = (&data[index..(index + 4)]).read_u32::<LittleEndian>()?;
57            index += 4;
58            let event_type = match EVENTLOG_TYPES.get(&event_type_num) {
59                Some(type_name) => type_name.to_string(),
60                None => format!("UNKOWN_TYPE: {:x}", &event_type_num),
61            };
62
63            if stop_flag == 0xFFFFFFFFFFFFFFFF || stop_flag == 0x0000000000000000 {
64                break;
65            }
66
67            let digest = data[index..(index + SHA1_DIGEST_SIZE)].to_vec();
68            index += SHA1_DIGEST_SIZE;
69
70            let event_data_size = (&data[index..(index + 4)]).read_u32::<LittleEndian>()? as usize;
71            index += 4;
72            let event_data = data[index..(index + event_data_size)].to_vec();
73            index += event_data_size;
74
75            let eventlog_entry = BiosEventlogEntry {
76                pcr_index,
77                event_type,
78                digest,
79                event_data,
80            };
81
82            event_log.push(eventlog_entry)
83        }
84
85        Ok(BiosEventlog { log: event_log })
86    }
87}