// SPDX-License-Identifier: MIT // // Copyright IBM Corp. 2024 use std::path::Path; use anyhow::Result; use log::{info, warn}; use pv::misc::{open_file, read_hkd}; use pv::{FileAccessErrorType, PvCoreError}; use pvimg::error::{Error, OwnExitCode}; use pvimg::uvdata::{KeyExchangeTrait, SeHdr, UvKeyHashesV1}; 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 { 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 mut contains = hdr.contains_hash(&hashes.pchkh); if contains { log_println!( " ✓ Host key hash {:#} is included", HexSlice::from(&hashes.pchkh) ); } if hdr.contains_hash(&hashes.pbhkh) { log_println!( " ✓ Backup host key hash {:#} is included", HexSlice::from(&hashes.pbhkh) ); contains = true; }; for hash in hashes.res { if hdr.contains_hash(&hash) { log_println!(" ✓ Key hash {:#} is included", HexSlice::from(&hash)); contains = true; } } if !contains { warn!(" ✘ None of the key hashes is included"); } Ok(contains) } /// 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

(hdr: &SeHdr, host_key_documents: &[P]) -> Result where P: AsRef, { if host_key_documents.is_empty() { return Ok(true); } let mut result = false; for path in host_key_documents { let hkd = read_hkd(path)?; 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 { 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 }) }