From 2cd0d9180d9541944c7ce8582a81a3d4f5c6328f Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 14 Jul 2024 23:34:00 -0400 Subject: [PATCH 1/7] tcg: PcrEvent/PcrEventInputs: impl Align This is needed for make_boxed. --- uefi/src/proto/tcg/v1.rs | 8 +++++++- uefi/src/proto/tcg/v2.rs | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/uefi/src/proto/tcg/v1.rs b/uefi/src/proto/tcg/v1.rs index 7f0226806..d67665538 100644 --- a/uefi/src/proto/tcg/v1.rs +++ b/uefi/src/proto/tcg/v1.rs @@ -9,7 +9,7 @@ //! [TPM]: https://en.wikipedia.org/wiki/Trusted_Platform_Module use super::{AlgorithmId, EventType, HashAlgorithm, PcrIndex}; -use crate::data_types::PhysicalAddress; +use crate::data_types::{Align, PhysicalAddress}; use crate::polyfill::maybe_uninit_slice_as_mut_ptr; use crate::proto::unsafe_protocol; use crate::util::{ptr_write_unaligned_and_add, usize_from_u32}; @@ -200,6 +200,12 @@ impl PcrEvent { } } +impl Align for PcrEvent { + fn alignment() -> usize { + 1 + } +} + // Manual `Debug` implementation since it can't be derived for a packed DST. impl Debug for PcrEvent { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { diff --git a/uefi/src/proto/tcg/v2.rs b/uefi/src/proto/tcg/v2.rs index 86b3bb39c..324a3748d 100644 --- a/uefi/src/proto/tcg/v2.rs +++ b/uefi/src/proto/tcg/v2.rs @@ -11,7 +11,7 @@ //! [TPM]: https://en.wikipedia.org/wiki/Trusted_Platform_Module use super::{v1, AlgorithmId, EventType, HashAlgorithm, PcrIndex}; -use crate::data_types::{PhysicalAddress, UnalignedSlice}; +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}; @@ -213,6 +213,12 @@ impl PcrEventInputs { } } +impl Align for PcrEventInputs { + fn alignment() -> usize { + 1 + } +} + impl Debug for PcrEventInputs { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { f.debug_struct("PcrEventInputs") From 373c4eafc5de137859e33c1ecdc41a07d8e0ee3e Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 14 Jul 2024 23:39:16 -0400 Subject: [PATCH 2/7] tcg: PcrEvent/PcrEventInputs: return required size on error This is needed for make_boxed. --- uefi/src/proto/tcg/v1.rs | 10 +++++----- uefi/src/proto/tcg/v2.rs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/uefi/src/proto/tcg/v1.rs b/uefi/src/proto/tcg/v1.rs index d67665538..2700457ae 100644 --- a/uefi/src/proto/tcg/v1.rs +++ b/uefi/src/proto/tcg/v1.rs @@ -128,7 +128,7 @@ impl PcrEvent { /// # Errors /// /// Returns [`Status::BUFFER_TOO_SMALL`] if the `buffer` is not large - /// enough. + /// enough. The required size will be returned in the error data. /// /// Returns [`Status::INVALID_PARAMETER`] if the `event_data` size is too /// large. @@ -138,9 +138,9 @@ impl PcrEvent { event_type: EventType, digest: Sha1Digest, event_data: &[u8], - ) -> Result<&'buf mut Self> { - let event_data_size = - u32::try_from(event_data.len()).map_err(|_| Error::from(Status::INVALID_PARAMETER))?; + ) -> Result<&'buf mut Self, Option> { + let event_data_size = u32::try_from(event_data.len()) + .map_err(|_| Error::new(Status::INVALID_PARAMETER, None))?; let required_size = mem::size_of::() + mem::size_of::() @@ -149,7 +149,7 @@ impl PcrEvent { + event_data.len(); if buffer.len() < required_size { - return Err(Status::BUFFER_TOO_SMALL.into()); + return Err(Error::new(Status::BUFFER_TOO_SMALL, Some(required_size))); } let mut ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(buffer); diff --git a/uefi/src/proto/tcg/v2.rs b/uefi/src/proto/tcg/v2.rs index 324a3748d..fba342872 100644 --- a/uefi/src/proto/tcg/v2.rs +++ b/uefi/src/proto/tcg/v2.rs @@ -172,7 +172,7 @@ impl PcrEventInputs { /// # Errors /// /// Returns [`Status::BUFFER_TOO_SMALL`] if the `buffer` is not large - /// enough. + /// enough. The required size will be returned in the error data. /// /// Returns [`Status::INVALID_PARAMETER`] if the `event_data` size is too /// large. @@ -181,15 +181,15 @@ impl PcrEventInputs { pcr_index: PcrIndex, event_type: EventType, event_data: &[u8], - ) -> Result<&'buf Self> { + ) -> Result<&'buf Self, Option> { let required_size = mem::size_of::() + mem::size_of::() + event_data.len(); if buffer.len() < required_size { - return Err(Status::BUFFER_TOO_SMALL.into()); + return Err(Error::new(Status::BUFFER_TOO_SMALL, Some(required_size))); } - let size_field = - u32::try_from(required_size).map_err(|_| Error::from(Status::INVALID_PARAMETER))?; + 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(); From d83e1d57055ff14b2c05f3583eb7a30d1743e1ef Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 14 Jul 2024 23:47:57 -0400 Subject: [PATCH 3/7] tcg: PcrEvent/PcrEventInputs: use initialized buf for input This is needed for make_boxed. Technically it's slightly less efficient, since the input buf must now be initialized, but in practice these structs are quite small and not created all that often, so there's no meaningful difference. --- uefi-test-runner/src/proto/tcg.rs | 5 ++--- uefi/src/proto/tcg/v1.rs | 10 ++++------ uefi/src/proto/tcg/v2.rs | 5 ++--- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/uefi-test-runner/src/proto/tcg.rs b/uefi-test-runner/src/proto/tcg.rs index 21e0cce55..b74772578 100644 --- a/uefi-test-runner/src/proto/tcg.rs +++ b/uefi-test-runner/src/proto/tcg.rs @@ -1,5 +1,4 @@ use alloc::vec::Vec; -use core::mem::MaybeUninit; use uefi::proto::tcg::{v1, v2, AlgorithmId, EventType, HashAlgorithm, PcrIndex}; use uefi::table::boot::BootServices; @@ -63,7 +62,7 @@ fn test_tcg_v1(bt: &BootServices) { let pcr_index = PcrIndex(8); - let mut event_buf = [MaybeUninit::uninit(); 256]; + let mut event_buf = [0; 256]; let event = v1::PcrEvent::new_in_buffer( &mut event_buf, pcr_index, @@ -279,7 +278,7 @@ pub fn test_tcg_v2(bt: &BootServices) { // Create a PCR event. let pcr_index = PcrIndex(8); - let mut event_buf = [MaybeUninit::uninit(); 256]; + let mut event_buf = [0; 256]; let event_data = [0x12, 0x13, 0x14, 0x15]; let data_to_hash = b"some-data"; let event = diff --git a/uefi/src/proto/tcg/v1.rs b/uefi/src/proto/tcg/v1.rs index 2700457ae..45a8d73ae 100644 --- a/uefi/src/proto/tcg/v1.rs +++ b/uefi/src/proto/tcg/v1.rs @@ -10,14 +10,12 @@ use super::{AlgorithmId, EventType, HashAlgorithm, PcrIndex}; use crate::data_types::{Align, PhysicalAddress}; -use crate::polyfill::maybe_uninit_slice_as_mut_ptr; 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::mem::{self, MaybeUninit}; -use core::ptr; +use core::{mem, ptr}; use ptr_meta::Pointee; /// 20-byte SHA-1 digest. @@ -133,7 +131,7 @@ impl PcrEvent { /// Returns [`Status::INVALID_PARAMETER`] if the `event_data` size is too /// large. pub fn new_in_buffer<'buf>( - buffer: &'buf mut [MaybeUninit], + buffer: &'buf mut [u8], pcr_index: PcrIndex, event_type: EventType, digest: Sha1Digest, @@ -152,7 +150,7 @@ impl PcrEvent { return Err(Error::new(Status::BUFFER_TOO_SMALL, Some(required_size))); } - let mut ptr: *mut u8 = maybe_uninit_slice_as_mut_ptr(buffer); + let mut ptr: *mut u8 = buffer.as_mut_ptr().cast(); unsafe { ptr_write_unaligned_and_add(&mut ptr, pcr_index); @@ -539,7 +537,7 @@ mod tests { #[test] fn test_new_pcr_event() { - let mut event_buf = [MaybeUninit::uninit(); 256]; + let mut event_buf = [0; 256]; #[rustfmt::skip] let digest = [ 0x00, 0x01, 0x02, 0x03, diff --git a/uefi/src/proto/tcg/v2.rs b/uefi/src/proto/tcg/v2.rs index fba342872..b3fbf5e71 100644 --- a/uefi/src/proto/tcg/v2.rs +++ b/uefi/src/proto/tcg/v2.rs @@ -18,7 +18,6 @@ use crate::{Error, Result, Status, StatusExt}; use bitflags::bitflags; use core::fmt::{self, Debug, Formatter}; use core::marker::PhantomData; -use core::mem::MaybeUninit; use core::{mem, ptr, slice}; use ptr_meta::{Pointee, PtrExt}; @@ -177,7 +176,7 @@ impl PcrEventInputs { /// Returns [`Status::INVALID_PARAMETER`] if the `event_data` size is too /// large. pub fn new_in_buffer<'buf>( - buffer: &'buf mut [MaybeUninit], + buffer: &'buf mut [u8], pcr_index: PcrIndex, event_type: EventType, event_data: &[u8], @@ -791,7 +790,7 @@ mod tests { #[test] fn test_new_event() { - let mut buf = [MaybeUninit::uninit(); 22]; + 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) From 6bead2e37aa59dc89a1891fac44f3dba02baebe1 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 14 Jul 2024 23:51:35 -0400 Subject: [PATCH 4/7] tcg: Impl Eq/PartialEq for PcrEventInputs A manual implementation is required since this is a packed struct. --- uefi/src/proto/tcg/v2.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/uefi/src/proto/tcg/v2.rs b/uefi/src/proto/tcg/v2.rs index b3fbf5e71..af3b96f39 100644 --- a/uefi/src/proto/tcg/v2.rs +++ b/uefi/src/proto/tcg/v2.rs @@ -157,7 +157,7 @@ struct EventHeader { /// `TCG_PCR_EVENT2` for reading events. To help clarify the usage, our /// API renames these types to `PcrEventInputs` and `PcrEvent`, /// respectively. -#[derive(Pointee)] +#[derive(Eq, Pointee)] #[repr(C, packed)] pub struct PcrEventInputs { size: u32, @@ -228,6 +228,15 @@ impl Debug for PcrEventInputs { } } +// Manual `PartialEq` implementation since it can't be derived for a packed DST. +impl PartialEq for PcrEventInputs { + fn eq(&self, other: &PcrEventInputs) -> 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 { From 6c726f3836559162b890ff82b59152e812e3fbad Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 14 Jul 2024 23:49:43 -0400 Subject: [PATCH 5/7] tcg: Return a mut ref from PcrEventInputs::new_in_buffer This is needed for make_boxed. --- uefi/src/proto/tcg/v2.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/uefi/src/proto/tcg/v2.rs b/uefi/src/proto/tcg/v2.rs index af3b96f39..1c27d67c9 100644 --- a/uefi/src/proto/tcg/v2.rs +++ b/uefi/src/proto/tcg/v2.rs @@ -180,7 +180,7 @@ impl PcrEventInputs { pcr_index: PcrIndex, event_type: EventType, event_data: &[u8], - ) -> Result<&'buf Self, Option> { + ) -> Result<&'buf mut Self, Option> { let required_size = mem::size_of::() + mem::size_of::() + event_data.len(); @@ -205,9 +205,9 @@ impl PcrEventInputs { ); ptr::copy(event_data.as_ptr(), ptr, event_data.len()); - let ptr: *const PcrEventInputs = - ptr_meta::from_raw_parts(buffer.as_ptr().cast(), event_data.len()); - Ok(&*ptr) + let ptr: *mut PcrEventInputs = + ptr_meta::from_raw_parts_mut(buffer.as_mut_ptr().cast(), event_data.len()); + Ok(&mut *ptr) } } } From 2e0be2a7c1be01f260801d382b71da83e34a4e0c Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 14 Jul 2024 23:58:56 -0400 Subject: [PATCH 6/7] tcg: PcrEvent/PcrEventInputs: add new_in_box constructors --- uefi/src/proto/tcg/v1.rs | 38 ++++++++++++++++++++++++++++++++++++++ uefi/src/proto/tcg/v2.rs | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/uefi/src/proto/tcg/v1.rs b/uefi/src/proto/tcg/v1.rs index 45a8d73ae..0fc55a7da 100644 --- a/uefi/src/proto/tcg/v1.rs +++ b/uefi/src/proto/tcg/v1.rs @@ -18,6 +18,12 @@ use core::marker::PhantomData; use core::{mem, ptr}; use ptr_meta::Pointee; +#[cfg(feature = "alloc")] +use {crate::mem::make_boxed, alloc::boxed::Box}; + +#[cfg(all(feature = "unstable", feature = "alloc"))] +use {alloc::alloc::Global, core::alloc::Allocator}; + /// 20-byte SHA-1 digest. pub type Sha1Digest = [u8; 20]; @@ -165,6 +171,32 @@ impl PcrEvent { } } + /// Create a new `PcrEvent` in a [`Box`]. + /// + /// # Errors + /// + /// Returns [`Status::INVALID_PARAMETER`] if the `event_data` size is too + /// large. + #[cfg(feature = "alloc")] + pub fn new_in_box( + pcr_index: PcrIndex, + event_type: EventType, + digest: Sha1Digest, + event_data: &[u8], + ) -> Result> { + #[cfg(not(feature = "unstable"))] + { + make_boxed(|buf| Self::new_in_buffer(buf, pcr_index, event_type, digest, event_data)) + } + #[cfg(feature = "unstable")] + { + make_boxed( + |buf| Self::new_in_buffer(buf, pcr_index, event_type, digest, event_data), + Global, + ) + } + } + /// PCR index for the event. #[must_use] pub fn pcr_index(&self) -> PcrIndex { @@ -575,6 +607,12 @@ mod tests { // Event data 0x14, 0x15, 0x16, 0x17, ]); + + // Check that `new_in_box` gives the same value. + assert_eq!( + event, + &*PcrEvent::new_in_box(PcrIndex(4), EventType::IPL, digest, &data).unwrap() + ); } #[test] diff --git a/uefi/src/proto/tcg/v2.rs b/uefi/src/proto/tcg/v2.rs index 1c27d67c9..df762f311 100644 --- a/uefi/src/proto/tcg/v2.rs +++ b/uefi/src/proto/tcg/v2.rs @@ -21,6 +21,12 @@ use core::marker::PhantomData; use core::{mem, ptr, slice}; use ptr_meta::{Pointee, PtrExt}; +#[cfg(feature = "alloc")] +use {crate::mem::make_boxed, alloc::boxed::Box}; + +#[cfg(all(feature = "unstable", feature = "alloc"))] +use {alloc::alloc::Global, core::alloc::Allocator}; + /// Version information. /// /// Layout compatible with the C type `EFI_TG2_VERSION`. @@ -210,6 +216,31 @@ impl PcrEventInputs { Ok(&mut *ptr) } } + + /// Create a new `PcrEventInputs` in a [`Box`]. + /// + /// # Errors + /// + /// Returns [`Status::INVALID_PARAMETER`] if the `event_data` size is too + /// large. + #[cfg(feature = "alloc")] + pub fn new_in_box( + pcr_index: PcrIndex, + event_type: EventType, + event_data: &[u8], + ) -> Result> { + #[cfg(not(feature = "unstable"))] + { + make_boxed(|buf| Self::new_in_buffer(buf, pcr_index, event_type, event_data)) + } + #[cfg(feature = "unstable")] + { + make_boxed( + |buf| Self::new_in_buffer(buf, pcr_index, event_type, event_data), + Global, + ) + } + } } impl Align for PcrEventInputs { @@ -838,6 +869,12 @@ mod tests { // Event data 0x12, 0x13, 0x14, 0x15, ]); + + // Check that `new_in_box` gives the same value. + assert_eq!( + event, + &*PcrEventInputs::new_in_box(PcrIndex(4), EventType::IPL, &event_data).unwrap() + ); } #[test] From 8bc76055948e6d9de0fd7c5ba2831a7ccc2fd3a1 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Mon, 15 Jul 2024 00:10:00 -0400 Subject: [PATCH 7/7] uefi: Update changelog --- uefi/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/uefi/CHANGELOG.md b/uefi/CHANGELOG.md index 5119d3547..c00f2a651 100644 --- a/uefi/CHANGELOG.md +++ b/uefi/CHANGELOG.md @@ -4,6 +4,8 @@ - `uefi::system` is a new module that provides freestanding functions for accessing fields of the global system table. - Add standard derives for `ConfigTableEntry`. +- `PcrEvent`/`PcrEventInputs` impl `Align`, `Eq`, and `PartialEq`. +- Added `PcrEvent::new_in_box` and `PcrEventInputs::new_in_box`. ## Changed - **Breaking:** `uefi::helpers::init` no longer takes an argument. @@ -14,6 +16,9 @@ The old `MemoryMap` was renamed to `MemoryMapOwned`. - `pub fn memory_map(&self, mt: MemoryType) -> Result` now returns a `MemoryMapOwned`. +- **Breaking:** `PcrEvent::new_in_buffer` and `PcrEventInputs::new_in_buffer` + now take an initialized buffer (`[u8`] instead of `[MaybeUninit]`), and if + the buffer is too small the required size is returned in the error data. # uefi - 0.29.0 (2024-07-02)