Files
s390-tools/rust/pvimg/src/cmd/test.rs
Marc Hartmayer 08d21b24b4 pvimg: Use indexed array for UV key hashes
Replace individual UV key hash fields with an indexed array and
introduce dedicated types for hash indices and key hash kinds. This
simplifies hash handling.

Co-developed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Marc Hartmayer <marc@linux.ibm.com>
Reviewed-by: Steffen Eiden <seiden@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2026-07-31 09:51:14 +02:00

109 lines
3.2 KiB
Rust

// SPDX-License-Identifier: MIT
//
// Copyright IBM Corp. 2024
use std::path::Path;
use anyhow::Result;
use log::{info, warn};
use pv::misc::open_file;
use pv::request::NoVerifyHkd;
use pv::{FileAccessErrorType, PvCoreError};
use pvimg::error::{Error, OwnExitCode};
use pvimg::uvdata::{KeyExchangeTrait, SeHdr, UvKeyHashesV1};
use utils::hkd::{HkdLoader, HkdVersionSelection};
use utils::HexSlice;
use crate::cli::TestArgs;
use crate::log_println;
/// Returns `Ok(true)` if at least one of the hashes is included.
fn hdr_test_target_hashes(hdr: &SeHdr, key_hashes: &Path) -> Result<bool> {
let file = open_file(key_hashes).map_err(|err| match err {
PvCoreError::FileAccess {
ref ty,
ref path,
ref source,
} if matches!(ty, FileAccessErrorType::Open)
&& source.kind() == std::io::ErrorKind::NotFound
&& path == Path::new(UvKeyHashesV1::SYS_UV_KEYS_ALL) =>
{
Error::UnavailableQueryUvKeyHashesSupport { source: err }
}
err => Error::PvCore(err),
})?;
let hashes = UvKeyHashesV1::read_from_io(file)?;
let matches = hashes.matching_hashes(hdr);
if matches.is_empty() {
warn!(" ✘ None of the key hashes is included");
Ok(false)
} else {
for m in matches {
match m.idx.kind() {
Some(kind) => {
log_println!(" ✓ {kind} {:#} is included", HexSlice::from(&m.hash))
}
None => log_println!(
" ✓ Key hash {:#} is included (zero-based index {})",
HexSlice::from(&m.hash),
m.idx.index()
),
}
}
Ok(true)
}
}
/// Returns `Ok(true)` if at least one of the given public key of the host key
/// documents was used for the image creation or if no host key document was
/// specified.
fn hdr_test_hkd<P>(hdr: &SeHdr, host_key_documents: &[P]) -> Result<bool>
where
P: AsRef<Path>,
{
if host_key_documents.is_empty() {
return Ok(true);
}
let mut result = false;
for path in host_key_documents {
let hkd = HkdLoader::load_and_verify(
path,
&NoVerifyHkd,
HkdVersionSelection::Explicit(hdr.common.version.into()),
)?;
if hdr.contains(hkd)? {
result = true;
log_println!(
" ✓ Host key document '{}' is included",
path.as_ref().display()
);
} else {
log_println!(
" ✘ Host key document '{}' is not included",
path.as_ref().display()
);
}
}
Ok(result)
}
pub fn test(opt: &TestArgs) -> Result<OwnExitCode> {
info!("Testing a Secure Execution image");
let mut input = open_file(&opt.input.path)?;
SeHdr::seek_sehdr(&mut input, None)?;
let hdr = SeHdr::try_from_io(input)?;
let mut success = hdr_test_hkd(&hdr, &opt.host_key_documents)?;
if let Some(path) = &opt.key_hashes {
success = hdr_test_target_hashes(&hdr, path)? && success;
}
Ok(if success {
OwnExitCode::Success
} else {
OwnExitCode::GenericError
})
}