lanzatool: sign and copy in one step)

This commit is contained in:
nikstur 2022-11-26 15:32:43 +01:00
parent 240c80368f
commit c441f5157e
2 changed files with 27 additions and 37 deletions

View File

@ -104,45 +104,31 @@ impl Installer {
let wrapped_initrd = pe::wrap_initrd(&secure_temp_dir, &self.initrd_stub, &initrd_location) let wrapped_initrd = pe::wrap_initrd(&secure_temp_dir, &self.initrd_stub, &initrd_location)
.context("Failed to assemble stub")?; .context("Failed to assemble stub")?;
println!("Copy files to EFI system partition..."); println!("Sign and copy files to EFI system partition...");
let signer = Signer::new(&self.public_key, &self.private_key);
let systemd_boot = bootspec_doc let systemd_boot = bootspec_doc
.extension .extension
.systemd .systemd
.join("lib/systemd/boot/efi/systemd-bootx64.efi"); .join("lib/systemd/boot/efi/systemd-bootx64.efi");
let files_to_copy = [ let files_to_copy_and_sign = [
(bootspec_doc.kernel, &esp_paths.kernel), (&systemd_boot, &esp_paths.efi_fallback),
(wrapped_initrd, &esp_paths.initrd), (&systemd_boot, &esp_paths.systemd_boot),
(lanzaboote_image, &esp_paths.lanzaboote_image), (&lanzaboote_image, &esp_paths.lanzaboote_image),
(systemd_boot.clone(), &esp_paths.efi_fallback), (&bootspec_doc.kernel, &esp_paths.kernel),
(systemd_boot, &esp_paths.systemd_boot), (&wrapped_initrd, &esp_paths.initrd),
]; ];
for (source, target) in files_to_copy { for (from, to) in files_to_copy_and_sign {
copy(&source, &target)?; println!("Signing {}...", to.display());
}
// TODO: we should implement sign_and_copy which would be secure ensure_parent_dir(to);
// by construction for TOCTOU. signer.sign_and_copy(&from, &to).with_context(|| {
format!("Failed to copy and sign file from {:?} to {:?}", from, to)
println!("Signing files..."); })?;
// Call sync to improve the likelihood that file is actually written to disk
let signer = Signer::new(&self.public_key, &self.private_key);
let files_to_sign = [
&esp_paths.efi_fallback,
&esp_paths.systemd_boot,
&esp_paths.lanzaboote_image,
&esp_paths.kernel,
&esp_paths.initrd,
];
for file in files_to_sign {
println!("Signing {}...", file.display());
signer
.sign_file(&file)
.with_context(|| format!("Failed to sign file {}", &file.display()))?;
sync(); sync();
} }
@ -185,10 +171,7 @@ fn assemble_kernel_cmdline(init: PathBuf, kernel_params: Vec<String>) -> Vec<Str
} }
fn copy(from: &Path, to: &Path) -> Result<()> { fn copy(from: &Path, to: &Path) -> Result<()> {
match to.parent() { ensure_parent_dir(to);
Some(parent) => fs::create_dir_all(parent).unwrap_or(()),
_ => (),
};
fs::copy(from, to) fs::copy(from, to)
.with_context(|| format!("Failed to copy from {} to {}", from.display(), to.display()))?; .with_context(|| format!("Failed to copy from {} to {}", from.display(), to.display()))?;
@ -202,3 +185,10 @@ fn copy(from: &Path, to: &Path) -> Result<()> {
Ok(()) Ok(())
} }
// Ensures the parent directory of an arbitrary path exists
fn ensure_parent_dir(path: &Path) {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).ok();
}
}

View File

@ -18,15 +18,15 @@ impl Signer {
} }
} }
pub fn sign_file(&self, filepath: &Path) -> Result<()> { pub fn sign_and_copy(&self, from: &Path, to: &Path) -> Result<()> {
let args = vec![ let args = vec![
String::from("--key"), String::from("--key"),
utils::path_to_string(&self.private_key), utils::path_to_string(&self.private_key),
String::from("--cert"), String::from("--cert"),
utils::path_to_string(&self.public_key), utils::path_to_string(&self.public_key),
utils::path_to_string(filepath), utils::path_to_string(from),
String::from("--output"), String::from("--output"),
utils::path_to_string(filepath), utils::path_to_string(to),
]; ];
let status = Command::new("sbsign").args(&args).status()?; let status = Command::new("sbsign").args(&args).status()?;