From 6f0a823e81401c1b7735cbb55252427d6d9ba0c1 Mon Sep 17 00:00:00 2001 From: Zach Halvorsen Date: Thu, 9 Jan 2025 20:53:31 +0000 Subject: [PATCH] Update image-builder to output a hashes file. This can be useful for offline/external signing to extract the digests for an image bundle to be passed to the signing interface. The output is a JSON file with the vendor and owner hashes tagged with their respective names. This was tested by printing the hash from the ROM in the smoke tests to ensure the calculated hash is the same for both the firmware and tool. --- Cargo.lock | 3 +++ builder/Cargo.toml | 3 +++ builder/bin/image_gen.rs | 31 ++++++++++++++++++++++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 96c8367ee7..43616f22f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -283,8 +283,11 @@ dependencies = [ "clap", "elf", "hex", + "memoffset 0.8.0", "nix 0.26.2", "once_cell", + "serde_json", + "sha2", "zerocopy", ] diff --git a/builder/Cargo.toml b/builder/Cargo.toml index bac1a4732a..72c8180399 100644 --- a/builder/Cargo.toml +++ b/builder/Cargo.toml @@ -17,8 +17,11 @@ caliptra-image-types.workspace = true clap.workspace = true elf.workspace = true hex.workspace = true +memoffset.workspace = true nix.workspace = true once_cell.workspace = true +serde_json.workspace = true +sha2.workspace = true zerocopy.workspace = true [features] diff --git a/builder/bin/image_gen.rs b/builder/bin/image_gen.rs index 45c72639dd..6f93a466aa 100644 --- a/builder/bin/image_gen.rs +++ b/builder/bin/image_gen.rs @@ -3,7 +3,12 @@ use caliptra_builder::firmware; use caliptra_builder::version; use caliptra_builder::ImageOptions; +use caliptra_image_types::ImageHeader; +use caliptra_image_types::ImageManifest; use clap::{arg, value_parser, Command}; +use memoffset::{offset_of, span_of}; +use serde_json::{json, to_string_pretty}; +use sha2::{Digest, Sha384}; use std::collections::HashSet; use std::path::PathBuf; @@ -33,6 +38,10 @@ fn main() { ) .arg(arg!(--"fake-rom" [FILE] "Fake ROM").value_parser(value_parser!(PathBuf))) .arg(arg!(--"fake-fw" [FILE] "Fake FW bundle image").value_parser(value_parser!(PathBuf))) + .arg( + arg!(--"hashes" [FILE] "File path for output JSON file containing image bundle header hashes for external signing tools") + .value_parser(value_parser!(PathBuf)), + ) .get_matches(); if let Some(path) = args.get_one::("rom-no-log") { @@ -75,7 +84,27 @@ fn main() { }, ) .unwrap(); - std::fs::write(path, image.to_bytes().unwrap()).unwrap(); + + let contents = image.to_bytes().unwrap(); + std::fs::write(path, contents.clone()).unwrap(); + + if let Some(path) = args.get_one::("hashes") { + let header_range = span_of!(ImageManifest, header); + + // Get the vendor digest which is taken from a subset of the header + let vendor_header_len = offset_of!(ImageHeader, owner_data); + let vendor_range = header_range.start..header_range.start + vendor_header_len; + let vendor_digest = Sha384::digest(&contents[vendor_range]); + + // Get the owner digest which is the full header + let owner_digest = Sha384::digest(&contents[header_range]); + + let json = json!({ + "vendor": format!("{vendor_digest:02x}"), + "owner": format!("{owner_digest:02x}"), + }); + std::fs::write(path, to_string_pretty(&json).unwrap()).unwrap(); + } } if let Some(path) = args.get_one::("fake-fw") {