use super::{AlgorithmId, EventType, HashAlgorithm, PcrIndex, v1};
use crate::data_types::{Align, PhysicalAddress, UnalignedSlice};
use crate::proto::unsafe_protocol;
use crate::util::{ptr_write_unaligned_and_add, usize_from_u32};
use crate::{Error, Result, Status, StatusExt};
use core::fmt::{self, Debug, Formatter};
use core::marker::PhantomData;
use core::{ptr, slice};
use ptr_meta::Pointee;
use uefi_raw::protocol::tcg::v2::{Tcg2EventHeader as EventHeader, Tcg2Protocol};
#[cfg(feature = "alloc")]
use {crate::mem::make_boxed, alloc::boxed::Box};
pub use uefi_raw::protocol::tcg::v2::{
Tcg2EventLogFormat as EventLogFormat, Tcg2HashAlgorithmBitmap,
Tcg2HashLogExtendEventFlags as HashLogExtendEventFlags, Tcg2Version as Version,
};
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub struct BootServiceCapability {
size: u8,
pub structure_version: Version,
pub protocol_version: Version,
pub hash_algorithm_bitmap: HashAlgorithm,
pub supported_event_logs: EventLogFormat,
present_flag: u8,
pub max_command_size: u16,
pub max_response_size: u16,
pub manufacturer_id: u32,
pub number_of_pcr_banks: u32,
pub active_pcr_banks: HashAlgorithm,
}
impl Default for BootServiceCapability {
fn default() -> Self {
let struct_size = u8::try_from(size_of::<Self>()).unwrap();
Self {
size: struct_size,
structure_version: Version::default(),
protocol_version: Version::default(),
hash_algorithm_bitmap: HashAlgorithm::default(),
supported_event_logs: EventLogFormat::default(),
present_flag: 0,
max_command_size: 0,
max_response_size: 0,
manufacturer_id: 0,
number_of_pcr_banks: 0,
active_pcr_banks: HashAlgorithm::default(),
}
}
}
impl BootServiceCapability {
#[must_use]
pub const fn tpm_present(&self) -> bool {
self.present_flag != 0
}
}
#[derive(Eq, Pointee)]
#[repr(C, packed)]
pub struct PcrEventInputs {
size: u32,
event_header: EventHeader,
event: [u8],
}
impl PcrEventInputs {
pub fn new_in_buffer<'buf>(
buffer: &'buf mut [u8],
pcr_index: PcrIndex,
event_type: EventType,
event_data: &[u8],
) -> Result<&'buf mut Self, Option<usize>> {
let required_size = size_of::<u32>() + size_of::<EventHeader>() + event_data.len();
if buffer.len() < required_size {
return Err(Error::new(Status::BUFFER_TOO_SMALL, Some(required_size)));
}
let size_field = u32::try_from(required_size)
.map_err(|_| Error::new(Status::INVALID_PARAMETER, None))?;
let mut ptr: *mut u8 = buffer.as_mut_ptr().cast();
unsafe {
ptr_write_unaligned_and_add(&mut ptr, size_field);
ptr_write_unaligned_and_add(
&mut ptr,
EventHeader {
header_size: u32::try_from(size_of::<EventHeader>()).unwrap(),
header_version: 1,
pcr_index: pcr_index.0,
event_type,
},
);
ptr::copy(event_data.as_ptr(), ptr, event_data.len());
let ptr: *mut Self =
ptr_meta::from_raw_parts_mut(buffer.as_mut_ptr().cast(), event_data.len());
Ok(&mut *ptr)
}
}
#[cfg(feature = "alloc")]
pub fn new_in_box(
pcr_index: PcrIndex,
event_type: EventType,
event_data: &[u8],
) -> Result<Box<Self>> {
make_boxed(|buf| Self::new_in_buffer(buf, pcr_index, event_type, event_data))
}
}
impl Align for PcrEventInputs {
fn alignment() -> usize {
1
}
}
impl Debug for PcrEventInputs {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("PcrEventInputs")
.field("size", &{ self.size })
.field("event_header", &self.event_header)
.field("event", &"<binary data>")
.finish()
}
}
impl PartialEq for PcrEventInputs {
fn eq(&self, other: &Self) -> bool {
self.size == other.size
&& self.event_header == other.event_header
&& self.event == other.event
}
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
struct AlgorithmDigestSize {
algorithm_id: AlgorithmId,
digest_size: u16,
}
#[derive(Clone, Debug)]
struct AlgorithmDigestSizes<'a>(UnalignedSlice<'a, AlgorithmDigestSize>);
impl AlgorithmDigestSizes<'_> {
fn get_size(&self, alg: AlgorithmId) -> Option<u16> {
self.0.iter().find_map(|elem| {
if { elem.algorithm_id } == alg {
Some(elem.digest_size)
} else {
None
}
})
}
}
fn u32_le_from_bytes_at_offset(bytes: &[u8], offset: usize) -> Option<u32> {
let bytes = bytes.get(offset..offset + 4)?;
let val = u32::from_le_bytes(bytes.try_into().unwrap());
Some(val)
}
#[derive(Clone, Debug)]
#[allow(unused)] struct EventLogHeader<'a> {
platform_class: u32,
spec_version: (u8, u8, u8),
uintn_size: u8,
algorithm_digest_sizes: AlgorithmDigestSizes<'a>,
vendor_info: &'a [u8],
size_in_bytes: usize,
}
impl<'a> EventLogHeader<'a> {
fn new(event: &'a v1::PcrEvent) -> Option<Self> {
if event.pcr_index() != PcrIndex(0) {
return None;
}
if { event.event_type() } != EventType::NO_ACTION {
return None;
}
if event.digest() != [0; 20] {
return None;
}
let event = &event.event_data();
if event.get(..16)? != *b"Spec ID Event03\0" {
return None;
}
let platform_class = u32_le_from_bytes_at_offset(event, 16)?;
let version_minor = *event.get(20)?;
let version_major = *event.get(21)?;
let version_errata = *event.get(22)?;
let uintn_size = *event.get(23)?;
let number_of_algorithms = usize_from_u32(u32_le_from_bytes_at_offset(event, 24)?);
let vendor_info_size_byte_offset =
28 + (number_of_algorithms * size_of::<AlgorithmDigestSize>());
let vendor_info_size = usize::from(*event.get(vendor_info_size_byte_offset)?);
let algorithm_digest_sizes = unsafe {
let ptr: *const AlgorithmDigestSize = event.as_ptr().add(28).cast();
AlgorithmDigestSizes(UnalignedSlice::new(ptr, number_of_algorithms))
};
let vendor_info_byte_offset = vendor_info_size_byte_offset + 1;
let vendor_info =
event.get(vendor_info_byte_offset..vendor_info_byte_offset + vendor_info_size)?;
let size_in_bytes = 32 + vendor_info_byte_offset + vendor_info_size;
Some(Self {
platform_class,
spec_version: (version_major, version_minor, version_errata),
uintn_size,
algorithm_digest_sizes,
vendor_info,
size_in_bytes,
})
}
}
#[derive(Debug)]
pub struct EventLog<'a> {
_lifetime: PhantomData<&'a Tcg>,
location: *const u8,
last_entry: *const u8,
is_truncated: bool,
}
impl EventLog<'_> {
#[must_use]
pub fn iter(&self) -> EventLogIter<'_> {
if let Some(header) = self.header() {
let location = unsafe { self.location.add(header.size_in_bytes) };
EventLogIter {
log: self,
location,
header: self.header(),
}
} else {
EventLogIter {
log: self,
location: ptr::null(),
header: None,
}
}
}
fn header(&self) -> Option<EventLogHeader<'_>> {
if self.location.is_null() {
None
} else {
let event = unsafe { v1::PcrEvent::from_ptr(self.location) };
EventLogHeader::new(event)
}
}
#[must_use]
pub const fn is_truncated(&self) -> bool {
self.is_truncated
}
}
#[derive(Clone)]
pub struct PcrEventDigests<'a> {
data: &'a [u8],
algorithm_digest_sizes: AlgorithmDigestSizes<'a>,
}
impl Debug for PcrEventDigests<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.clone()).finish()
}
}
impl<'a> IntoIterator for PcrEventDigests<'a> {
type Item = (AlgorithmId, &'a [u8]);
type IntoIter = PcrEventDigestIter<'a>;
fn into_iter(self) -> Self::IntoIter {
PcrEventDigestIter {
digests: self,
offset: 0,
}
}
}
#[derive(Debug)]
pub struct PcrEventDigestIter<'a> {
digests: PcrEventDigests<'a>,
offset: usize,
}
impl<'a> Iterator for PcrEventDigestIter<'a> {
type Item = (AlgorithmId, &'a [u8]);
fn next(&mut self) -> Option<Self::Item> {
let data = &self.digests.data[self.offset..];
let alg = data.get(..2)?;
let alg = AlgorithmId(u16::from_le_bytes([alg[0], alg[1]]));
let digest_size = usize::from(self.digests.algorithm_digest_sizes.get_size(alg)?);
let digest = data.get(2..2 + digest_size)?;
self.offset += 2 + digest_size;
Some((alg, digest))
}
}
#[derive(Debug)]
pub struct PcrEvent<'a> {
pcr_index: PcrIndex,
event_type: EventType,
digests: &'a [u8],
event_data: &'a [u8],
next: *const u8,
algorithm_digest_sizes: AlgorithmDigestSizes<'a>,
}
impl<'a> PcrEvent<'a> {
unsafe fn from_ptr(ptr: *const u8, header: EventLogHeader<'a>) -> Option<Self> {
let ptr_u32: *const u32 = ptr.cast();
let pcr_index = PcrIndex(unsafe { ptr_u32.read_unaligned() });
let event_type = EventType(unsafe { ptr_u32.add(1).read_unaligned() });
let digests_count = unsafe { ptr_u32.add(2).read_unaligned() };
let digests_ptr: *const u8 = unsafe { ptr.add(12) };
let mut digests_byte_size = 0;
let mut elem_ptr = digests_ptr;
for _ in 0..digests_count {
let algorithm_id = AlgorithmId(unsafe { elem_ptr.cast::<u16>().read_unaligned() });
let alg_and_digest_size = size_of::<AlgorithmId>()
+ usize::from(header.algorithm_digest_sizes.get_size(algorithm_id)?);
digests_byte_size += alg_and_digest_size;
elem_ptr = unsafe { elem_ptr.add(alg_and_digest_size) };
}
let digests = unsafe { slice::from_raw_parts(digests_ptr, digests_byte_size) };
let event_size_ptr = unsafe { digests_ptr.add(digests_byte_size) };
let event_size = usize_from_u32(unsafe { event_size_ptr.cast::<u32>().read_unaligned() });
let event_data_ptr = unsafe { event_size_ptr.add(4) };
let event_data = unsafe { slice::from_raw_parts(event_data_ptr, event_size) };
Some(Self {
pcr_index,
event_type,
digests,
event_data,
next: unsafe { event_data_ptr.add(event_size) },
algorithm_digest_sizes: header.algorithm_digest_sizes,
})
}
#[must_use]
pub const fn pcr_index(&self) -> PcrIndex {
self.pcr_index
}
#[must_use]
pub const fn event_type(&self) -> EventType {
self.event_type
}
#[must_use]
pub const fn event_data(&self) -> &[u8] {
self.event_data
}
#[must_use]
pub fn digests(&self) -> PcrEventDigests<'_> {
PcrEventDigests {
data: self.digests,
algorithm_digest_sizes: self.algorithm_digest_sizes.clone(),
}
}
}
#[derive(Debug)]
pub struct EventLogIter<'a> {
log: &'a EventLog<'a>,
header: Option<EventLogHeader<'a>>,
location: *const u8,
}
impl<'a> Iterator for EventLogIter<'a> {
type Item = PcrEvent<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.location.is_null() || self.log.last_entry.is_null() {
return None;
}
let event = unsafe { PcrEvent::from_ptr(self.location, self.header.clone()?)? };
if self.location == self.log.last_entry {
self.location = ptr::null();
} else {
self.location = event.next;
}
Some(event)
}
}
#[derive(Debug)]
#[repr(transparent)]
#[unsafe_protocol(Tcg2Protocol::GUID)]
pub struct Tcg(Tcg2Protocol);
impl Tcg {
pub fn get_capability(&mut self) -> Result<BootServiceCapability> {
let mut capability = BootServiceCapability::default();
unsafe {
(self.0.get_capability)(&mut self.0, ptr::from_mut(&mut capability).cast())
.to_result_with_val(|| capability)
}
}
pub fn get_event_log_v1(&mut self) -> Result<v1::EventLog<'_>> {
let mut location = 0;
let mut last_entry = 0;
let mut truncated = 0;
let status = unsafe {
(self.0.get_event_log)(
&mut self.0,
EventLogFormat::TCG_1_2,
&mut location,
&mut last_entry,
&mut truncated,
)
};
if status.is_success() {
let is_truncated = truncated != 0;
let log = unsafe {
v1::EventLog::new(location as *const u8, last_entry as *const u8, is_truncated)
};
Ok(log)
} else {
Err(status.into())
}
}
pub fn get_event_log_v2(&mut self) -> Result<EventLog<'_>> {
let mut location = 0;
let mut last_entry = 0;
let mut truncated = 0;
let status = unsafe {
(self.0.get_event_log)(
&mut self.0,
EventLogFormat::TCG_2,
&mut location,
&mut last_entry,
&mut truncated,
)
};
if status.is_success() {
let is_truncated = truncated != 0;
let log = EventLog {
_lifetime: PhantomData,
location: location as *const u8,
last_entry: last_entry as *const u8,
is_truncated,
};
Ok(log)
} else {
Err(status.into())
}
}
pub fn hash_log_extend_event(
&mut self,
flags: HashLogExtendEventFlags,
data_to_hash: &[u8],
event: &PcrEventInputs,
) -> Result {
let event: *const PcrEventInputs = event;
let (event, _event_size) = ptr_meta::to_raw_parts(event);
unsafe {
(self.0.hash_log_extend_event)(
&mut self.0,
flags,
data_to_hash.as_ptr() as PhysicalAddress,
u64::try_from(data_to_hash.len()).unwrap(),
event.cast(),
)
.to_result()
}
}
pub fn submit_command(
&mut self,
input_parameter_block: &[u8],
output_parameter_block: &mut [u8],
) -> Result {
let input_parameter_block_len = u32::try_from(input_parameter_block.len())
.map_err(|_| Error::from(Status::BAD_BUFFER_SIZE))?;
let output_parameter_block_len = u32::try_from(output_parameter_block.len())
.map_err(|_| Error::from(Status::BAD_BUFFER_SIZE))?;
unsafe {
(self.0.submit_command)(
&mut self.0,
input_parameter_block_len,
input_parameter_block.as_ptr(),
output_parameter_block_len,
output_parameter_block.as_mut_ptr(),
)
.to_result()
}
}
pub fn get_active_pcr_banks(&mut self) -> Result<HashAlgorithm> {
let mut active_pcr_banks = Tcg2HashAlgorithmBitmap::empty();
let status = unsafe { (self.0.get_active_pcr_banks)(&mut self.0, &mut active_pcr_banks) };
status.to_result_with_val(|| HashAlgorithm::from_bits_retain(active_pcr_banks.bits()))
}
pub fn set_active_pcr_banks(&mut self, active_pcr_banks: HashAlgorithm) -> Result {
let active_pcr_banks = Tcg2HashAlgorithmBitmap::from_bits_retain(active_pcr_banks.bits());
unsafe { (self.0.set_active_pcr_banks)(&mut self.0, active_pcr_banks) }.to_result()
}
pub fn get_result_of_set_active_pcr_banks(&mut self) -> Result<Option<u32>> {
let mut operation_present = 0;
let mut response = 0;
let status = unsafe {
(self.0.get_result_of_set_active_pcr_banks)(
&mut self.0,
&mut operation_present,
&mut response,
)
};
status.to_result_with_val(|| {
if operation_present == 0 {
None
} else {
Some(response)
}
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec::Vec;
use core::slice;
#[test]
fn test_new_event() {
let mut buf = [0; 22];
let event_data = [0x12, 0x13, 0x14, 0x15];
let event =
PcrEventInputs::new_in_buffer(&mut buf, PcrIndex(4), EventType::IPL, &event_data)
.unwrap();
assert_eq!({ event.size }, 22);
assert_eq!(
event.event_header,
EventHeader {
header_size: 14,
header_version: 1,
pcr_index: 4,
event_type: EventType::IPL,
}
);
let event_ptr: *const PcrEventInputs = event;
let event_ptr: *const u8 = event_ptr.cast();
let event_bytes = unsafe { slice::from_raw_parts(event_ptr, size_of_val(event)) };
#[rustfmt::skip]
assert_eq!(event_bytes, [
0x16, 0x00, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00,
0x01, 0x00,
0x04, 0x00, 0x00, 0x00,
0x0d, 0x00, 0x00, 0x00,
0x12, 0x13, 0x14, 0x15,
]);
assert_eq!(
event,
&*PcrEventInputs::new_in_box(PcrIndex(4), EventType::IPL, &event_data).unwrap()
);
}
#[test]
fn test_event_log_v2() {
#[rustfmt::skip]
let bytes = [
0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2d, 0x00, 0x00, 0x00,
0x53, 0x70, 0x65, 0x63,
0x20, 0x49, 0x44, 0x20,
0x45, 0x76, 0x65, 0x6e,
0x74, 0x30, 0x33, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00,
0x02,
0x04, 0x00, 0x00, 0x00,
0x04, 0x00,
0x14, 0x00,
0x0b, 0x00,
0x20, 0x00,
0x0c, 0x00,
0x30, 0x00,
0x0d, 0x00,
0x40, 0x00,
0x00,
0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00,
0x04, 0x00,
0x14, 0x89, 0xf9, 0x23, 0xc4, 0xdc, 0xa7, 0x29, 0x17, 0x8b,
0x3e, 0x32, 0x33, 0x45, 0x85, 0x50, 0xd8, 0xdd, 0xdf, 0x29,
0x0b, 0x00,
0x96, 0xa2, 0x96, 0xd2, 0x24, 0xf2, 0x85, 0xc6,
0x7b, 0xee, 0x93, 0xc3, 0x0f, 0x8a, 0x30, 0x91,
0x57, 0xf0, 0xda, 0xa3, 0x5d, 0xc5, 0xb8, 0x7e,
0x41, 0x0b, 0x78, 0x63, 0x0a, 0x09, 0xcf, 0xc7,
0x0c, 0x00,
0x1d, 0xd6, 0xf7, 0xb4, 0x57, 0xad, 0x88, 0x0d,
0x84, 0x0d, 0x41, 0xc9, 0x61, 0x28, 0x3b, 0xab,
0x68, 0x8e, 0x94, 0xe4, 0xb5, 0x93, 0x59, 0xea,
0x45, 0x68, 0x65, 0x81, 0xe9, 0x0f, 0xec, 0xce,
0xa3, 0xc6, 0x24, 0xb1, 0x22, 0x61, 0x13, 0xf8,
0x24, 0xf3, 0x15, 0xeb, 0x60, 0xae, 0x0a, 0x7c,
0x0d, 0x00,
0x5e, 0xa7, 0x1d, 0xc6, 0xd0, 0xb4, 0xf5, 0x7b,
0xf3, 0x9a, 0xad, 0xd0, 0x7c, 0x20, 0x8c, 0x35,
0xf0, 0x6c, 0xd2, 0xba, 0xc5, 0xfd, 0xe2, 0x10,
0x39, 0x7f, 0x70, 0xde, 0x11, 0xd4, 0x39, 0xc6,
0x2e, 0xc1, 0xcd, 0xf3, 0x18, 0x37, 0x58, 0x86,
0x5f, 0xd3, 0x87, 0xfc, 0xea, 0x0b, 0xad, 0xa2,
0xf6, 0xc3, 0x7a, 0x4a, 0x17, 0x85, 0x1d, 0xd1,
0xd7, 0x8f, 0xef, 0xe6, 0xf2, 0x04, 0xee, 0x54,
0x02, 0x00, 0x00, 0x00,
0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x80,
0x04, 0x00, 0x00, 0x00,
0x04, 0x00,
0xc7, 0x06, 0xe7, 0xdd, 0x36, 0x39, 0x29, 0x84, 0xeb, 0x06,
0xaa, 0xa0, 0x8f, 0xf3, 0x36, 0x84, 0x40, 0x77, 0xb3, 0xed,
0x0b, 0x00,
0x3a, 0x30, 0x8e, 0x95, 0x87, 0x84, 0xbf, 0xd0,
0xf6, 0xe3, 0xf1, 0xbd, 0x4d, 0x42, 0x14, 0xd3,
0x0a, 0x4c, 0x55, 0x00, 0xa4, 0x5b, 0x06, 0xda,
0x96, 0xfc, 0x90, 0x33, 0x8f, 0x69, 0xb3, 0x61,
0x0c, 0x00,
0xc0, 0xd0, 0x75, 0x96, 0xc5, 0x9a, 0x90, 0x7b,
0x79, 0x71, 0x6f, 0xc9, 0xf3, 0x6a, 0xad, 0x8f,
0x0f, 0x26, 0xf2, 0x02, 0x67, 0x5b, 0x42, 0x5a,
0x52, 0x3f, 0x72, 0xec, 0xb6, 0xf2, 0x53, 0x99,
0x57, 0xf0, 0xd9, 0x2c, 0x0a, 0x7d, 0xce, 0xaa,
0xf9, 0x9e, 0x60, 0x0e, 0x54, 0x18, 0xf1, 0xdc,
0x0d, 0x00,
0x9a, 0xe9, 0x25, 0xdc, 0x9c, 0xd2, 0x9d, 0xf0,
0xe5, 0x80, 0x54, 0x35, 0xa5, 0x99, 0x06, 0x1f,
0xcf, 0x32, 0x98, 0xcc, 0x2a, 0x15, 0xe4, 0x87,
0x99, 0xa2, 0x0c, 0x9c, 0xe5, 0x6c, 0x8f, 0xe5,
0x84, 0x09, 0x75, 0xaf, 0xf0, 0xe1, 0xb6, 0x98,
0x20, 0x07, 0x5e, 0xe4, 0x29, 0x79, 0x8b, 0x5d,
0xbb, 0xe5, 0xd1, 0xa2, 0x74, 0x36, 0xab, 0x49,
0xf1, 0x9b, 0x7a, 0x04, 0x11, 0xd2, 0x96, 0x2c,
0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let log = EventLog {
_lifetime: PhantomData,
location: bytes.as_ptr(),
last_entry: unsafe { bytes.as_ptr().add(267) },
is_truncated: false,
};
let header = log.header().unwrap();
assert_eq!(header.platform_class, 0);
assert_eq!(header.spec_version, (2, 0, 0));
assert_eq!(header.uintn_size, 2);
assert_eq!(
header.algorithm_digest_sizes.0.to_vec(),
[
AlgorithmDigestSize {
algorithm_id: AlgorithmId::SHA1,
digest_size: 20,
},
AlgorithmDigestSize {
algorithm_id: AlgorithmId::SHA256,
digest_size: 32,
},
AlgorithmDigestSize {
algorithm_id: AlgorithmId::SHA384,
digest_size: 48,
},
AlgorithmDigestSize {
algorithm_id: AlgorithmId::SHA512,
digest_size: 64,
},
]
);
assert_eq!(header.vendor_info, []);
let mut iter = log.iter();
let entry = iter.next().unwrap();
assert_eq!(entry.pcr_index, PcrIndex(0));
assert_eq!(entry.event_type, EventType::CRTM_VERSION);
#[rustfmt::skip]
assert_eq!(
entry.digests().into_iter().collect::<Vec<_>>(),
[
(AlgorithmId::SHA1, [
0x14, 0x89, 0xf9, 0x23, 0xc4, 0xdc, 0xa7, 0x29, 0x17, 0x8b,
0x3e, 0x32, 0x33, 0x45, 0x85, 0x50, 0xd8, 0xdd, 0xdf, 0x29,
].as_slice()),
(AlgorithmId::SHA256, [
0x96, 0xa2, 0x96, 0xd2, 0x24, 0xf2, 0x85, 0xc6,
0x7b, 0xee, 0x93, 0xc3, 0x0f, 0x8a, 0x30, 0x91,
0x57, 0xf0, 0xda, 0xa3, 0x5d, 0xc5, 0xb8, 0x7e,
0x41, 0x0b, 0x78, 0x63, 0x0a, 0x09, 0xcf, 0xc7,
].as_slice()),
(AlgorithmId::SHA384, [
0x1d, 0xd6, 0xf7, 0xb4, 0x57, 0xad, 0x88, 0x0d,
0x84, 0x0d, 0x41, 0xc9, 0x61, 0x28, 0x3b, 0xab,
0x68, 0x8e, 0x94, 0xe4, 0xb5, 0x93, 0x59, 0xea,
0x45, 0x68, 0x65, 0x81, 0xe9, 0x0f, 0xec, 0xce,
0xa3, 0xc6, 0x24, 0xb1, 0x22, 0x61, 0x13, 0xf8,
0x24, 0xf3, 0x15, 0xeb, 0x60, 0xae, 0x0a, 0x7c,
].as_slice()),
(AlgorithmId::SHA512, [
0x5e, 0xa7, 0x1d, 0xc6, 0xd0, 0xb4, 0xf5, 0x7b,
0xf3, 0x9a, 0xad, 0xd0, 0x7c, 0x20, 0x8c, 0x35,
0xf0, 0x6c, 0xd2, 0xba, 0xc5, 0xfd, 0xe2, 0x10,
0x39, 0x7f, 0x70, 0xde, 0x11, 0xd4, 0x39, 0xc6,
0x2e, 0xc1, 0xcd, 0xf3, 0x18, 0x37, 0x58, 0x86,
0x5f, 0xd3, 0x87, 0xfc, 0xea, 0x0b, 0xad, 0xa2,
0xf6, 0xc3, 0x7a, 0x4a, 0x17, 0x85, 0x1d, 0xd1,
0xd7, 0x8f, 0xef, 0xe6, 0xf2, 0x04, 0xee, 0x54,
].as_slice()),
]
);
assert_eq!(entry.event_data, [0, 0]);
let entry = iter.next().unwrap();
assert_eq!(entry.pcr_index, PcrIndex(0));
assert_eq!(entry.event_type, EventType::EFI_PLATFORM_FIRMWARE_BLOB);
#[rustfmt::skip]
assert_eq!(
entry.digests().into_iter().collect::<Vec<_>>(),
[
(AlgorithmId::SHA1, [
0xc7, 0x06, 0xe7, 0xdd, 0x36, 0x39, 0x29, 0x84, 0xeb, 0x06,
0xaa, 0xa0, 0x8f, 0xf3, 0x36, 0x84, 0x40, 0x77, 0xb3, 0xed,
].as_slice()),
(AlgorithmId::SHA256, [
0x3a, 0x30, 0x8e, 0x95, 0x87, 0x84, 0xbf, 0xd0,
0xf6, 0xe3, 0xf1, 0xbd, 0x4d, 0x42, 0x14, 0xd3,
0x0a, 0x4c, 0x55, 0x00, 0xa4, 0x5b, 0x06, 0xda,
0x96, 0xfc, 0x90, 0x33, 0x8f, 0x69, 0xb3, 0x61,
].as_slice()),
(AlgorithmId::SHA384, [
0xc0, 0xd0, 0x75, 0x96, 0xc5, 0x9a, 0x90, 0x7b,
0x79, 0x71, 0x6f, 0xc9, 0xf3, 0x6a, 0xad, 0x8f,
0x0f, 0x26, 0xf2, 0x02, 0x67, 0x5b, 0x42, 0x5a,
0x52, 0x3f, 0x72, 0xec, 0xb6, 0xf2, 0x53, 0x99,
0x57, 0xf0, 0xd9, 0x2c, 0x0a, 0x7d, 0xce, 0xaa,
0xf9, 0x9e, 0x60, 0x0e, 0x54, 0x18, 0xf1, 0xdc,
].as_slice()),
(AlgorithmId::SHA512, [
0x9a, 0xe9, 0x25, 0xdc, 0x9c, 0xd2, 0x9d, 0xf0,
0xe5, 0x80, 0x54, 0x35, 0xa5, 0x99, 0x06, 0x1f,
0xcf, 0x32, 0x98, 0xcc, 0x2a, 0x15, 0xe4, 0x87,
0x99, 0xa2, 0x0c, 0x9c, 0xe5, 0x6c, 0x8f, 0xe5,
0x84, 0x09, 0x75, 0xaf, 0xf0, 0xe1, 0xb6, 0x98,
0x20, 0x07, 0x5e, 0xe4, 0x29, 0x79, 0x8b, 0x5d,
0xbb, 0xe5, 0xd1, 0xa2, 0x74, 0x36, 0xab, 0x49,
0xf1, 0x9b, 0x7a, 0x04, 0x11, 0xd2, 0x96, 0x2c,
].as_slice()),
]
);
#[rustfmt::skip]
assert_eq!(entry.event_data, [
0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
]);
assert!(iter.next().is_none());
}
}