rust/(pv|pvimg): Add Secure Execution boot image metadata

Add metadata about the image to the Secure Execution image. This helps
to identify where the Secure Execution header is located in the image
and therefore it's less prone to errors to locate the header.

This patch adds the support for it to 'pvimg' as well as to the
'pvsecret' and 'pvattest' tools.

Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Marc Hartmayer
2024-11-28 15:48:31 +01:00
committed by Jan Höppner
parent f4cf4ae6eb
commit d2de7f2808
7 changed files with 228 additions and 29 deletions
+110 -2
View File
@@ -7,7 +7,7 @@ use std::{
mem::size_of,
};
use log::debug;
use log::{debug, warn};
use zerocopy::{AsBytes, BigEndian, FromBytes, FromZeroes, U32, U64};
// (SE) boot request control block aka SE header
@@ -46,6 +46,81 @@ impl TryFrom<Vec<u8>> for BootHdrTags {
}
}
/// Struct representing the Secure Execution boot image metadata
#[allow(unused)]
#[repr(packed)]
#[derive(Debug, Clone, FromBytes, FromZeroes, AsBytes, PartialEq, Eq)]
pub struct SeImgMetaData {
/// Magic value
magic: [u8; 8],
/// Secure Execution header offset in the image
hdr_off: U64<BigEndian>,
/// Version
version: U32<BigEndian>,
/// IPIB offset in the image
ipib_off: U64<BigEndian>,
}
assert_size!(SeImgMetaData, 28);
impl SeImgMetaData {
/// Address in the Secure Execution boot image
pub const OFFSET: u64 = 0xc000;
/// V1 of the Secure Execution boot image metadata
const V1: u32 = 0x1;
/// Create v1 Secure Execution image metadata.
pub fn new_v1(hdr_off: u64, ipib_off: u64) -> Self {
Self {
magic: Self::MAGIC,
version: Self::V1.into(),
hdr_off: hdr_off.into(),
ipib_off: ipib_off.into(),
}
}
fn seek_start<R>(img: &mut R) -> Result<bool>
where
R: Read + Seek,
{
const BUF_SIZE: i64 = 8;
static_assert!(SeImgMetaData::MAGIC.len() == BUF_SIZE as usize);
let mut buf = [0; BUF_SIZE as usize];
match img.seek(std::io::SeekFrom::Start(Self::OFFSET)) {
Ok(it) => it,
Err(_) => return Ok(false),
};
match img.read_exact(&mut buf) {
Ok(it) => it,
Err(_) => return Ok(false),
}
if Self::starts_with_magic(&buf) {
// go back to the beginning of the metadata
img.seek(Current(-BUF_SIZE))?;
return Ok(true);
}
Ok(false)
}
/// Gets the bytes of this value.
#[inline(always)]
pub fn as_bytes(&self) -> &[u8] {
<Self as AsBytes>::as_bytes(self)
}
/// Returns the version of this [`SeImgMetaData`].
pub fn version(&self) -> u32 {
self.version.into()
}
}
/// Magic value for the metadata of a Secure Execution boot image
impl MagicValue<8> for SeImgMetaData {
// ASCII `SeImgLnx`
const MAGIC: [u8; 8] = [0x53, 0x65, 0x49, 0x6d, 0x67, 0x4c, 0x6e, 0x78];
}
/// Magic value for a SE-(boot)header
#[derive(Debug)]
pub struct BootHdrMagic;
@@ -65,10 +140,30 @@ pub fn seek_se_hdr_start<R>(img: &mut R) -> Result<bool>
where
R: Read + Seek,
{
let max_iter: usize = 0x15;
let max_iter: usize;
const BUF_SIZE: i64 = 8;
static_assert!(BootHdrMagic::MAGIC.len() == BUF_SIZE as usize);
let old_position = img.stream_position()?;
if !SeImgMetaData::seek_start(img)? {
// Search from the previous position.
img.seek(std::io::SeekFrom::Start(old_position))?;
max_iter = 0x15;
} else {
let mut img_metadata_bytes = vec![0u8; size_of::<SeImgMetaData>()];
// read in the header
img.read_exact(&mut img_metadata_bytes)?;
// Cannot fail because the buffer has the same size as SeImgMetaData.
let img_metadata = SeImgMetaData::ref_from(&img_metadata_bytes).unwrap();
let img_metadata_version = img_metadata.version();
if img_metadata_version != SeImgMetaData::V1 {
warn!("Unknown Secure Execution boot image version {img_metadata_version}");
}
img.seek(std::io::SeekFrom::Start(img_metadata.hdr_off.into()))?;
max_iter = 1;
}
let mut buf = [0; BUF_SIZE as usize];
for _ in 0..max_iter {
match img.read_exact(&mut buf) {
@@ -284,4 +379,17 @@ mod tests {
let der: Result<BootHdrTags> = ser.clone().try_into();
assert!(matches!(der, Err(Error::InvBootHdrSize(_))));
}
#[test]
fn se_img_metadata() {
let metadata = SeImgMetaData::new_v1(0x14000, 0x16000);
let data = [
83, 101, 73, 109, 103, 76, 110, 120, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 1, 96, 0,
];
assert_eq!(metadata.as_bytes(), &data);
assert_eq!(SeImgMetaData::ref_from(&data), Some(&metadata));
assert_eq!(metadata.version(), SeImgMetaData::V1);
}
}
+1 -1
View File
@@ -86,7 +86,7 @@ pub use crate::error::HkdVerifyErrorType;
/// Functionalities to build UV requests
pub mod request {
pub use crate::{
brcb::{seek_se_hdr_start, BootHdrTags},
brcb::{seek_se_hdr_start, BootHdrTags, SeImgMetaData},
crypto::{
decrypt_aead, derive_aes256_gcm_key, encrypt_aead, gen_ec_key, random_array,
AeadDecryptionResult, AeadEncryptionResult, Aes256GcmKey, Aes256XtsKey, SymKey,