Skip to content

Add PcrEvent::new_in_box/PcrEventInputs::new_in_box #1246

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 16, 2024
Merged
5 changes: 2 additions & 3 deletions uefi-test-runner/src/proto/tcg.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 =
Expand Down
5 changes: 5 additions & 0 deletions uefi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -14,6 +16,9 @@
The old `MemoryMap` was renamed to `MemoryMapOwned`.
- `pub fn memory_map(&self, mt: MemoryType) -> Result<MemoryMap>` now returns
a `MemoryMapOwned`.
- **Breaking:** `PcrEvent::new_in_buffer` and `PcrEventInputs::new_in_buffer`
now take an initialized buffer (`[u8`] instead of `[MaybeUninit<u8>]`), and if
the buffer is too small the required size is returned in the error data.


# uefi - 0.29.0 (2024-07-02)
Expand Down
66 changes: 54 additions & 12 deletions uefi/src/proto/tcg/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,21 @@
//! [TPM]: https://en.wikipedia.org/wiki/Trusted_Platform_Module

use super::{AlgorithmId, EventType, HashAlgorithm, PcrIndex};
use crate::data_types::PhysicalAddress;
use crate::polyfill::maybe_uninit_slice_as_mut_ptr;
use crate::data_types::{Align, PhysicalAddress};
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;

#[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];

Expand Down Expand Up @@ -128,19 +132,19 @@ 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.
pub fn new_in_buffer<'buf>(
buffer: &'buf mut [MaybeUninit<u8>],
buffer: &'buf mut [u8],
pcr_index: PcrIndex,
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<usize>> {
let event_data_size = u32::try_from(event_data.len())
.map_err(|_| Error::new(Status::INVALID_PARAMETER, None))?;

let required_size = mem::size_of::<PcrIndex>()
+ mem::size_of::<EventType>()
Expand All @@ -149,10 +153,10 @@ 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);
let mut ptr: *mut u8 = buffer.as_mut_ptr().cast();

unsafe {
ptr_write_unaligned_and_add(&mut ptr, pcr_index);
Expand All @@ -167,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<Box<Self>> {
#[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 {
Expand Down Expand Up @@ -200,6 +230,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 {
Expand Down Expand Up @@ -533,7 +569,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,
Expand Down Expand Up @@ -571,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]
Expand Down
77 changes: 64 additions & 13 deletions uefi/src/proto/tcg/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,22 @@
//! [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};
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};

#[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`.
Expand Down Expand Up @@ -158,7 +163,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,
Expand All @@ -172,24 +177,24 @@ 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.
pub fn new_in_buffer<'buf>(
buffer: &'buf mut [MaybeUninit<u8>],
buffer: &'buf mut [u8],
pcr_index: PcrIndex,
event_type: EventType,
event_data: &[u8],
) -> Result<&'buf Self> {
) -> Result<&'buf mut Self, Option<usize>> {
let required_size =
mem::size_of::<u32>() + mem::size_of::<EventHeader>() + 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();

Expand All @@ -206,13 +211,44 @@ 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)
}
}

/// 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<Box<Self>> {
#[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 {
fn alignment() -> usize {
1
}
}

impl Debug for PcrEventInputs {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("PcrEventInputs")
Expand All @@ -223,6 +259,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 {
Expand Down Expand Up @@ -785,7 +830,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)
Expand Down Expand Up @@ -824,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]
Expand Down