From 25b3093c4d87b5c2023c3a37809d244faf2088a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ravier?= Date: Wed, 24 Sep 2025 19:22:01 +0200 Subject: [PATCH 1/7] WIP --- cli/src/main.rs | 53 +++++++++++++++++++++++++++---- justfile | 18 +++++++++++ lib/src/lib.rs | 16 ++++++++-- lib/src/tpmevents/compute.rs | 60 +++++++++++++++++++++++++++++++++++- 4 files changed, 138 insertions(+), 9 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index ef63254..c6b40d4 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -10,6 +10,8 @@ use clap::{Args, Parser, Subcommand}; use log::LevelFilter; use serde::{Deserialize, Serialize}; +use std::path::PathBuf; + use compute_pcrs_lib::*; #[derive(Parser, Debug)] @@ -36,7 +38,12 @@ struct SecureBootVarStores { #[derive(Subcommand, Debug)] enum Command { - /// Compute all possible PCR values from the binaries available in the current environment + /// Compute the Authentihash of a PE binary + Authentihash { + /// Path to a PE binary + binary: String, + }, + /// Compute all possible PCR values from the binaries available in the current environment. Meant to be run inside a Bootable Container. All { #[arg( long, @@ -66,8 +73,8 @@ enum Command { )] mok_variables: String, }, - /// Compute PCR 4 - Pcr4 { + /// Compute PCR 4 for the non UKI case + Pcr4NoUki { #[arg( long, short, @@ -88,6 +95,25 @@ enum Command { )] no_secureboot: bool, }, + /// Compute PCR 4 for the Bootable Container UKI case + Pcr4 { + #[arg( + long, + short, + default_value = "/", + help = "Path to the target container image root filesystem" + )] + rootfs: String, + #[arg( + long, + short, + default_value = "/boot/EFI/Linux/uki.efi", + help = "Path to the UKI binary" + )] + uki: String, + #[arg(long, help = "Path to a UKI addon (can be passed multiple times)")] + uki_addon: Vec, + }, /// Compute PCR 7 Pcr7 { #[arg( @@ -143,6 +169,11 @@ fn main() -> Result<()> { .init(); match &cli.command { + Command::Authentihash { binary } => { + let hash = authentihash(&PathBuf::from(binary)).unwrap(); + println!("{hash}"); + Ok(()) + } Command::All { rootfs, secureboot_variables, @@ -152,7 +183,7 @@ fn main() -> Result<()> { } => { let rfs = rootfs::RootFSTree::new(rootfs).unwrap(); let pcrs = vec![ - compute_pcr4(rfs.vmlinuz(), rfs.esp(), *uki, !no_secureboot), + compute_pcr4_nouki(rfs.vmlinuz(), rfs.esp(), *uki, !no_secureboot), compute_pcr7( secureboot_variables.efivars.as_deref(), rfs.esp(), @@ -167,13 +198,23 @@ fn main() -> Result<()> { ); Ok(()) } - Command::Pcr4 { + Command::Pcr4NoUki { rootfs, uki, no_secureboot, } => { let rfs = rootfs::RootFSTree::new(rootfs).unwrap(); - let pcr = compute_pcr4(rfs.vmlinuz(), rfs.esp(), *uki, !no_secureboot); + let pcr = compute_pcr4_no_uki(rfs.vmlinuz(), rfs.esp(), *uki, !no_secureboot); + println!("{}", serde_json::to_string_pretty(&pcr).unwrap()); + Ok(()) + } + Command::Pcr4 { + rootfs, + uki, + uki_addon, + } => { + log::debug!("{uki_addon:?}"); + let pcr = compute_pcr4(rfs.esp(), uki, uki_addon); println!("{}", serde_json::to_string_pretty(&pcr).unwrap()); Ok(()) } diff --git a/justfile b/justfile index f842cca..16d55de 100644 --- a/justfile +++ b/justfile @@ -38,6 +38,24 @@ extract-info-target-container-image: pull-target-container-image cat /etc/os-release \ > {{target_container_osinfo_path}} +run container *args: + #!/bin/bash + set -euo pipefail + cargo build --release + set -x + podman run --rm -ti \ + --security-opt label=disable \ + --mount=type=image,source={{container}},destination=/var/srv/image,rw=false \ + -v $PWD/target/release/compute-pcrs:/usr/bin/compute-pcrs \ + -v $PWD/test-data/:/var/srv/test-data \ + -v $PWD/systemd-bootx64.efi:/var/srv/image/usr/lib/bootupd/updates/EFI/fedora/grubx64.efi \ + fedora:latest \ + compute-pcrs pcr4 \ + --shim /var/srv/image/usr/lib/bootupd/updates/EFI/fedora/shimx64.efi \ + --bootloader /var/srv/image/usr/lib/bootupd/updates/EFI/fedora/grubx64.efi \ + --uki /var/srv/image/boot/EFI/Linux/6.15.10-200.fc42.x86_64.efi \ + --uki-addon /var/srv/image/boot/EFI/Linux/6.15.10-200.fc42.x86_64.efi.extra.d/ignition.addon.efi + build-container: #!/bin/bash set -euo pipefail diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 83ce228..3ea7015 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -5,6 +5,8 @@ // SPDX-License-Identifier: MIT pub use pcrs::Pcr; +use std::path::Path; + pub mod certs; mod esp; mod linux; @@ -16,8 +18,18 @@ pub mod shim; pub mod tpmevents; pub mod uefi; -pub fn compute_pcr4(kernels_dir: &str, esp_path: &str, uki: bool, secureboot: bool) -> Pcr { - let events = tpmevents::compute::pcr4_events(kernels_dir, esp_path, uki, secureboot); +pub fn authentihash(binary: &Path) -> Option { + let pe = pefile::PeFile::load_from_file(&binary.to_string_lossy(), false)?; + Some(hex::encode(pe.authenticode())) +} + +pub fn compute_pcr4_nouki(kernels_dir: &str, esp_path: &str, uki: bool, secureboot: bool) -> Pcr { + let events = tpmevents::compute::pcr4_nouki_events(kernels_dir, esp_path, uki, secureboot); + Pcr::compile_from(&events) +} + +pub fn compute_pcr4(esp_path: &str, uki: &str, uki_addons: &Vec, secureboot: bool) -> Pcr { + let events = tpmevents::compute::pcr4_uki_events(esp_path, uki, uki_addons, secureboot); Pcr::compile_from(&events) } diff --git a/lib/src/tpmevents/compute.rs b/lib/src/tpmevents/compute.rs index 2c52970..c398717 100644 --- a/lib/src/tpmevents/compute.rs +++ b/lib/src/tpmevents/compute.rs @@ -2,9 +2,11 @@ // SPDX-FileCopyrightText: Beñat Gartzia Arruabarrena // // SPDX-License-Identifier: MIT +use crate::pefile::PeFile; use lief::generic::Section; use sha2::{Digest, Sha256}; use std::collections::HashSet; +use std::path::PathBuf; use crate::esp; use crate::linux; @@ -47,7 +49,7 @@ const MODELS_MOKVARS: [TPMEventID; 3] = [ TPMEventID::Pcr14MokListTrusted, ]; -pub fn pcr4_events( +pub fn pcr4_nouki_events( kernels_dir: &str, esp_path: &str, uki: bool, @@ -101,6 +103,62 @@ pub fn pcr4_events( events } +pub fn pcr4_uki_events( + esp_path: &str, + uki: &str, + uki_addons: &Vec, + secureboot: bool, +) -> Vec { + let esp = esp::Esp::new(esp_path).unwrap(); + let mut uki_and_addons: Vec<&str> = vec![uki]; + + let ev_efi_action_hash: Vec = + Sha256::digest(b"Calling EFI Application from Boot Option").to_vec(); + let ev_separator_hash: Vec = Sha256::digest(hex::decode("00000000").unwrap()).to_vec(); + + let mut hashes: Vec<(String, Vec)> = vec![]; + hashes.push(("EV_EFI_ACTION".into(), ev_efi_action_hash)); + hashes.push(("EV_SEPARATOR".into(), ev_separator_hash)); + + let mut bins: Vec = vec![esp.shim(), esp.grub()]; + for addon in uki_and_addons { + bins.push(PeFile::load_from_file(uki, false).expect("Can't open binary")); + } + + // println!("{bins:?}"); + + let mut bin_hashes: Vec<(String, Vec)> = bins + .iter() + .map(|b| ("EV_EFI_BOOT_SERVICES_APPLICATION".into(), b.authenticode())) + .collect(); + hashes.append(&mut bin_hashes); + + // Start with 0 + let mut result = + hex::decode("0000000000000000000000000000000000000000000000000000000000000000") + .unwrap() + .to_vec(); + + for (_p, h) in &hashes { + let mut hasher = Sha256::new(); + hasher.update(result); + hasher.update(h); + result = hasher.finalize().to_vec(); + } + + Pcr { + id: 4, + value: hex::encode(result), + parts: hashes + .iter() + .map(|(p, h)| Part { + name: p.to_string(), + hash: hex::encode(h), + }) + .collect(), + } +} + pub fn pcr7_events(efivars_path: &str, esp_path: &str, secureboot_enabled: bool) -> Vec { let n_pcr = 7; let sb_var_loader = From 7361fc104c29e1f3f766b0075f84f9e50f3f94cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Ravier?= Date: Wed, 24 Sep 2025 19:58:56 +0200 Subject: [PATCH 2/7] DNM: DEMO FILES From 8e3dc2240d17e97dbfebc0d9f3512ccc18660eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Wed, 22 Apr 2026 12:35:49 +0200 Subject: [PATCH 3/7] rootfs: Manage uki + addon paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some images might boot from an UKI. By default, it will be located under /boot/EFI/Linux/uki.efi in fedora images. If the user provides another path, that will preceed over it. Now, when new rootfs are created it will check if the user-provided or the default UKI exists. If it does, it will fill the uki + addon fields of the rootfs struct. Later, we can retrieve those. uki returns an Option to know if it is or not a uki image. Signed-off-by: Beñat Gartzia Arruabarrena --- lib/src/rootfs.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/lib/src/rootfs.rs b/lib/src/rootfs.rs index 20071c2..93fac8d 100644 --- a/lib/src/rootfs.rs +++ b/lib/src/rootfs.rs @@ -12,10 +12,13 @@ const RELATIVE_ESP_OLD: &str = "usr/lib/bootupd/updates/"; // From fcos-44 on shim/grub are stored in different directories // see https://fedoraproject.org/wiki/Changes/BootLoaderUpdatesPhase1 const RELATIVE_ESP_NEW: &str = "usr/lib/efi"; +const RELATIVE_DEFAULT_UKI_PATH: &str = "boot/EFI/Linux/uki.efi"; pub struct RootFSTree { esp_path: String, kernels_path: String, + uki_path: Option, + uki_addons: Vec, } fn esp_path_absolute(rootfs_path: &path::Path) -> io::Result { @@ -26,14 +29,58 @@ fn esp_path_absolute(rootfs_path: &path::Path) -> io::Result { } } +fn uki_path_absolute(rootfs_path: &path::Path, uki: &str) -> io::Result> { + let relative_uki_path = if uki.is_empty() { + RELATIVE_DEFAULT_UKI_PATH + } else { + uki + }; + + let temptative = rootfs_path.join(relative_uki_path); + if fs::exists(&temptative)? { + return Ok(Some(temptative.to_str().unwrap().into())); + } + Ok(None) +} + +fn uki_addons_absolute( + rootfs_path: &path::Path, + uki_addons: Vec, +) -> io::Result> { + let mut absolute_addon_paths = vec![]; + for addon in uki_addons.iter() { + let temptative = rootfs_path.join(addon); + if !fs::exists(&temptative)? { + return Err(io::Error::new( + io::ErrorKind::NotFound, + format!("Couldn't find uki addon {temptative:?}"), + )); + } + absolute_addon_paths.push(temptative.to_str().unwrap().into()) + } + + Ok(absolute_addon_paths) +} + impl RootFSTree { - pub fn new(rootfs_path: &str) -> io::Result { + pub fn new(rootfs_path: &str, uki: &str, uki_addons: Vec) -> io::Result { let rootfs_path = path::absolute(rootfs_path)?; let kernels_path = rootfs_path.join(RELATIVE_KERNELS_PATH); let esp_path = esp_path_absolute(&rootfs_path)?; + + let uki_path = uki_path_absolute(&rootfs_path, uki)?; + if uki_path.is_none() && !uki_addons.is_empty() { + return Err(io::Error::other( + "uki addons were provided but a valid uki is not found", + )); + } + let uki_addons_paths = uki_addons_absolute(&rootfs_path, uki_addons)?; + Ok(RootFSTree { esp_path: esp_path.to_str().unwrap().into(), kernels_path: kernels_path.to_str().unwrap().into(), + uki_path, + uki_addons: uki_addons_paths, }) } @@ -44,4 +91,12 @@ impl RootFSTree { pub fn vmlinuz(&self) -> &str { self.kernels_path.as_str() } + + pub fn uki(&self) -> Option<&String> { + self.uki_path.as_ref() + } + + pub fn uki_addons(&self) -> &Vec { + self.uki_addons.as_ref() + } } From a7d6801dcf77bbdc8b5088bc7ba1ddee2722eba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Wed, 22 Apr 2026 12:40:57 +0200 Subject: [PATCH 4/7] tpmevents: TPMEventIDs for uki-related events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Beñat Gartzia Arruabarrena --- lib/src/tpmevents.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/src/tpmevents.rs b/lib/src/tpmevents.rs index a188d52..5070cc1 100644 --- a/lib/src/tpmevents.rs +++ b/lib/src/tpmevents.rs @@ -28,6 +28,8 @@ pub enum TPMEventID { Pcr4Separator, Pcr4Shim, Pcr4Grub, + Pcr4Uki, + Pcr4UkiAddon, Pcr4Vmlinuz, Pcr7SecureBoot, Pcr7Pk, @@ -66,6 +68,8 @@ impl TPMEventID { TPMEventID::Pcr4Separator => TPMEG_NEVER, TPMEventID::Pcr4Shim => TPMEG_BOOTLOADER, TPMEventID::Pcr4Grub => TPMEG_BOOTLOADER, + TPMEventID::Pcr4Uki => TPMEG_UKI, + TPMEventID::Pcr4UkiAddon => TPMEG_UKI, TPMEventID::Pcr4Vmlinuz => TPMEG_LINUX, TPMEventID::Pcr7SecureBoot => TPMEG_SECUREBOOT, TPMEventID::Pcr7Pk => TPMEG_SECUREBOOT, From 8feed2753bad692bd1213b2438feb2c2c02c0824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Wed, 22 Apr 2026 12:44:37 +0200 Subject: [PATCH 5/7] tpmevents, pcr4: Merge uki+nonuki logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PCR computation for PCR4 with uki or without it was not so different. The only thing that changes is part related to vmlinuz or the UKI. Merge both of them, as we can know which of the cases we are dealing with easily, based on whether the UKI was found in the expected path or not. Signed-off-by: Beñat Gartzia Arruabarrena --- lib/src/tpmevents/compute.rs | 93 +++++++++++++----------------------- 1 file changed, 32 insertions(+), 61 deletions(-) diff --git a/lib/src/tpmevents/compute.rs b/lib/src/tpmevents/compute.rs index c398717..6786f44 100644 --- a/lib/src/tpmevents/compute.rs +++ b/lib/src/tpmevents/compute.rs @@ -6,7 +6,6 @@ use crate::pefile::PeFile; use lief::generic::Section; use sha2::{Digest, Sha256}; use std::collections::HashSet; -use std::path::PathBuf; use crate::esp; use crate::linux; @@ -49,10 +48,11 @@ const MODELS_MOKVARS: [TPMEventID; 3] = [ TPMEventID::Pcr14MokListTrusted, ]; -pub fn pcr4_nouki_events( +pub fn pcr4_events( kernels_dir: &str, esp_path: &str, - uki: bool, + uki_path: Option<&String>, + uki_addons: &[String], secureboot: bool, ) -> Vec { let mut events: Vec = vec![]; @@ -90,7 +90,35 @@ pub fn pcr4_nouki_events( id: TPMEventID::Pcr4Grub, }); - if secureboot && !uki { + if let Some(uki) = uki_path { + events.push(TPMEvent { + name: "EV_EFI_BOOT_SERVICES_APPLICATION".into(), + pcr: n_pcr, + hash: PeFile::load_from_file(uki, false) + .expect("Can't open binary") + .authenticode(), + id: TPMEventID::Pcr4Uki, + }); + events.extend(uki_addons.iter().map(|addon| { + TPMEvent { + name: "EV_EFI_BOOT_SERVICES_APPLICATION".into(), + pcr: n_pcr, + hash: PeFile::load_from_file(addon, false) + .expect("Can't open binary") + .authenticode(), + id: TPMEventID::Pcr4UkiAddon, + } + })); + + if !secureboot { + events.push(TPMEvent { + name: "EV_EFI_BOOT_SERVICES_APPLICATION".into(), + pcr: n_pcr, + hash: linux::load_vmlinuz(kernels_dir).unwrap().authenticode(), + id: TPMEventID::Pcr4Vmlinuz, + }); + } + } else if secureboot { events.push(TPMEvent { name: "EV_EFI_BOOT_SERVICES_APPLICATION".into(), pcr: n_pcr, @@ -99,66 +127,9 @@ pub fn pcr4_nouki_events( }); } - // TODO: write condition for uki and implement logic events } -pub fn pcr4_uki_events( - esp_path: &str, - uki: &str, - uki_addons: &Vec, - secureboot: bool, -) -> Vec { - let esp = esp::Esp::new(esp_path).unwrap(); - let mut uki_and_addons: Vec<&str> = vec![uki]; - - let ev_efi_action_hash: Vec = - Sha256::digest(b"Calling EFI Application from Boot Option").to_vec(); - let ev_separator_hash: Vec = Sha256::digest(hex::decode("00000000").unwrap()).to_vec(); - - let mut hashes: Vec<(String, Vec)> = vec![]; - hashes.push(("EV_EFI_ACTION".into(), ev_efi_action_hash)); - hashes.push(("EV_SEPARATOR".into(), ev_separator_hash)); - - let mut bins: Vec = vec![esp.shim(), esp.grub()]; - for addon in uki_and_addons { - bins.push(PeFile::load_from_file(uki, false).expect("Can't open binary")); - } - - // println!("{bins:?}"); - - let mut bin_hashes: Vec<(String, Vec)> = bins - .iter() - .map(|b| ("EV_EFI_BOOT_SERVICES_APPLICATION".into(), b.authenticode())) - .collect(); - hashes.append(&mut bin_hashes); - - // Start with 0 - let mut result = - hex::decode("0000000000000000000000000000000000000000000000000000000000000000") - .unwrap() - .to_vec(); - - for (_p, h) in &hashes { - let mut hasher = Sha256::new(); - hasher.update(result); - hasher.update(h); - result = hasher.finalize().to_vec(); - } - - Pcr { - id: 4, - value: hex::encode(result), - parts: hashes - .iter() - .map(|(p, h)| Part { - name: p.to_string(), - hash: hex::encode(h), - }) - .collect(), - } -} - pub fn pcr7_events(efivars_path: &str, esp_path: &str, secureboot_enabled: bool) -> Vec { let n_pcr = 7; let sb_var_loader = From 8c4801f1a557fa191eb6d9d5aad9c2b82ab7b748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Wed, 22 Apr 2026 12:46:18 +0200 Subject: [PATCH 6/7] lib: Update compute_pcr4 interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Admit paths to the UKI and its addons. Signed-off-by: Beñat Gartzia Arruabarrena --- lib/src/lib.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 3ea7015..6aa68a3 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -23,14 +23,20 @@ pub fn authentihash(binary: &Path) -> Option { Some(hex::encode(pe.authenticode())) } -pub fn compute_pcr4_nouki(kernels_dir: &str, esp_path: &str, uki: bool, secureboot: bool) -> Pcr { - let events = tpmevents::compute::pcr4_nouki_events(kernels_dir, esp_path, uki, secureboot); - Pcr::compile_from(&events) -} - -pub fn compute_pcr4(esp_path: &str, uki: &str, uki_addons: &Vec, secureboot: bool) -> Pcr { - let events = tpmevents::compute::pcr4_uki_events(esp_path, uki, uki_addons, secureboot); - Pcr::compile_from(&events) +pub fn compute_pcr4( + kernels_dir: &str, + esp_path: &str, + uki: Option<&String>, + uki_addons: &[String], + secureboot: bool, +) -> Pcr { + Pcr::compile_from(&tpmevents::compute::pcr4_events( + kernels_dir, + esp_path, + uki, + uki_addons, + secureboot, + )) } pub fn compute_pcr11(uki: &str) -> Pcr { From ec70b84714ca3e684f7dc484d4dc8f7df0a58b39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Be=C3=B1at=20Gartzia=20Arruabarrena?= Date: Wed, 22 Apr 2026 12:48:10 +0200 Subject: [PATCH 7/7] cli: compute PCR4 for uki images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now users can pass uki and uki addons paths to the compute-pcrs binary. Now, the binary will assume that it is predicting PCRs for an UKI image. It will try to find the UKI image in the path provided by the user. If it was not provided, it will try finding it in the default path. It it was not found even there, then it will assume it is the legacy case and will compute pcr4 as it was done until now. Signed-off-by: Beñat Gartzia Arruabarrena --- cli/src/main.rs | 86 ++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index c6b40d4..76ef5be 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -56,10 +56,16 @@ enum Command { secureboot_variables: SecureBootVarStores, #[arg( long, - default_value_t = false, - help = "Indicates that the linux image is an UKI image (e.g. is not vmlinuz))" + short, + default_value = "", + help = "Path to the UKI binary. It will try to find it in ${rootfs}/boot/EFI/Linux/uki.efi by default." + )] + uki: String, + #[arg( + long, + help = "Path to a UKI addon relative to the root dir. It can be passed multiple times." )] - uki: bool, + uki_addon: Vec, #[arg( long = "secureboot-disabled", default_value_t = false, @@ -73,8 +79,13 @@ enum Command { )] mok_variables: String, }, - /// Compute PCR 4 for the non UKI case - Pcr4NoUki { + /// Compute PCR 4 + /// + /// It will try to find the UKI in the user-provided path. If empty, + /// it will assume the default Bootable Container UKI path: + /// ${rootfs}/boot/EFI/Linux/uki.efi. + /// If not found, it will then assume that it is the non UKI case. + Pcr4 { #[arg( long, short, @@ -84,10 +95,16 @@ enum Command { rootfs: String, #[arg( long, - default_value_t = false, - help = "Indicates that the linux image is an UKI image (e.g. is not vmlinuz))" + short, + default_value = "", + help = "Path to the UKI binary. It will try to find it in ${rootfs}/boot/EFI/Linux/uki.efi by default." )] - uki: bool, + uki: String, + #[arg( + long, + help = "Path to a UKI addon relative to the root dir. It can be passed multiple times." + )] + uki_addon: Vec, #[arg( long = "secureboot-disabled", default_value_t = false, @@ -95,25 +112,6 @@ enum Command { )] no_secureboot: bool, }, - /// Compute PCR 4 for the Bootable Container UKI case - Pcr4 { - #[arg( - long, - short, - default_value = "/", - help = "Path to the target container image root filesystem" - )] - rootfs: String, - #[arg( - long, - short, - default_value = "/boot/EFI/Linux/uki.efi", - help = "Path to the UKI binary" - )] - uki: String, - #[arg(long, help = "Path to a UKI addon (can be passed multiple times)")] - uki_addon: Vec, - }, /// Compute PCR 7 Pcr7 { #[arg( @@ -178,12 +176,19 @@ fn main() -> Result<()> { rootfs, secureboot_variables, uki, + uki_addon, no_secureboot, mok_variables, } => { - let rfs = rootfs::RootFSTree::new(rootfs).unwrap(); + let rfs = rootfs::RootFSTree::new(rootfs, uki, uki_addon.clone()).unwrap(); let pcrs = vec![ - compute_pcr4_nouki(rfs.vmlinuz(), rfs.esp(), *uki, !no_secureboot), + compute_pcr4( + rfs.vmlinuz(), + rfs.esp(), + rfs.uki(), + rfs.uki_addons(), + !no_secureboot, + ), compute_pcr7( secureboot_variables.efivars.as_deref(), rfs.esp(), @@ -198,23 +203,22 @@ fn main() -> Result<()> { ); Ok(()) } - Command::Pcr4NoUki { - rootfs, - uki, - no_secureboot, - } => { - let rfs = rootfs::RootFSTree::new(rootfs).unwrap(); - let pcr = compute_pcr4_no_uki(rfs.vmlinuz(), rfs.esp(), *uki, !no_secureboot); - println!("{}", serde_json::to_string_pretty(&pcr).unwrap()); - Ok(()) - } Command::Pcr4 { rootfs, uki, uki_addon, + no_secureboot, } => { log::debug!("{uki_addon:?}"); - let pcr = compute_pcr4(rfs.esp(), uki, uki_addon); + let rfs = rootfs::RootFSTree::new(rootfs, uki, uki_addon.clone()).unwrap(); + let pcr = compute_pcr4( + rfs.vmlinuz(), + rfs.esp(), + rfs.uki(), + rfs.uki_addons(), + !no_secureboot, + ); + println!("{}", serde_json::to_string_pretty(&pcr).unwrap()); Ok(()) } @@ -223,7 +227,7 @@ fn main() -> Result<()> { secureboot_variables, no_secureboot, } => { - let rfs = rootfs::RootFSTree::new(rootfs).unwrap(); + let rfs = rootfs::RootFSTree::new(rootfs, "", vec![]).unwrap(); let pcr = compute_pcr7( secureboot_variables.efivars.as_deref(), rfs.esp(),